From 45e023371599238d8c862641b7c2e42cb0fc6c2a Mon Sep 17 00:00:00 2001 From: romaric-g Date: Wed, 19 May 2021 07:53:08 +0200 Subject: [PATCH 1/8] doc --- requirements-docs.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/requirements-docs.txt b/requirements-docs.txt index 1436c2fc..aa6ae1f1 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,2 +1,13 @@ Sphinx==1.6.5 sphinx_rtd_theme==0.2.5b1 +sphinx-jsonschema==1.16.8 +sphinxcontrib-applehelp==1.0.2 +sphinxcontrib-devhelp==1.0.2 +sphinxcontrib-htmlhelp==1.0.3 +sphinxcontrib-httpdomain==1.7.0 +sphinxcontrib-httpexample==0.11.0 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==1.0.3 +sphinxcontrib-serializinghtml==1.1.4 +urllib3==1.26.4 +Werkzeug==2.0.0 \ No newline at end of file From e8edcc4db8fc584444d75a2f6302f4ab49c116ad Mon Sep 17 00:00:00 2001 From: romaric-g Date: Wed, 19 May 2021 07:55:43 +0200 Subject: [PATCH 2/8] oups deja fait --- requirements-docs.txt | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index aa6ae1f1..1436c2fc 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,13 +1,2 @@ Sphinx==1.6.5 sphinx_rtd_theme==0.2.5b1 -sphinx-jsonschema==1.16.8 -sphinxcontrib-applehelp==1.0.2 -sphinxcontrib-devhelp==1.0.2 -sphinxcontrib-htmlhelp==1.0.3 -sphinxcontrib-httpdomain==1.7.0 -sphinxcontrib-httpexample==0.11.0 -sphinxcontrib-jsmath==1.0.1 -sphinxcontrib-qthelp==1.0.3 -sphinxcontrib-serializinghtml==1.1.4 -urllib3==1.26.4 -Werkzeug==2.0.0 \ No newline at end of file From 4387a7dccefde867689aabbaaf2f240030d24eb4 Mon Sep 17 00:00:00 2001 From: romaric-g Date: Wed, 19 May 2021 11:18:50 +0200 Subject: [PATCH 3/8] formulaire requete --- web_app/build/asset-manifest.json | 6 +- web_app/build/index.html | 2 +- .../build/static/js/main.755d67ad.chunk.js | 2 - .../static/js/main.755d67ad.chunk.js.map | 1 - .../build/static/js/main.88ea6b9f.chunk.js | 2 + .../static/js/main.88ea6b9f.chunk.js.map | 1 + web_app/src/pages/Requests.js | 106 ++++++++++++------ web_app/src/pages/icon.js | 58 ++++++++++ 8 files changed, 137 insertions(+), 41 deletions(-) delete mode 100644 web_app/build/static/js/main.755d67ad.chunk.js delete mode 100644 web_app/build/static/js/main.755d67ad.chunk.js.map create mode 100644 web_app/build/static/js/main.88ea6b9f.chunk.js create mode 100644 web_app/build/static/js/main.88ea6b9f.chunk.js.map create mode 100644 web_app/src/pages/icon.js diff --git a/web_app/build/asset-manifest.json b/web_app/build/asset-manifest.json index d9fb3c48..c02333fd 100644 --- a/web_app/build/asset-manifest.json +++ b/web_app/build/asset-manifest.json @@ -1,8 +1,8 @@ { "files": { "main.css": "/app/static/css/main.fd5c3e28.chunk.css", - "main.js": "/app/static/js/main.755d67ad.chunk.js", - "main.js.map": "/app/static/js/main.755d67ad.chunk.js.map", + "main.js": "/app/static/js/main.88ea6b9f.chunk.js", + "main.js.map": "/app/static/js/main.88ea6b9f.chunk.js.map", "runtime-main.js": "/app/static/js/runtime-main.f6be42b7.js", "runtime-main.js.map": "/app/static/js/runtime-main.f6be42b7.js.map", "static/js/2.3af01b63.chunk.js": "/app/static/js/2.3af01b63.chunk.js", @@ -15,6 +15,6 @@ "static/js/runtime-main.f6be42b7.js", "static/js/2.3af01b63.chunk.js", "static/css/main.fd5c3e28.chunk.css", - "static/js/main.755d67ad.chunk.js" + "static/js/main.88ea6b9f.chunk.js" ] } \ No newline at end of file diff --git a/web_app/build/index.html b/web_app/build/index.html index 9ab4a3b8..3486ede3 100644 --- a/web_app/build/index.html +++ b/web_app/build/index.html @@ -1 +1 @@ -Request App
\ No newline at end of file +Request App
\ No newline at end of file diff --git a/web_app/build/static/js/main.755d67ad.chunk.js b/web_app/build/static/js/main.755d67ad.chunk.js deleted file mode 100644 index 2f2b6aba..00000000 --- a/web_app/build/static/js/main.755d67ad.chunk.js +++ /dev/null @@ -1,2 +0,0 @@ -(this.webpackJsonprequest_app=this.webpackJsonprequest_app||[]).push([[0],{31:function(e,t,s){},32:function(e,t,s){"use strict";s.r(t);var n=s(1),c=s.n(n),a=s(19),r=s.n(a),l=s(5),i=s(2),o=s(17),d=s(4),j=s(0),b={p2n_family:{name:"p2n family",description:"run family data acquisition"},p2n_image:{name:"p2n images",description:"Fetch images"},p2n_network:{name:"p2n networks",description:"Build various artefacts for data exploration based on network graphs"},p2n_freeplane:{name:"p2n freeplane",description:"Build mind map for Freeplane"},p2n_bibfile:{name:"p2n bibfile",description:"Export data in bibfile format"},p2n_map:{name:"p2n maps",description:"Build maps of country coverage of patents, as well as applicants and inventors"},p2n_tables:{name:"p2n tables",description:"Export various artefacts for tabular data exploration"},p2n_carrot:{name:"p2n carrot",description:"Export data to XML suitable for using in Carro"},p2n_iramuteq:{name:"p2n iramuteq",description:"Fetch more data and export it to suitable format for using in Iramuteq"},p2n_cluster:{name:"p2n cluster",description:"Double clustering system based on non so trivial words"}};var x=function(){var e=c.a.useState(""),t=Object(d.a)(e,2),s=t[0],n=t[1],a=c.a.useState(""),r=Object(d.a)(a,2),x=r[0],h=r[1],u=c.a.useState(["p2n_content","p2n_gather_biblio","p2n_family","p2n_image","p2n_network","p2n_freeplane","p2n_bibfile","p2n_map","p2n_tables","p2n_carrot","p2n_iramuteq","p2n_cluster"]),m=Object(d.a)(u,2),p=m[0],f=m[1],O=c.a.useState({}),g=Object(d.a)(O,2),w=g[0],v=g[1],N=c.a.useState(!1),y=Object(d.a)(N,2),k=y[0],_=y[1],C=Object(i.f)();c.a.useEffect((function(){fetch("http://localhost:5000/api/v1/requests").then((function(e){return e.json()})).then((function(e){e.data&&v(e.data),console.log(e.data)}))}),[]);var q=c.a.useCallback((function(e){f((function(t){return t.includes(e)?Object(o.a)(t.filter((function(t){return t!==e}))):[].concat(Object(o.a)(t),[e])}))}),[f]),P=c.a.useCallback((function(e){e.preventDefault();var t=new FormData;t.append("p2n_req",s),t.append("p2n_dir",x),t.append("p2n_options",p.join(",")),t.append("p2n_auto",k?"true":"false"),console.log(t),fetch("http://localhost:5000/api/v1/requests",{method:"POST",body:t}).then((function(e){return e.json()})).then((function(e){console.log(e),C.push("/app/requests/"+e.data.p2n_dir)}))}),[s,x,p,C,k]);return Object(j.jsxs)("div",{className:"container mx-auto grid grid-cols-4 gap-4 items-start",children:[Object(j.jsxs)("div",{className:"col-start-1 bg-white p-8 rounded shadow",children:[Object(j.jsxs)("div",{className:"mb-6 flex flex-col",children:[Object(j.jsx)("h3",{className:"text-lg mb-2 font-bold",children:"Requ\xeates pr\xe9c\xe9dentes"}),w.done&&w.done.map((function(e){return Object(j.jsx)(l.b,{to:"/app/requests/"+e,children:e},e)})),!w.done&&Object(j.jsxs)("div",{className:"grid grid-cols-1 gap-2",children:[Object(j.jsx)("span",{className:"skeleton-box h-5 w-3/5 inline-block"}),Object(j.jsx)("span",{className:"skeleton-box h-5 w-1/2 inline-block"}),Object(j.jsx)("span",{className:"skeleton-box h-5 w-2/5 inline-block"})]})]}),Object(j.jsx)("hr",{class:"mb-3"}),Object(j.jsxs)("div",{class:"mb-6 flex flex-col",children:[Object(j.jsx)("h3",{className:"text-lg mb-2 font-bold",children:"Requ\xeates en cours"}),Object(j.jsx)("div",{className:"",children:Object(j.jsxs)("div",{className:"relative pt-1",children:[w.in_progress&&w.in_progress.map((function(e){return Object(j.jsxs)(l.b,{to:"/app/requests/"+e,children:[Object(j.jsx)("p",{class:"mb-1",children:e}),w.global_progress&&w.global_progress[e]&&Object(j.jsxs)("div",{className:"overflow-hidden h-2 mb-4 text-xs flex rounded bg-orange-200",children:[Object(j.jsx)("div",{style:{width:w.global_progress[e].done_step_count/w.global_progress[e].total_step_count*100+"%"},className:"shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-indigo-500"}),Object(j.jsx)("div",{style:{width:w.global_progress[e].progress_step_count/w.global_progress[e].total_step_count*100+"%"},className:"shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-orange-300"})]})]},e)})),!w.in_progress&&Object(j.jsxs)("div",{className:"grid grid-cols-1 gap-2",children:[Object(j.jsx)("span",{className:"skeleton-box h-5 w-3/5 inline-block"}),Object(j.jsx)("span",{className:"skeleton-box h-5 w-1/2 inline-block"}),Object(j.jsx)("span",{className:"skeleton-box h-5 w-2/5 inline-block"})]})]})})]})]}),Object(j.jsxs)("div",{className:"col-span-3 flex flex-col mb-12 bg-white p-8 rounded shadow ",children:[Object(j.jsx)("h1",{className:"text-3xl font-semibold mb-2 text-gray-900",children:"Patent2Net toolkit"}),Object(j.jsx)("hr",{}),Object(j.jsx)("div",{className:"mt-4",children:Object(j.jsxs)("form",{onSubmit:P,children:[Object(j.jsxs)("div",{children:[Object(j.jsx)("label",{className:"font-semibold",children:"Request in CQL format * :"}),Object(j.jsx)("p",{className:"pt-2 pb-2 text-sm italic text-gray-800",children:"Enter in the textbox a valid espacenet smart search query for your patent research."})]}),Object(j.jsx)("div",{className:"mb-2",children:Object(j.jsx)("input",{value:s,onChange:function(e){return n(e.target.value)},className:"px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border border-blueGray-300 outline-none focus:outline-none focus:ring w-full",type:"text",required:!0,placeholder:"TA=lentille",name:"p2n_req",id:"p2n_reqBtn"})}),Object(j.jsxs)("div",{children:[Object(j.jsx)("label",{className:"font-semibold",children:"Request Location * :"}),Object(j.jsx)("p",{className:"pt-2 pb-2 text-sm italic text-gray-800",children:"Enter in the textbox where your patent research will be stocked."})]}),Object(j.jsx)("div",{className:"mb-2",children:Object(j.jsx)("input",{value:x,onChange:function(e){return h(e.target.value)},className:"px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border border-blueGray-300 outline-none focus:outline-none focus:ring w-full",type:"text",required:!0,placeholder:"lentille",name:"p2n_dir",pattern:"[A-Za-z0-9_-]{1,}",title:"Use only lowercase [a-z], Uppercase [A-Z], Numbers[0-9], Underscore[_] and Hyphen [-]"})}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("label",{className:"font-semibold",children:"Request Options :"}),Object(j.jsx)("p",{className:"pt-2 pb-2 text-sm italic text-gray-800",children:"Click on the checkbox to specify the elements you need in your research:"}),Object.keys(b).map((function(e,t){var s=b[e];return Object(j.jsxs)("p",{children:[Object(j.jsx)("input",{type:"checkbox",id:e,name:e,checked:p.includes(e),onChange:function(){return q(e)}}),Object(j.jsxs)("label",{htmlFor:e,className:"text-gray-800 text-sm mb-4 text-justify",children:[Object(j.jsx)("b",{children:s.name}),": ",s.description," "]})]},e)}))]}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("label",{className:"font-semibold",children:"Use auto request splitter:"}),Object(j.jsx)("input",{type:"checkbox",name:"p2n_auto",checked:k,onChange:function(){return _(!k)}})]}),Object(j.jsx)("div",{className:"mt-4 italic text-sm text-gray-800",children:"Fields marked with * are mandatory."}),Object(j.jsx)("input",{className:"w-64 focus:outline-none px-8 py-2 rounded-md font-semibold text-white bg-indigo-500 cursor-pointer mt-4",type:"submit",value:"Submit"})]})})]})]})},h=function(e){var t=e.fusion_list;return Object(j.jsx)("div",{className:"mt-4 p-4 border border-gray-200 rounded",children:Object(j.jsxs)("div",{className:"flex flex-row justify-between items-center",children:[Object(j.jsxs)("p",{className:"font-semibold mr-3",children:[!t.start&&!t.end&&"La fusion des donn\xe9es va commencer",t.start&&!t.end&&"Les donn\xe9es sont en cours de fusion",t.end&&"La fusion des donn\xe9es est termin\xe9"]}),!t.end&&Object(j.jsxs)("svg",{className:"animate-spin -ml-1 h-5 w-5 text-indigo-600",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})]})})},u=function(e){var t=e.dir,s=e.data,n=e.showLoading,a=c.a.useState(!1),r=Object(d.a)(a,2),i=r[0],o=r[1],b=c.a.useCallback((function(){o(!0),fetch("http://localhost:5000/api/v1/requests/"+t+"/interface",{method:"POST"}).then((function(e){return e.json()})).then((function(e){o(!1)}))}),[t]);return Object(j.jsxs)("div",{className:"pb-4 flex justify-between",children:[Object(j.jsxs)("div",{className:"flex items-center",children:[Object(j.jsx)(l.b,{to:"/app/requests",className:"focus:outline-none p-2 rounded-md font-semibold text-white bg-gray-600",children:Object(j.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M15 19l-7-7 7-7"})})}),Object(j.jsxs)("div",{className:"ml-4",children:[Object(j.jsx)("h1",{className:"text-3xl font-semibold leading-7",children:t}),Object(j.jsx)("h2",{className:"text-lg",children:s.cql&&s.cql.requete})]})]}),Object(j.jsxs)("div",{className:"flex items-center",children:[s.done&&Object(j.jsxs)(j.Fragment,{children:[Object(j.jsx)("button",{className:"focus:outline-none p-2 rounded-md font-semibold text-white bg-red-500 mr-2 flex justify-center items-center",onClick:b,children:i?Object(j.jsxs)("svg",{className:"animate-spin h-6 w-6 text-white",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]}):Object(j.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})})}),Object(j.jsx)("a",{target:"_blank",rel:"noreferrer",href:"/DATA/"+t+".html",className:"focus:outline-none px-8 py-2 rounded-md font-semibold text-white bg-indigo-500",children:"Voir les donn\xe9es"})]}),!s.done&&n&&Object(j.jsxs)("div",{className:"focus:outline-none px-4 py-2 rounded-md font-semibold text-white bg-indigo-400 flex justify-center items-center",children:[Object(j.jsxs)("svg",{className:"animate-spin -ml-1 mr-3 h-5 w-5 text-white",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]}),"Chargements"]})]})]})},m=function(){return Object(j.jsxs)("div",{className:"mt-4 p-4 border border-gray-200 flex flex-row justify-between rounded",children:[Object(j.jsx)("p",{children:"Verification du nombre de ressource associ\xe9 \xe0 la requete"}),Object(j.jsx)("div",{children:Object(j.jsxs)("svg",{className:"animate-spin -ml-1 h-5 w-5 text-indigo-600",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})})]})},p=(new Date).getFullYear(),f=Array.from({length:30},(function(e,t){return p-t})),O=function(e){var t=e.dir,s=e.to_be_found,n=c.a.useState(!1),a=Object(d.a)(n,2),r=a[0],l=a[1],i=c.a.useState(p),o=Object(d.a)(i,2),b=o[0],x=o[1],h=c.a.useMemo((function(){return s&&(s.amount>=1e4?"Plus de 10000":s.amount)}),[s]),u=c.a.useCallback((function(){var e=new FormData;e.append("date",b),fetch("http://localhost:5000/api/v1/requests/"+t+"/split",{method:"POST",body:e}).then((function(e){return e.json()})).then((function(e){}))}),[b,t]),m=c.a.useCallback((function(e){x(e),l(!1)}),[x]);return Object(j.jsxs)("div",{className:"mt-4 p-4 bg-indigo-600 flex flex-row justify-between rounded items-center text-white",children:[Object(j.jsxs)("div",{children:[Object(j.jsxs)("p",{className:"font-bold text-lg",children:[h," \xe9l\xe9ments ont \xe9t\xe9 trouv\xe9s"]}),Object(j.jsx)("p",{className:"text-sm",children:s.need_spliter?"\xc0 partir de quelle ann\xe9e voulez vous r\xe9cuperer les donn\xe9es ?":"Il n'est pas necessaire de d\xe9couper la requete, le traiement va bient\xf4t commencer"})]}),s.need_spliter&&Object(j.jsxs)("div",{className:"flex flex-row mt-1",children:[Object(j.jsx)("div",{className:"w-32",children:Object(j.jsx)("div",{children:Object(j.jsxs)("div",{className:"relative text-black",children:[Object(j.jsxs)("button",{type:"button",className:"relative w-full bg-white border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 font-semibold","aria-haspopup":"listbox","aria-expanded":"true","aria-labelledby":"listbox-label",onClick:function(){return l(!r)},children:[Object(j.jsx)("span",{className:"flex items-center",children:Object(j.jsx)("span",{className:"ml-3 block truncate",children:b})}),Object(j.jsx)("span",{className:"ml-3 absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none",children:Object(j.jsx)("svg",{className:"h-5 w-5 text-gray-400",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true",children:Object(j.jsx)("path",{"fill-rule":"evenodd",d:"M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z","clip-rule":"evenodd"})})})]}),Object(j.jsx)("ul",{style:{maxHeight:200},className:"absolute z-10 mt-2 w-full bg-white shadow-lg rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"+(r?" opacity-100":" transition ease-in duration-100 opacity-0"),tabindex:"-1",role:"listbox","aria-labelledby":"listbox-label","aria-activedescendant":"listbox-option-3",children:f.map((function(e){return Object(j.jsx)("li",{className:"text-gray-900 cursor-default select-none relative py-2 pl-3 pr-9",id:"listbox-option-0",role:"option",onClick:function(){return m(e)},children:Object(j.jsx)("div",{className:"flex items-center",children:Object(j.jsx)("span",{className:"font-normal ml-3 block truncate",children:e})})})}))})]})})}),Object(j.jsx)("button",{type:"button",className:"bg-green-500 ml-2 px-2 rounded","aria-label":"Suivant",onClick:function(){return u()},children:Object(j.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M17 8l4 4m0 0l-4 4m4-4H3"})})})]})]})},g=function(e){var t=e.process_list,s=e.hide_result;return Object(j.jsxs)("div",{className:"mt-4 p-4 border border-gray-200 rounded",children:[Object(j.jsxs)("div",{className:"flex flex-row justify-between items-center",children:[Object(j.jsxs)("p",{className:"font-semibold mr-3",children:[!t.start&&!t.end&&"La r\xe9cuperation des donn\xe9es va commencer",t.start&&!t.end&&"Les donn\xe9es sont en cours de r\xe9cup\xe9ration",t.end&&"La r\xe9cup\xe9ration des donn\xe9es est termin\xe9"]}),!t.end&&Object(j.jsxs)("svg",{className:"animate-spin -ml-1 h-5 w-5 text-indigo-600",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})]}),!s&&Object(j.jsxs)(j.Fragment,{children:[Object(j.jsx)("hr",{className:"border-gray-200 my-4"}),Object(j.jsx)("div",{children:t.queue_list&&t.queue_list.map((function(e){return Object(j.jsxs)("div",{className:"flex flex-row justify-between",children:[Object(j.jsx)("p",{children:e}),Object(j.jsx)("div",{children:t.done_list.includes(e)&&Object(j.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4 text-indigo-600",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"})})})]})}))})]})]})},w=function(e){var t=e.name,s=e.value,n=e.max_value,a=c.a.useMemo((function(){return s/n*100||0}),[s,n]),r=null===s||null===n?"En attente...":a+"%";return Object(j.jsxs)("div",{class:"ProgressBar",children:[Object(j.jsxs)("div",{class:"flex justify-between",children:[Object(j.jsx)("p",{children:t}),Object(j.jsx)("p",{children:r})]}),Object(j.jsx)("div",{class:"relative pt-1",children:Object(j.jsx)("div",{class:"overflow-hidden h-2 mb-4 text-xs flex rounded bg-orange-200",children:Object(j.jsx)("div",{style:{width:a+"%"},class:"shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-indigo-500"})})})]})},v=function(e){var t=e.data;return Object(j.jsxs)("div",{className:"mt-4 p-4 border border-gray-200 rounded",children:[Object(j.jsxs)("div",{className:"flex flex-row justify-between items-center",children:[Object(j.jsxs)("p",{className:"font-semibold mr-3",children:[!t.progress&&!t.done&&"La requete va bient\xf4t se lancer",t.progress&&!t.done&&"La requete est en cours",t.done&&"La requete est termin\xe9"]}),!t.done&&Object(j.jsxs)("svg",{className:"animate-spin -ml-1 h-5 w-5 text-indigo-600",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})]}),!1===t.done&&t.progress&&Object(j.jsxs)(j.Fragment,{children:[Object(j.jsx)("hr",{className:"border-gray-200 my-4"}),Object(j.jsx)("div",{children:Object.keys(t.progress).map((function(e,s){return Object(j.jsx)(w,{name:e,value:t.progress[e].value,max_value:t.progress[e].max_value},e)}))})]})]})},N=function(e){var t=e.spliter_result,s=e.hide_result;return Object(j.jsxs)("div",{className:"mt-4 p-4 border border-gray-200 rounded",children:[Object(j.jsxs)("div",{className:"flex flex-row justify-between",children:[Object(j.jsxs)("div",{className:"flex flex-row justify-between items-center",children:[Object(j.jsxs)("p",{className:"font-semibold mr-3",children:[!t.start&&!t.end&&"La s\xe9paration de la requete va commencer",t.start&&!t.end&&"S\xe9paration de la requete en cours",t.end&&"La s\xe9paration de la requete est termin\xe9"]}),!t.end&&Object(j.jsxs)("svg",{className:"animate-spin -ml-1 h-5 w-5 text-indigo-600",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})]}),Object(j.jsx)("p",{className:"font-semibold",children:t.cumulative?t.cumulative:0})]}),t.requests&&!s&&Object(j.jsxs)(j.Fragment,{children:[Object(j.jsx)("hr",{className:"border-gray-200 my-4"}),Object(j.jsx)("div",{children:t.requests&&t.requests.map((function(e){return Object(j.jsxs)("div",{className:"flex flex-row justify-between",children:[Object(j.jsx)("p",{children:e.name}),Object(j.jsx)("p",{children:e.find})]})}))})]})]})},y=function(){var e=Object(i.g)().dir,t=c.a.useState({}),s=Object(d.a)(t,2),n=s[0],a=s[1],r=c.a.useCallback((function(){fetch("http://localhost:5000/api/v1/requests/"+e).then((function(e){return e.json()})).then((function(e){200===e.code&&(console.log(e.data),a(e.data))}))}),[e]);c.a.useEffect((function(){r()}),[r]),c.a.useEffect((function(){console.log("Opening the SSE connection");var t=new EventSource("http://localhost:5000/api/v1/listen");return t.onmessage=function(t){var s=JSON.parse(t.data);console.log(s),s.data.directory===e&&r()},function(){t.close()}}),[r,e]);var l=c.a.useMemo((function(){return"SPLITER_RUN"===n.state}),[n]),o=c.a.useMemo((function(){return l&&n.data&&!n.data.to_be_found}),[n,l]),b=c.a.useMemo((function(){return l&&n.data&&n.data.spliter_result}),[n,l]),x=c.a.useMemo((function(){return l&&n.data&&n.data.to_be_found&&!b}),[n,l,b]),p=c.a.useMemo((function(){return l&&n.data&&n.data.process_list}),[n,l]),f=c.a.useMemo((function(){return l&&n.data&&n.data.fusion_list}),[n,l]),w=c.a.useMemo((function(){return x&&n.data.to_be_found}),[n,x]),y=c.a.useMemo((function(){return b&&n.data.spliter_result}),[n,b]),k=c.a.useMemo((function(){return p&&n.data.process_list}),[n,p]),_=c.a.useMemo((function(){return f&&n.data.fusion_list}),[n,f]),C=c.a.useMemo((function(){return f&&_.end}),[f,_]);return Object(j.jsx)("div",{className:"container mx-auto",children:Object(j.jsx)("div",{className:"flex justify-center items-center",children:Object(j.jsx)("div",{className:"flex flex-col w-full lg:w-3/5 mb-12 bg-white p-8 rounded shadow",children:n.cql?Object(j.jsxs)(j.Fragment,{children:[Object(j.jsx)(u,{dir:e,data:n,showLoading:!l}),Object(j.jsx)("hr",{className:"border-gray-200"}),l?Object(j.jsxs)(j.Fragment,{children:[o&&Object(j.jsx)(m,{}),x&&Object(j.jsx)(O,{dir:e,to_be_found:w}),b&&Object(j.jsx)(N,{spliter_result:y,hide_result:p}),p&&Object(j.jsx)(g,{process_list:k,hide_result:f}),f&&Object(j.jsx)(h,{fusion_list:_}),C&&Object(j.jsx)(v,{data:n})]}):Object(j.jsx)(j.Fragment,{children:Object(j.jsx)(v,{data:n})})]}):null})})})},k=function(){return Object(j.jsx)("div",{className:"container mx-auto",children:Object(j.jsx)("div",{className:"flex justify-center items-center",children:Object(j.jsxs)("div",{className:"flex flex-col w-full lg:w-3/5 mb-12 bg-white p-8 rounded shadow",children:[Object(j.jsxs)("div",{children:[Object(j.jsx)("h1",{className:"text-3xl font-semibold mb-2 text-gray-900",children:"Get Started"}),Object(j.jsx)("hr",{}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("h2",{className:"font-semibold",id:"Register",children:"Register the use of P2N"}),Object(j.jsx)("hr",{}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("p",{className:"text-gray-800 text-sm mb-4 text-justify",children:"You have first to register yourself at Espacenet and get a key to data access. So you must (if you already have it skip this step)"}),Object(j.jsxs)("ol",{className:"list-decimal text-gray-800 text-sm mb-3 text-justify",children:[Object(j.jsxs)("li",{children:["Go to the Open Patent Services (OPS) by opening the link :",Object(j.jsx)("br",{}),Object(j.jsx)("a",{className:"hover:underline",href:"https://www.epo.org/searching-for-patents/technical/espacenet/ops.html#tab1",children:" https://www.epo.org/searching-for-patents/technical/espacenet/ops.html#tab1"})]}),Object(j.jsxs)("li",{children:["Click on the \u201c",Object(j.jsx)("b",{children:"Register"}),"\u201d button and fulfill the form"]}),Object(j.jsx)("li",{children:"Wait until you receive the email confirmation of you register from EPO Developer Portal."}),Object(j.jsxs)("li",{children:["Log in the EPO Developer Portal :",Object(j.jsx)("br",{})," ",Object(j.jsx)("a",{className:"hover:underline",href:" https://developers.epo.org/user/login",children:"https://developers.epo.org/user/login"})," "]}),Object(j.jsxs)("li",{children:["Select the option \u201c",Object(j.jsx)("b",{children:"My apps"}),"\u201d"]}),Object(j.jsxs)("li",{children:["Create and register the \u201c",Object(j.jsx)("b",{children:"Patent2Net"}),"\u201d application"]}),Object(j.jsxs)("li",{children:[" The system returns the API credentials key and secret, similar to that shown bellow (this one is invalid, of course):",Object(j.jsx)("br",{}),Object(j.jsx)("pre",{className:"code border-dashed border-2 border-orange-600 bg-orange-100",children:"vmrr7AaAGIl794E6VunJ6PzjbkfajwLW,KHzH4fGM7opMhDDD"})]}),Object(j.jsx)("li",{children:"Copy/paste the key in the textbox and click on confirm. It will create a file in your install of Patent2Net who will let you have full use of it. "})]})]})]}),Object(j.jsx)("div",{className:"mt-4",children:Object(j.jsxs)("form",{action:"http://localhost:5000/get_started/stocked",method:"post",children:[Object(j.jsxs)("div",{children:[Object(j.jsx)("label",{className:"font-semibold",children:"cles-epo * :"}),Object(j.jsx)("p",{className:"pt-2 pb-2 text-sm italic text-gray-800",children:"Paste in the textbox the key provided by EPO."})]}),Object(j.jsx)("div",{className:"mb-2",children:Object(j.jsx)("input",{className:"px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border border-blueGray-300 outline-none focus:outline-none focus:ring w-full",type:"text",required:!0,placeholder:"vmrr7AaAGIl794E6VunJ6PzjbkfajwLW,KHzH4fGM7opMhDDD",name:"p2n_epo"})}),Object(j.jsx)("div",{className:"mt-4 italic text-sm text-gray-800",children:"Fields marked with * are mandatory."}),Object(j.jsx)("input",{className:"w-64 focus:outline-none px-8 py-2 rounded-md font-semibold text-white bg-indigo-500 cursor-pointer mt-4",type:"submit",value:"confirm",id:"pacing"})]})})]}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("h2",{className:"font-semibold",Id:"Archive_Content",children:"P2N Docker archive content"}),Object(j.jsx)("hr",{})]}),Object(j.jsx)("div",{className:"mt-2",children:Object(j.jsx)("div",{children:Object(j.jsxs)("ul",{className:"list-disc text-gray-800 text-sm mb-3 mt-3 text-justify ",children:[Object(j.jsxs)("li",{children:[" ",Object(j.jsx)("b",{children:"Dockerfile"})," : Mandatory for the install of P2N Docker"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Install_P2N.bat"})," : used to install all the P2N Content in Docker"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Run_P2N.bat"})," : Used to initiate P2N instance in Docker"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Stop_P2N.bat"})," : Used to stop P2N instance"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Copy Docker P2N"})," :",Object(j.jsxs)("ul",{children:[Object(j.jsx)("li",{children:"Copy_Docker_P2N.bat : Create a tar file with all the base content of your docker version"}),Object(j.jsx)("li",{children:"Load_Docker_P2N.bat : Import the tar file insde docker and create P2N image"})]})]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"P2N_Bash.bat"})," : Create a command prompt instance who interact with P2N Docker. ",Object(j.jsx)("a",{href:"https://docs.ip-tools.org/patent2net/usage/classic.html",target:"_blank",className:"hover:underline",children:Object(j.jsx)("i",{children:"Click here for more details."})})]})]})})}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("h2",{className:"font-semibold",Id:"Interface_Directory",children:"P2N Interface directories"}),Object(j.jsx)("hr",{})]}),Object(j.jsx)("div",{className:"mt-2",children:Object(j.jsx)("div",{children:Object(j.jsxs)("ul",{className:"list-disc text-gray-800 text-sm mb-3 mt-3 text-justify ",children:[Object(j.jsxs)("li",{children:[" ",Object(j.jsx)("b",{children:" Home"})," : Default page. Explain how PatentNet can help you"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Get Started"})," : Explain how to use P2N Docker"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Requests"})," : form used to execute requests to the EPO database "]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Index"})," : Display all the results of P2N "]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Download Data"})," : create a zip folder with all the datas contained in Index. Downloaded on your local machine"]})]})})})]})})})},_=(s(31),function(e){var t=e.version,s=c.a.useState(!1),n=Object(d.a)(s,2),a=n[0],r=n[1],l=c.a.useCallback((function(){r(!0),fetch("http://localhost:5000/updateP2N").then((function(e){r(!1)}))}),[]);return Object(j.jsx)("div",{className:"container mx-auto",children:Object(j.jsx)("div",{className:"flex justify-center items-center",children:Object(j.jsxs)("div",{className:"flex flex-col w-full lg:w-3/5 mb-12 bg-white p-8 rounded shadow",children:[Object(j.jsxs)("h1",{className:"text-3xl font-semibold mb-2 text-gray-900",children:["Patent2Net Docker Version : ",Object(j.jsx)("span",{class:"font-normal",children:t})," "]}),Object(j.jsx)("hr",{}),Object(j.jsx)("div",{className:"mt-4",children:Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsxs)("p",{className:"text-gray-800 text-sm mb-4 text-justify",children:["Patent2Net is a toolkit for patent information processing and statistical analysis for education and science.",Object(j.jsx)("br",{}),"Patent2Net helps to collect, study and analyze patent data from the European Patent Office\u2019s Open Patent Services API (OPS). ",Object(j.jsx)("br",{}),"Patent2Net is a free software dedicated to :"]}),Object(j.jsxs)("ul",{className:"list-disc text-gray-800 text-sm mb-3 text-justify",children:[Object(j.jsx)("li",{children:"provide statistical analysis and representations of a set of patents."}),Object(j.jsx)("li",{children:"promote the use of patent information in the academic field, nano and small firms, developing countries."}),Object(j.jsx)("li",{children:"study and practice how to collect, treat and communicate \u201ctextual bibliographic information\u201d and learn the automation process."})]}),Object(j.jsx)("p",{className:"text-gray-800 text-sm mb-4 text-justify",children:"Contributions are always welcome!"})]})}),Object(j.jsx)("hr",{}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("p",{className:"text-gray-800 text-sm mb-4 text-justify",children:"To update your P2N version click on the button : "}),Object(j.jsxs)("button",{onClick:l,className:"w-64 focus:outline-none px-8 py-2 rounded-md font-semibold text-white bg-red-500 cursor-pointer mt-4 flex flex-ror justify-center items-center",children:["Update P2N",a&&Object(j.jsxs)("svg",{className:"animate-spin ml-1 h-5 w-5 text-white",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})]})]})]})})})}),C=function(){var e=c.a.useState({}),t=Object(d.a)(e,2),s=t[0],n=t[1];return c.a.useEffect((function(){fetch("http://localhost:5000/api/v1/requests").then((function(e){return e.json()})).then((function(e){e.data&&n(e.data),console.log(e.data)}))}),[]),Object(j.jsx)("div",{className:"container mx-auto",children:Object(j.jsx)("div",{className:"flex justify-center items-center",children:Object(j.jsx)("div",{className:"flex flex-col w-full lg:w-3/5 mb-12 bg-white p-8 rounded shadow",children:Object(j.jsxs)("div",{children:[Object(j.jsx)("h1",{className:"text-3xl font-semibold mb-2 text-gray-900",children:"Index"}),Object(j.jsx)("hr",{}),Object(j.jsx)("div",{className:"mt-4",children:s.done&&s.done.map((function(e){return Object(j.jsx)("div",{children:Object(j.jsx)("a",{rel:"noreferrer",target:"_blank",href:"http://localhost:5000/DATA/"+e+".html",children:e})},e)}))})]})})})})};r.a.render(Object(j.jsx)(c.a.StrictMode,{children:Object(j.jsxs)(l.a,{children:[Object(j.jsx)("nav",{className:"bg-indigo-600 p-2 mt-0 w-full z-10 top-0 shadow text-white",children:Object(j.jsxs)("div",{className:"container mx-auto flex flex-wrap items-center",children:[Object(j.jsx)("div",{className:"flex w-full md:w-1/2 justify-center md:justify-start font-extrabold",children:Object(j.jsx)("a",{className:"no-underline hover:no-underline",href:"/",children:Object(j.jsx)("span",{className:"text-2xl pl-2",children:" Patent2Net"})})}),Object(j.jsx)("div",{className:"flex w-full pt-2 content-center justify-between md:w-1/2 md:justify-end",children:Object(j.jsxs)("ul",{className:"list-reset flex justify-between flex-1 md:flex-none items-center",children:[Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)(l.b,{to:"/app/",className:"inline-block no-underline hover:underline py-2 px-4",children:"Home"})}),Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)(l.b,{to:"/app/get_started",className:"inline-block no-underline hover:underline py-2 px-4",children:"Get Started"})}),Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)(l.b,{to:"/app/requests",className:"inline-block py-2 px-4 no-underline font-medium",children:"Requests"})}),Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)(l.b,{to:"/app/index",className:"inline-block no-underline hover:underline py-2 px-4",children:"Index"})}),Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)("a",{href:"/downloadDat",className:"inline-block no-underline hover:underline py-2 px-4",children:"Download Data"})}),Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)("a",{href:"/doc/_build/html/index.html",className:"inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-orange-500 hover:bg-white mt-4 lg:mt-0",children:"Documentation"})})]})})]})}),Object(j.jsx)("div",{className:"my-10",children:Object(j.jsxs)(i.c,{children:[Object(j.jsx)(i.a,{path:"/app/get_started",children:Object(j.jsx)(k,{})}),Object(j.jsx)(i.a,{path:"/app/requests/:dir",children:Object(j.jsx)(y,{})}),Object(j.jsx)(i.a,{path:"/app/requests",children:Object(j.jsx)(x,{})}),Object(j.jsx)(i.a,{path:"/app/index",children:Object(j.jsx)(C,{})}),Object(j.jsx)(i.a,{exact:!0,path:"/app/",children:Object(j.jsx)(_,{})})]})})]})}),document.getElementById("root"))}},[[32,1,2]]]); -//# sourceMappingURL=main.755d67ad.chunk.js.map \ No newline at end of file diff --git a/web_app/build/static/js/main.755d67ad.chunk.js.map b/web_app/build/static/js/main.755d67ad.chunk.js.map deleted file mode 100644 index 86af055f..00000000 --- a/web_app/build/static/js/main.755d67ad.chunk.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["pages/Requests.js","pages/Request/FusionList/index.js","pages/Request/Header/index.js","pages/Request/PatentCount/index.js","pages/Request/PatentCountResult/index.js","pages/Request/ProcessList/index.js","components/ProgressBar.js","pages/Request/Progress/index.js","pages/Request/RequestSplit/index.js","pages/Request/index.js","pages/GetStarted.js","pages/Home.js","pages/DataIndex.js","index.js"],"names":["all_options","name","description","App","React","useState","request","setRequest","directory","setDirectory","options","setOptions","requests","setRequests","p2nAuto","setP2nAuto","history","useHistory","useEffect","fetch","then","response","json","data","console","log","toggleCheckbox","useCallback","key","includes","filter","value","onSubmit","event","preventDefault","FormData","append","join","method","body","push","p2n_dir","className","done","map","to","class","in_progress","global_progress","style","done_step_count","total_step_count","progress_step_count","onChange","e","target","type","required","placeholder","id","pattern","title","Object","keys","index","option","checked","htmlFor","FusionList","fusion_list","start","end","xmlns","fill","viewBox","cx","cy","r","stroke","stroke-width","d","RequestHeader","dir","showLoading","isViewUpdate","setIsViewUpdate","updateView","strokeLinecap","strokeLinejoin","strokeWidth","cql","requete","onClick","rel","href","PatentCount","currentYear","Date","getFullYear","years","Array","from","length","_","i","PatentCountResult","to_be_found","yearOpen","setYearOpen","year","setYear","to_be_found_amount","useMemo","amount","runSpliter","onSelectYear","need_spliter","aria-haspopup","aria-expanded","aria-labelledby","aria-hidden","fill-rule","clip-rule","maxHeight","tabindex","role","aria-activedescendant","aria-label","ProcessList","process_list","hide_result","queue_list","file","done_list","ProgressBar","max_value","percent","text","Progress","progress","RequestSplit","spliter_result","cumulative","find","Request","useParams","setData","updateData","code","source","EventSource","onmessage","JSON","parse","close","isSpliterRun","state","showPatentCount","showRequestSplit","showPatentCountResult","showProgressList","showFusion","showRequestProgress","GetStarted","action","Id","Home","version","isUpdate","setIsUpdate","update","DataIndex","ReactDOM","render","StrictMode","path","Requests","exact","document","getElementById"],"mappings":"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","file":"static/js/main.755d67ad.chunk.js","sourcesContent":["import React from \"react\";\nimport { useHistory } from \"react-router\";\nimport { Link } from \"react-router-dom\";\n\nconst all_options = {\n \"p2n_family\": {\n name: \"p2n family\",\n description: \"run family data acquisition\"\n },\n \"p2n_image\": {\n name: \"p2n images\",\n description: \"Fetch images\"\n },\n \"p2n_network\": {\n name: \"p2n networks\",\n description: \"Build various artefacts for data exploration based on network graphs\"\n },\n \"p2n_freeplane\": {\n name: \"p2n freeplane\",\n description: \"Build mind map for Freeplane\"\n },\n \"p2n_bibfile\": {\n name: \"p2n bibfile\",\n description: \"Export data in bibfile format\"\n },\n \"p2n_map\": {\n name: \"p2n maps\",\n description: \"Build maps of country coverage of patents, as well as applicants and inventors\"\n },\n \"p2n_tables\": {\n name: \"p2n tables\",\n description: \"Export various artefacts for tabular data exploration\"\n },\n \"p2n_carrot\": {\n name: \"p2n carrot\",\n description: \"Export data to XML suitable for using in Carro\"\n },\n \"p2n_iramuteq\": {\n name: \"p2n iramuteq\",\n description: \"Fetch more data and export it to suitable format for using in Iramuteq\"\n },\n \"p2n_cluster\": {\n name: \"p2n cluster\",\n description: \"Double clustering system based on non so trivial words\"\n },\n}\n\nfunction App() {\n\n const [ request, setRequest ] = React.useState(\"\");\n const [ directory, setDirectory ] = React.useState(\"\");\n const [ options, setOptions ] = React.useState([\n \"p2n_content\",\n \"p2n_gather_biblio\",\n \"p2n_family\",\n \"p2n_image\",\n \"p2n_network\",\n \"p2n_freeplane\",\n \"p2n_bibfile\",\n \"p2n_map\",\n \"p2n_tables\",\n \"p2n_carrot\",\n \"p2n_iramuteq\",\n \"p2n_cluster\",\n ]);\n const [ requests, setRequests ] = React.useState({});\n const [ p2nAuto, setP2nAuto ] = React.useState(false);\n\n const history = useHistory();\n\n React.useEffect(() => {\n fetch(\"http://localhost:5000/api/v1/requests\")\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {\n if (json.data) {\n setRequests(json.data)\n }\n console.log(json.data)\n });\n }, []);\n\n const toggleCheckbox = React.useCallback((key) => {\n setOptions((options) => !options.includes(key) ? [...options, key] : [...options.filter((value) => value !== key)] )\n }, [setOptions])\n\n const onSubmit = React.useCallback((event) => {\n event.preventDefault()\n\n const data = new FormData();\n data.append(\"p2n_req\", request);\n data.append(\"p2n_dir\", directory);\n data.append(\"p2n_options\", options.join(','));\n data.append(\"p2n_auto\", p2nAuto ? \"true\" : \"false\")\n\n console.log(data)\n\n fetch('http://localhost:5000/api/v1/requests', { \n method: 'POST',\n body: data\n })\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {\n console.log(json)\n history.push(\"/app/requests/\" + json.data.p2n_dir );\n });\n \n\n }, [request, directory, options, history, p2nAuto])\n\n return (\n
\n
\n \n
\n

Requêtes précédentes

\n\n { requests.done && requests.done.map((name) => (\n {name}\n ))}\n\n { !requests.done && (\n
\n \n \n \n
\n ) }\n
\n \n
\n\n
\n

Requêtes en cours

\n
\n
\n { requests.in_progress && requests.in_progress.map((name) => (\n \n

{ name }

\n {\n requests.global_progress && requests.global_progress[name] && (\n
\n
\n
\n
\n )\n }\n \n ))}\n\n { !requests.in_progress && (\n
\n \n \n \n
\n ) }\n
\n
\n
\n
\n \n
\n

Patent2Net toolkit

\n
\n
\n\n
\n
\n \n

Enter in the textbox a valid espacenet smart search query for your patent research.

\n
\n
\n setRequest(e.target.value)}\n className=\"px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border border-blueGray-300 outline-none focus:outline-none focus:ring w-full\"\n type=\"text\"\n required\n placeholder=\"TA=lentille\"\n name=\"p2n_req\"\n id=\"p2n_reqBtn\"\n />\n
\n\n
\n \n

Enter in the textbox where your patent research will be stocked.

\n
\n
\n setDirectory(e.target.value)}\n className=\"px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border border-blueGray-300 outline-none focus:outline-none focus:ring w-full\" \n type=\"text\" \n required \n placeholder=\"lentille\" \n name=\"p2n_dir\" pattern=\"[A-Za-z0-9_-]{1,}\" \n title=\"Use only lowercase [a-z], Uppercase [A-Z], Numbers[0-9], Underscore[_] and Hyphen [-]\" \n />\n
\t\t\t\t\n\n
\n \n

Click on the checkbox to specify the elements you need in your research:

\n \n {Object.keys(all_options).map((key, index) => {\n let option = all_options[key]\n return (\n

\n toggleCheckbox(key) }\n />\n \n

\n )\n })}\n
\n
\n \n setP2nAuto(!p2nAuto) }\n />\n
\n\n\n
\n Fields marked with * are mandatory.\n
\n \n
\n
\n
\n
\n );\n}\n\nexport default App;\n","\nconst FusionList = ({ fusion_list }) => (\n
\n
\n

\n { (!fusion_list.start && !fusion_list.end) && \"La fusion des données va commencer\" }\n { (fusion_list.start && !fusion_list.end) && \"Les données sont en cours de fusion\" }\n { (fusion_list.end) && \"La fusion des données est terminé\" }\n

\n { !fusion_list.end && (\n \n \n \n \n )}\n
\n
\n)\n\nexport default FusionList","import React from \"react\";\nimport { Link } from \"react-router-dom\";\n\nconst RequestHeader = ({ dir, data, showLoading }) => {\n\n const [isViewUpdate, setIsViewUpdate] = React.useState(false);\n\n const updateView = React.useCallback(() => {\n setIsViewUpdate(true)\n fetch('http://localhost:5000/api/v1/requests/' + dir + \"/interface\", { \n method: 'POST'\n })\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {\n setIsViewUpdate(false)\n });\n }, [dir])\n\n\n return (\n
\n
\n \n \n \n \n \n
\n

{ dir }

\n

{ data.cql && data.cql.requete }

\n
\n
\n
\n { \n data.done && (\n <>\n \n \n Voir les données\n \n \n ) \n }\n {\n !data.done && showLoading && (\n \n \n \n \n \n Chargements\n
\n )\n }\n\n
\n \n )\n\n}\n\nexport default RequestHeader;","\nconst PatentCount = () => (\n
\n

Verification du nombre de ressource associé à la requete

\n
\n \n \n \n \n
\n
\n)\n\nexport default PatentCount","import React from \"react\"\n\nconst currentYear = new Date().getFullYear();\nconst years = Array.from({length: 30}, (_, i) => currentYear - i)\n\nconst PatentCountResult = ({ dir, to_be_found }) => {\n\n const [yearOpen, setYearOpen] = React.useState(false);\n const [year, setYear] = React.useState(currentYear)\n\n const to_be_found_amount = React.useMemo(() => (\n to_be_found && (to_be_found.amount >= 10000 ? `Plus de 10000` : to_be_found.amount)\n ), [to_be_found])\n\n const runSpliter = React.useCallback(() => {\n const data = new FormData();\n data.append(\"date\", year);\n\n fetch('http://localhost:5000/api/v1/requests/' + dir + \"/split\", { \n method: 'POST',\n body: data\n })\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {});\n }, [year, dir])\n\n const onSelectYear = React.useCallback((year) => {\n setYear(year)\n setYearOpen(false)\n }, [setYear])\n\n return (\n
\n
\n

{to_be_found_amount} éléments ont été trouvés

\n

\n {\n to_be_found.need_spliter ?\n \"À partir de quelle année voulez vous récuperer les données ?\" : \n \"Il n'est pas necessaire de découper la requete, le traiement va bientôt commencer\"\n }\n

\n
\n {\n to_be_found.need_spliter && (\n
\n
\n
\n
\n \n\n
    \n \n { years.map((year) => (\n
  • onSelectYear(year)}>\n
    \n \n \n { year }\n \n
    \n
  • \n ))}\n
\n
\n
\n
\n \n
\n )\n }\n \n
\n )\n\n}\n\nexport default PatentCountResult","\nconst ProcessList = ({ process_list, hide_result }) => (\n
\n
\n

\n { (!process_list.start && !process_list.end) && \"La récuperation des données va commencer\" }\n { (process_list.start && !process_list.end) && \"Les données sont en cours de récupération\" }\n { (process_list.end) && \"La récupération des données est terminé\" }\n

\n { !process_list.end && (\n \n \n \n \n )}\n
\n \n {\n !hide_result && (\n <>\n
\n
\n { process_list.queue_list && process_list.queue_list.map((file) => (\n
\n

{file}

\n
\n {\n process_list.done_list.includes(file) && (\n \n \n \n )\n }\n
\n
\n ))}\n
\n \n )\n }\n \n \n
\n)\n\n\n\nexport default ProcessList","import React from \"react\"\n\nconst ProgressBar = ({ name, value, max_value }) => {\n\n const percent = React.useMemo(() => (value / max_value * 100) || 0, [value, max_value])\n const text = value === null || max_value === null ? \"En attente...\" : percent + \"%\"\n\n\n return (\n
\n
\n

{ name }

\n

{ text }

\n
\n
\n
\n
\n
\n
\n
\n )\n}\n\nexport default ProgressBar","import ProgressBar from \"../../../components/ProgressBar\";\n\nconst Progress = ({ data }) => (\n
\n
\n

\n { (!data.progress && !data.done) && \"La requete va bientôt se lancer\" }\n { (data.progress && !data.done) && \"La requete est en cours\" }\n { (data.done) && \"La requete est terminé\" }\n

\n { !data.done && (\n \n \n \n \n )}\n
\n {\n (data.done === false && data.progress && (\n <>\n
\n
\n {Object.keys(data.progress).map((key, index) => (\n \n ))} \n
\n \n ))\n }\n
\n)\n\nexport default Progress","\nconst RequestSplit = ({spliter_result, hide_result}) => {\n \n return (\n
\n
\n
\n

\n { (!spliter_result.start && !spliter_result.end) && \"La séparation de la requete va commencer\" }\n { (spliter_result.start && !spliter_result.end) && \"Séparation de la requete en cours\" }\n { (spliter_result.end) && \"La séparation de la requete est terminé\" }\n\n

\n { !spliter_result.end && (\n \n \n \n \n )}\n
\n

{ (spliter_result.cumulative) ? spliter_result.cumulative : 0 }

\n
\n { spliter_result.requests && !hide_result && (\n <>\n
\n
\n { spliter_result.requests && spliter_result.requests.map((request) => (\n
\n

{request.name}

\n

{request.find}

\n
\n ))}\n
\n \n )}\n\n
\n )\n}\n\nexport default RequestSplit","import React from \"react\";\nimport { useHistory, useParams } from \"react-router\";\nimport { Link } from \"react-router-dom\";\nimport FusionList from \"./FusionList\";\nimport RequestHeader from \"./Header\";\nimport PatentCount from \"./PatentCount\";\nimport PatentCountResult from \"./PatentCountResult\";\nimport ProcessList from \"./ProcessList\";\nimport Progress from \"./Progress\";\nimport RequestSplit from \"./RequestSplit\";\n\n\nconst Request = () => {\n let { dir } = useParams();\n\n const [data, setData] = React.useState({});\n\n const updateData = React.useCallback(() => {\n fetch(\"http://localhost:5000/api/v1/requests/\" + dir)\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {\n if(json.code === 200) {\n console.log(json.data)\n setData(json.data)\n }\n });\n }, [dir])\n \n React.useEffect(() => {\n updateData()\n }, [updateData]);\n\n React.useEffect(() => {\n console.log(\"Opening the SSE connection\")\n var source = new EventSource(\"http://localhost:5000/api/v1/listen\");\n source.onmessage = function(event) {\n const data = JSON.parse(event.data)\n console.log(data)\n if(data.data.directory === dir) {\n updateData()\n }\n }\n return () => {\n source.close()\n }\n }, [updateData, dir])\n \n const isSpliterRun = React.useMemo(() => (\n data.state === \"SPLITER_RUN\"\n ), [data])\n\n const showPatentCount = React.useMemo(() => (\n isSpliterRun && data.data && !data.data.to_be_found\n ), [data, isSpliterRun])\n\n const showRequestSplit = React.useMemo(() => (\n isSpliterRun && data.data && data.data.spliter_result\n ), [data, isSpliterRun])\n\n const showPatentCountResult = React.useMemo(() => (\n isSpliterRun && data.data && data.data.to_be_found && !showRequestSplit\n ), [data, isSpliterRun, showRequestSplit])\n\n const showProgressList = React.useMemo(() => (\n isSpliterRun && data.data && data.data.process_list\n ), [data, isSpliterRun])\n\n const showFusion = React.useMemo(() => (\n isSpliterRun && data.data && data.data.fusion_list\n ), [data, isSpliterRun])\n\n const to_be_found = React.useMemo(() => showPatentCountResult && data.data.to_be_found, [data, showPatentCountResult])\n\n const spliter_result = React.useMemo(() => showRequestSplit && data.data.spliter_result, [data, showRequestSplit])\n\n const process_list = React.useMemo(() => showProgressList && data.data.process_list, [data, showProgressList])\n\n const fusion_list = React.useMemo(() => showFusion && data.data.fusion_list, [data, showFusion])\n\n const showRequestProgress = React.useMemo(() => (\n showFusion && fusion_list.end\n ), [showFusion, fusion_list])\n\n return (\n
\n
\n
\n {\n data.cql ? (\n <>\n \n
\n {\n !isSpliterRun ? \n (\n <>\n \n \n ) : (\n <>\n {\n showPatentCount && ( )\n }\n {\n showPatentCountResult && ( )\n }\n {\n showRequestSplit && ( )\n }\n {\n showProgressList && ( )\n }\n {\n showFusion && ( )\n }\n {\n showRequestProgress && ( )\n }\n \n )\n }\n \n \n ) : null\n }\n
\n
\n
\n ) \n}\n\nexport default Request;","\nconst GetStarted = () => {\n \n return (\n
\n
\n
\n
\n

Get Started

\n
\n \n
\n\n

Register the use of P2N

\n
\n\n
\n

You have first to register yourself at Espacenet and get a key to data access. So you must (if you already have it skip this step)\n

\t\n \n
    \n
  1. Go to the Open Patent Services (OPS) by opening the link :
    \n https://www.epo.org/searching-for-patents/technical/espacenet/ops.html#tab1
  2. \n
  3. Click on the “Register” button and fulfill the form
  4. \n
  5. Wait until you receive the email confirmation of you register from EPO Developer Portal.
  6. \n
  7. Log in the EPO Developer Portal :
    https://developers.epo.org/user/login
  8. \n
  9. Select the option “My apps
  10. \n
  11. Create and register the “Patent2Net” application
  12. \n
  13. The system returns the API credentials key and secret, similar to that shown bellow (this one is invalid, of course):
    \n
    vmrr7AaAGIl794E6VunJ6PzjbkfajwLW,KHzH4fGM7opMhDDD
    \n
  14. \n
  15. Copy/paste the key in the textbox and click on confirm. It will create a file in your install of Patent2Net who will let you have full use of it.
  16. \n
\n \n
\n
\n
\n
\n
\n \n

Paste in the textbox the key provided by EPO.

\n
\n
\n \n
\n\n \n
\n Fields marked with * are mandatory.\n
\n \n
\n
\n
\n
\n

P2N Docker archive content

\n
\n
\n
\n
\n
    \n
  • Dockerfile : Mandatory for the install of P2N Docker
  • \n
  • Install_P2N.bat : used to install all the P2N Content in Docker
  • \n
  • Run_P2N.bat : Used to initiate P2N instance in Docker
  • \n
  • Stop_P2N.bat : Used to stop P2N instance
  • \n
  • Copy Docker P2N :\n
      \n
    • Copy_Docker_P2N.bat : Create a tar file with all the base content of your docker version
    • \n
    • Load_Docker_P2N.bat : Import the tar file insde docker and create P2N image
    • \n
    \n
  • \n
  • P2N_Bash.bat : Create a command prompt instance who interact with P2N Docker. Click here for more details.
  • \n
\n
\n
\n
\n

P2N Interface directories

\n
\n
\n
\n
\n
    \n
  • Home : Default page. Explain how PatentNet can help you
  • \n
  • Get Started : Explain how to use P2N Docker
  • \n
  • Requests : form used to execute requests to the EPO database
  • \n
  • Index : Display all the results of P2N
  • \n
  • Download Data : create a zip folder with all the datas contained in Index. Downloaded on your local machine
  • \n
\n
\n
\n
\n
\n
\n )\n}\n\nexport default GetStarted;","import React from \"react\"\n\nconst Home = ({version}) => {\n\n const [isUpdate, setIsUpdate] = React.useState(false)\n\n const update = React.useCallback(() => {\n setIsUpdate(true)\n fetch(\"http://localhost:5000/updateP2N\")\n .then(function(response) {\n setIsUpdate(false)\n })\n }, [])\n\n return (\n
\n
\n
\n

Patent2Net Docker Version : {version}

\n
\n
\n
\n

Patent2Net is a toolkit for patent information processing and statistical analysis for education and science.
\n Patent2Net helps to collect, study and analyze patent data from the European Patent Office’s Open Patent Services API (OPS).
\n Patent2Net is a free software dedicated to :\n

\t\n \n
    \n
  • provide statistical analysis and representations of a set of patents.
  • \n
  • promote the use of patent information in the academic field, nano and small firms,\n developing countries.
  • \n
  • study and practice how to collect, treat and communicate “textual bibliographic information”\n and learn the automation process.
  • \n
\n \n

Contributions are always welcome!\n

\n
\n
\n
\n
\n

To update your P2N version click on the button :

\n \n
\n
\n
\n
\n )\n}\n\nexport default Home","import React from \"react\";\nimport { Link } from \"react-router-dom\";\n\nconst DataIndex = () => {\n const [ requests, setRequests ] = React.useState({});\n \n React.useEffect(() => {\n fetch(\"http://localhost:5000/api/v1/requests\")\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {\n if (json.data) {\n setRequests(json.data)\n }\n console.log(json.data)\n });\n }, []);\n \n return (\n
\n
\n
\n
\n

Index

\n
\n \n
\n { requests.done && requests.done.map((name) => (\n
\n {name}\n
\n ))}\n
\n
\n
\n
\n
\n )\n}\n\nexport default DataIndex","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport {\n BrowserRouter as Router,\n Switch,\n Route,\n Link,\n Redirect\n} from \"react-router-dom\";\nimport Requests from './pages/Requests';\nimport Request from './pages/Request/index';\nimport GetStarted from './pages/GetStarted';\nimport './index.css'\nimport Home from './pages/Home';\nimport DataIndex from './pages/DataIndex';\n\nReactDOM.render(\n \n \n \n {/* A looks through its children s and\n renders the first one that matches the current URL. */}\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n
\n
,\n document.getElementById('root')\n);\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\n// reportWebVitals();\n"],"sourceRoot":""} \ No newline at end of file diff --git a/web_app/build/static/js/main.88ea6b9f.chunk.js b/web_app/build/static/js/main.88ea6b9f.chunk.js new file mode 100644 index 00000000..8301ec7e --- /dev/null +++ b/web_app/build/static/js/main.88ea6b9f.chunk.js @@ -0,0 +1,2 @@ +(this.webpackJsonprequest_app=this.webpackJsonprequest_app||[]).push([[0],{31:function(e,t,s){},32:function(e,t,s){"use strict";s.r(t);var c=s(1),n=s.n(c),a=s(19),r=s.n(a),l=s(5),i=s(2),o=s(17),d=s(4),j=s(0),h=function(e){switch(e.name){case"family":return Object(j.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",viewBox:"0 0 512 512",children:Object(j.jsxs)("g",{children:[Object(j.jsx)("path",{d:"M56,88H80a8,8,0,0,0,8-8V56a8,8,0,0,0-8-8H56a8,8,0,0,0-8,8V80A8,8,0,0,0,56,88Zm8-24h8v8H64Z"}),Object(j.jsx)("path",{d:"M184,48H104a8,8,0,0,0,0,16h80a8,8,0,0,0,0-16Z"}),Object(j.jsx)("path",{d:"M184,72H104a8,8,0,0,0,0,16h80a8,8,0,0,0,0-16Z"}),Object(j.jsx)("path",{d:"M184,96H56a8,8,0,0,0,0,16H184a8,8,0,0,0,0-16Z"}),Object(j.jsx)("path",{d:"M120,120H56a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Z"}),Object(j.jsx)("path",{d:"M476,176H394.12L232,83.36V36A28.031,28.031,0,0,0,204,8H36A28.031,28.031,0,0,0,8,36V148a28.031,28.031,0,0,0,28,28H204a28.031,28.031,0,0,0,28-28V101.79L361.88,176H308a28.031,28.031,0,0,0-28,28V316a28.031,28.031,0,0,0,28,28h50.62L232,432.63V364a28.031,28.031,0,0,0-28-28H36A28.031,28.031,0,0,0,8,364V476a28.031,28.031,0,0,0,28,28H204a28.031,28.031,0,0,0,28-28V452.17L386.52,344H476a28.031,28.031,0,0,0,28-28V204A28.031,28.031,0,0,0,476,176ZM216,148a12.01,12.01,0,0,1-12,12H36a12.01,12.01,0,0,1-12-12V36A12.01,12.01,0,0,1,36,24H204a12.01,12.01,0,0,1,12,12Zm0,328a12.01,12.01,0,0,1-12,12H36a12.01,12.01,0,0,1-12-12V364a12.01,12.01,0,0,1,12-12H204a12.01,12.01,0,0,1,12,12ZM488,316a12.01,12.01,0,0,1-12,12H308a12.01,12.01,0,0,1-12-12V204a12.01,12.01,0,0,1,12-12H476a12.01,12.01,0,0,1,12,12Z"}),Object(j.jsx)("path",{d:"M328,256h24a8,8,0,0,0,8-8V224a8,8,0,0,0-8-8H328a8,8,0,0,0-8,8v24A8,8,0,0,0,328,256Zm8-24h8v8h-8Z"}),Object(j.jsx)("path",{d:"M456,216H376a8,8,0,0,0,0,16h80a8,8,0,0,0,0-16Z"}),Object(j.jsx)("path",{d:"M456,240H376a8,8,0,0,0,0,16h80a8,8,0,0,0,0-16Z"}),Object(j.jsx)("path",{d:"M456,264H328a8,8,0,0,0,0,16H456a8,8,0,0,0,0-16Z"}),Object(j.jsx)("path",{d:"M392,288H328a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Z"}),Object(j.jsx)("path",{d:"M56,416H80a8,8,0,0,0,8-8V384a8,8,0,0,0-8-8H56a8,8,0,0,0-8,8v24A8,8,0,0,0,56,416Zm8-24h8v8H64Z"}),Object(j.jsx)("path",{d:"M184,376H104a8,8,0,0,0,0,16h80a8,8,0,0,0,0-16Z"}),Object(j.jsx)("path",{d:"M184,400H104a8,8,0,0,0,0,16h80a8,8,0,0,0,0-16Z"}),Object(j.jsx)("path",{d:"M184,424H56a8,8,0,0,0,0,16H184a8,8,0,0,0,0-16Z"}),Object(j.jsx)("path",{d:"M120,448H56a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Z"})]})});case"image":return Object(j.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:[" ",Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"})," "]});case"network":return Object(j.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",x:"0px",y:"0px",viewBox:"0 0 418.026 418.026",children:[" ",Object(j.jsx)("path",{d:"M275.403,228.092l38.054,7.552c1.337,21.384,19.756,37.634,41.14,36.297c21.384-1.337,37.634-19.756,36.297-41.14 c-1.337-21.384-19.756-37.634-41.14-36.297c-13.863,0.867-26.204,9.079-32.358,21.532l-39.379-7.815 c-0.427-14.916-6.199-29.182-16.263-40.2l53.084-74.988c24.581,10.661,53.15-0.624,63.81-25.204s-0.624-53.15-25.204-63.81 s-53.15,0.624-63.81,25.204c-7.649,17.637-4.163,38.126,8.889,52.24l-52.454,74.1c-25.096-14.084-56.571-9.157-76.162,11.922 l-68.737-53.381c9.076-19.458,0.659-42.588-18.798-51.664c-19.458-9.076-42.588-0.659-51.664,18.798 c-9.076,19.458-0.659,42.588,18.798,51.664c12.623,5.888,27.432,4.572,38.82-3.449l70.419,54.686 c-11.312,24.707-5.322,53.895,14.808,72.148l-42.182,59.655c-24.902-13.883-56.344-4.951-70.227,19.951 c-13.883,24.902-4.951,56.344,19.951,70.227c24.902,13.883,56.344,4.951,70.227-19.951c10.179-18.258,8.343-40.852-4.651-57.227 l43.649-61.735c15.209,6.747,32.485,7.127,47.976,1.055l52.18,77.082c-15.957,18.174-14.159,45.842,4.014,61.798 c18.174,15.957,45.842,14.159,61.798-4.014c15.957-18.174,14.159-45.842-4.014-61.798c-12.496-10.972-30.128-13.919-45.513-7.607 l-51.219-75.662C264.948,250.225,271.853,239.807,275.403,228.092z M352.157,214.428c10.374,0,18.784,8.41,18.784,18.784 c0,10.374-8.41,18.784-18.784,18.784c-10.374,0-18.784-8.41-18.784-18.784C333.382,222.841,341.787,214.436,352.157,214.428z M334.01,20.237c15.674,0.001,28.381,12.708,28.38,28.382s-12.708,28.381-28.382,28.38c-15.674-0.001-28.38-12.707-28.38-28.381 C305.647,32.95,318.343,20.254,334.01,20.237z M66.009,116.54c-10.369-0.012-18.772-8.415-18.784-18.784 c0-10.374,8.41-18.784,18.784-18.784c10.374,0,18.784,8.41,18.784,18.784C84.793,108.13,76.384,116.54,66.009,116.54z M106.363,392.398c-17.388-0.001-31.483-14.096-31.482-31.484c0.001-17.388,14.096-31.483,31.484-31.482 c17.387,0.001,31.482,14.096,31.482,31.483C137.828,378.295,123.743,392.379,106.363,392.398z M323.374,350.449 c13.174,0.015,23.849,10.69,23.864,23.864c0,13.18-10.684,23.864-23.864,23.864c-13.18,0-23.864-10.684-23.864-23.864 C299.51,361.133,310.195,350.449,323.374,350.449z M215.572,252.56c-23.455-0.026-42.463-19.034-42.489-42.489h0 c0-23.466,19.023-42.489,42.489-42.489c23.466,0,42.489,19.023,42.489,42.489C258.061,233.537,239.038,252.56,215.572,252.56z"})," "]});case"nodes":return Object(j.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",viewBox:"0 0 64 64",children:[Object(j.jsx)("path",{d:"m34.293 6.293-4.293 4.293-1.293-1.293-1.414 1.414 2 2c.195.195.451.293.707.293s.512-.098.707-.293l5-5z"}),Object(j.jsx)("path",{d:"m52 24c.256 0 .512-.098.707-.293l5-5-1.414-1.414-4.293 4.293-1.293-1.293-1.414 1.414 2 2c.195.195.451.293.707.293z"}),Object(j.jsx)("path",{d:"m54 46c-2.282 0-4.339.966-5.798 2.504l-15.599-11.432c.882-1.489 1.397-3.22 1.397-5.072 0-.859-.12-1.688-.325-2.484l13.224-4.846c1.333 2.568 4.013 4.33 7.101 4.33 4.411 0 8-3.589 8-8s-3.589-8-8-8-8 3.589-8 8c0 .617.077 1.215.21 1.792l-13.225 4.847c-.985-2.022-2.628-3.659-4.653-4.638l1.899-5.205c.57.13 1.16.204 1.769.204 4.411 0 8-3.589 8-8s-3.589-8-8-8-8 3.589-8 8c0 3.097 1.772 5.782 4.352 7.111l-1.9 5.206c-.786-.2-1.605-.317-2.452-.317-1.616 0-3.139.394-4.492 1.078l-4.403-6.925c1.767-1.469 2.895-3.681 2.895-6.153 0-4.411-3.589-8-8-8s-8 3.589-8 8 3.589 8 8 8c1.223 0 2.378-.284 3.416-.777l4.405 6.93c-2.322 1.833-3.821 4.665-3.821 7.847 0 3.023 1.354 5.732 3.481 7.567l-3.753 5.361c-1.114-.59-2.382-.928-3.728-.928-4.411 0-8 3.589-8 8s3.589 8 8 8 8-3.589 8-8c0-2.347-1.022-4.454-2.637-5.919l3.754-5.363c1.446.813 3.11 1.282 4.883 1.282 2.944 0 5.586-1.286 7.418-3.318l15.596 11.43c-.644 1.153-1.014 2.477-1.014 3.888 0 4.411 3.589 8 8 8s8-3.589 8-8-3.589-8-8-8zm0-31c3.309 0 6 2.691 6 6s-2.691 6-6 6-6-2.691-6-6 2.691-6 6-6zm-28-5c0-3.309 2.691-6 6-6s6 2.691 6 6-2.691 6-6 6-6-2.691-6-6zm-22 0c0-3.309 2.691-6 6-6s6 2.691 6 6-2.691 6-6 6-6-2.691-6-6zm12 42c0 3.309-2.691 6-6 6s-6-2.691-6-6 2.691-6 6-6 6 2.691 6 6zm8-12c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8zm30 20c-3.309 0-6-2.691-6-6s2.691-6 6-6 6 2.691 6 6-2.691 6-6 6z"}),Object(j.jsx)("path",{d:"m8 52.586-1.293-1.293-1.414 1.414 2 2c.195.195.451.293.707.293s.512-.098.707-.293l5-5-1.414-1.414z"})]});case"archive":return Object(j.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:[" ",Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"})," "]});case"map":return Object(j.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:[" ",Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7"})," "]});case"table":return Object(j.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:[" ",Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M3 10h18M3 14h18m-9-4v8m-7 0h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"})," "]});case"carrot":return Object(j.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",viewBox:"0 0 512 512",children:Object(j.jsxs)("g",{children:[Object(j.jsx)("path",{d:"m280.95 178.016v-2.336c0-8.674 4.952-16.736 12.924-21.042 11.161-6.029 21.928-17.815 29.537-32.333 6.604-12.584 10.193-25.919 10.107-37.549-.099-13.321-4.955-23.176-13.667-27.744-7.416-3.902-16.443-3.272-25.7 1.577-1.036-15.003-4.299-28.017-9.59-38.061-6.974-13.237-17.117-20.528-28.561-20.528s-21.587 7.291-28.561 20.528c-5.29 10.041-8.553 23.047-9.589 38.061-9.256-4.85-18.282-5.479-25.691-1.583-12.125 6.354-16.622 23.118-11.737 43.751.954 4.03 4.993 6.521 9.026 5.57 4.031-.955 6.524-4.996 5.57-9.026-3.083-13.021-1.396-24.127 4.113-27.014 4.146-2.179 11.2.152 18.415 6.085 2.752 2.265 6.467 2.725 9.693 1.202 3.19-1.507 5.251-4.763 5.251-8.324 0-35.237 12.113-54.25 23.51-54.25s23.51 19.013 23.51 54.28c0 3.532 2.062 6.788 5.251 8.294 3.224 1.521 6.938 1.062 9.693-1.202 7.213-5.934 14.27-8.264 18.423-6.081 3.531 1.852 5.587 7.164 5.642 14.575.067 9.075-2.991 20.18-8.392 30.472-6.167 11.768-14.908 21.526-23.38 26.103-12.828 6.927-20.796 20.046-20.796 34.239v1.534c-6.409-.174-13.438-.175-19.9 0v-1.534c0-14.193-7.969-27.312-20.801-34.242-5.622-3.03-11.533-8.48-16.643-15.346-2.473-3.323-7.171-4.01-10.495-1.539-3.323 2.473-4.012 7.172-1.539 10.495 6.484 8.711 13.938 15.487 21.553 19.591 7.971 4.305 12.923 12.367 12.923 21.041v2.336c-42.256 3.495-86.21 18.771-86.21 76.667 0 12.806 2.284 26.2 6.969 38.781l68.283 193.026c5.319 15.258 19.75 25.51 35.909 25.51s30.59-10.252 35.897-25.478l40.734-115.15c1.381-3.905-.665-8.191-4.569-9.572-3.908-1.381-8.191.664-9.572 4.57l-17.983 50.836h-39.467c-4.142 0-7.5 3.358-7.5 7.5s3.358 7.5 7.5 7.5h34.161l-17.456 49.346c-3.222 9.24-11.96 15.448-21.745 15.448s-18.523-6.208-21.756-15.48c0 0-68.543-193.777-68.64-194.044h42.019c4.142 0 7.5-3.358 7.5-7.5s-3.358-7.5-7.5-7.5h-46.124c-1.095-5.838-1.66-11.781-1.66-17.792 0-43.878 28.758-62.6 96.161-62.6s96.161 18.721 96.161 62.6c0 11.542-2.034 22.846-6.045 33.599-.015.04-15.587 44.06-15.587 44.06-1.381 3.905.665 8.19 4.569 9.572 3.906 1.379 8.19-.665 9.572-4.57l15.523-43.882c4.624-12.417 6.968-25.464 6.968-38.779 0-57.897-43.955-73.173-86.211-76.668z"}),Object(j.jsx)("path",{d:"m302.185 279.975c0-4.142-3.358-7.5-7.5-7.5h-26.083c-4.142 0-7.5 3.358-7.5 7.5s3.358 7.5 7.5 7.5h26.083c4.142 0 7.5-3.358 7.5-7.5z"}),Object(j.jsx)("path",{d:"m234.278 344.843c-4.142 0-7.5 3.358-7.5 7.5s3.358 7.5 7.5 7.5h43.443c4.142 0 7.5-3.358 7.5-7.5s-3.358-7.5-7.5-7.5z"})]})});case"chart-pie":return Object(j.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:[" ",Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M11 3.055A9.001 9.001 0 1020.945 13H11V3.055z"})," ",Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M20.488 9H15V3.512A9.025 9.025 0 0120.488 9z"})," "]});case"cluster":return Object(j.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",viewBox:"0 0 512 512",children:[Object(j.jsx)("path",{d:"m94.944 369.437h-31.67c-17.819 0-32.317 14.497-32.317 32.317s14.497 32.317 32.317 32.317h31.67c17.819 0 32.317-14.497 32.317-32.317s-14.498-32.317-32.317-32.317zm0 49.56h-31.67c-9.508 0-17.243-7.735-17.243-17.243s7.735-17.243 17.243-17.243h31.67c9.508 0 17.243 7.735 17.243 17.243s-7.735 17.243-17.243 17.243z"}),Object(j.jsx)("path",{d:"m130.276 106.994c0-7.888-6.418-14.307-14.306-14.307h-73.721c-7.888 0-14.306 6.418-14.306 14.307v202.225c0 7.888 6.418 14.307 14.306 14.307h73.721c7.888 0 14.306-6.418 14.306-14.307zm-15.074 201.458h-72.185v-200.69h72.185z"}),Object(j.jsx)("path",{d:"m64.916 261.082c4.163 0 7.537-3.374 7.537-7.537v-93.198c0-4.163-3.374-7.537-7.537-7.537s-7.537 3.374-7.537 7.537v93.198c0 4.163 3.374 7.537 7.537 7.537z"}),Object(j.jsx)("path",{d:"m93.302 261.082c4.163 0 7.537-3.374 7.537-7.537v-68.633c0-4.163-3.374-7.537-7.537-7.537s-7.537 3.374-7.537 7.537v68.633c0 4.163 3.375 7.537 7.537 7.537z"}),Object(j.jsx)("path",{d:"m238.047 369.437h-31.669c-17.819 0-32.317 14.497-32.317 32.317s14.497 32.317 32.317 32.317h31.669c17.819 0 32.317-14.497 32.317-32.317s-14.498-32.317-32.317-32.317zm0 49.56h-31.669c-9.508 0-17.243-7.735-17.243-17.243s7.735-17.243 17.243-17.243h31.669c9.508 0 17.243 7.735 17.243 17.243s-7.735 17.243-17.243 17.243z"}),Object(j.jsx)("path",{d:"m273.379 106.994c0-7.888-6.418-14.307-14.306-14.307h-73.721c-7.888 0-14.306 6.418-14.306 14.307v202.225c0 7.888 6.418 14.307 14.306 14.307h73.721c7.888 0 14.306-6.418 14.306-14.307zm-15.074 201.458h-72.185v-200.69h72.185z"}),Object(j.jsx)("path",{d:"m208.019 261.082c4.163 0 7.537-3.374 7.537-7.537v-93.198c0-4.163-3.374-7.537-7.537-7.537s-7.537 3.374-7.537 7.537v93.198c0 4.163 3.374 7.537 7.537 7.537z"}),Object(j.jsx)("path",{d:"m236.406 261.083c4.163 0 7.537-3.374 7.537-7.537v-93.199c0-4.163-3.374-7.537-7.537-7.537s-7.537 3.374-7.537 7.537v93.199c0 4.163 3.374 7.537 7.537 7.537z"}),Object(j.jsx)("path",{d:"m511.713 444.597-69.238-403.93c-1.824-10.649-11.97-17.822-22.625-16.005l-117.314 20.11c-1.673.287-3.277.788-4.785 1.472-3.549-5.044-9.404-8.355-16.026-8.355h-119.026c-4.537 0-8.708 1.564-12.033 4.163-3.326-2.602-7.504-4.163-12.044-4.163h-63.352c-4.163 0-7.537 3.374-7.537 7.537s3.374 7.537 7.537 7.537h63.352c2.401 0 4.351 1.885 4.495 4.251-.001.091-.014.18-.014.272v346.16c0 4.163 3.374 7.537 7.537 7.537s7.537-3.374 7.537-7.537v-346.161c0-2.494 2.029-4.522 4.522-4.522h119.026c2.494 0 4.522 2.029 4.522 4.522v409.822c0 2.494-2.029 4.522-4.522 4.522h-119.026c-2.401 0-4.351-1.885-4.495-4.251.001-.091.014-.18.014-.272 0-.266-.014-.528-.041-.786v-28.54c0-4.163-3.374-7.537-7.537-7.537s-7.537 3.374-7.537 7.537v29.327c0 .092.012.18.014.272-.144 2.365-2.094 4.251-4.495 4.251h-119.026c-2.494 0-4.522-2.029-4.522-4.522v-409.823c0-2.494 2.029-4.522 4.522-4.522h20.836c4.163 0 7.537-3.374 7.537-7.537s-3.374-7.537-7.537-7.537h-20.836c-10.805-.001-19.596 8.79-19.596 19.596v409.822c0 10.805 8.791 19.596 19.596 19.596h119.026c4.54 0 8.713-1.566 12.039-4.167 3.326 2.601 7.499 4.167 12.039 4.167h119.026c10.806 0 19.596-8.791 19.596-19.596v-313.623l54.448 317.644c.884 5.16 3.725 9.666 7.998 12.688 3.346 2.367 7.257 3.603 11.274 3.603 1.112 0 2.234-.095 3.353-.287l117.315-20.11c5.159-.884 9.666-3.724 12.688-7.998 3.022-4.272 4.2-9.468 3.315-14.627zm-15.622 5.923c-.697.986-1.737 1.641-2.928 1.845l-117.316 20.11c-1.189.206-2.389-.068-3.375-.765-.986-.698-1.642-1.737-1.846-2.928l-69.238-403.932c-.153-.893-.039-1.798.33-2.615 0 0 0-.001.001-.001.622-1.377 1.878-2.349 3.362-2.604l117.315-20.11c.257-.044.513-.066.766-.066 2.161 0 4.078 1.558 4.455 3.76l69.238 403.931c.205 1.19-.067 2.389-.764 3.375z"}),Object(j.jsx)("path",{d:"m432.814 358.824-31.214 5.35c-8.508 1.458-15.939 6.143-20.924 13.191-4.984 7.047-6.927 15.614-5.468 24.121 1.458 8.509 6.142 15.94 13.19 20.924 5.519 3.904 11.968 5.941 18.594 5.941 1.834 0 3.684-.156 5.529-.472l31.214-5.351c8.508-1.458 15.939-6.143 20.924-13.191 4.985-7.047 6.927-15.614 5.469-24.122-3.013-17.562-19.75-29.401-37.314-26.391zm19.537 41.81c-2.66 3.761-6.624 6.259-11.164 7.038l-31.214 5.351c-4.538.778-9.111-.258-12.871-2.918s-6.259-6.624-7.038-11.163c-.778-4.54.258-9.111 2.918-12.871 2.66-3.761 6.625-6.26 11.164-7.038l31.214-5.35c.981-.169 1.958-.25 2.922-.25 8.239 0 15.548 5.942 16.986 14.331.779 4.539-.257 9.111-2.917 12.87z"}),Object(j.jsx)("path",{d:"m387.718 312.326c-.704-4.102-4.604-6.857-8.702-6.155l-7.687 1.318-33.906-197.805 71.148-12.195 33.906 197.805-28.978 4.967c-4.103.704-6.858 4.6-6.155 8.703.704 4.102 4.597 6.857 8.702 6.155l29.736-5.098c7.774-1.333 13.015-8.743 11.682-16.518l-34.165-199.317c-.645-3.767-2.719-7.056-5.839-9.263-3.121-2.207-6.914-3.064-10.678-2.421l-72.662 12.456c-7.775 1.333-13.016 8.742-11.683 16.518l34.165 199.317c.645 3.767 2.719 7.057 5.839 9.263 2.443 1.728 5.298 2.63 8.231 2.63.813 0 1.631-.07 2.448-.209l8.443-1.448c4.103-.703 6.859-4.599 6.155-8.703z"}),Object(j.jsx)("path",{d:"m366.619 150.385c-4.103.704-6.858 4.6-6.155 8.703l15.746 91.859c.63 3.671 3.816 6.264 7.42 6.264.422 0 .851-.035 1.282-.109 4.103-.704 6.858-4.6 6.155-8.703l-15.746-91.859c-.703-4.102-4.598-6.854-8.702-6.155z"}),Object(j.jsx)("path",{d:"m411.608 252.415c.422 0 .851-.035 1.282-.109 4.103-.704 6.858-4.6 6.155-8.703l-15.746-91.859c-.703-4.101-4.594-6.857-8.702-6.155-4.103.704-6.858 4.6-6.155 8.703l15.746 91.859c.629 3.671 3.816 6.264 7.42 6.264z"})]});case"infographic":return Object(j.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",viewBox:"0 0 512.002 512.002",children:Object(j.jsx)("path",{d:"m479.502 296.834c-14.433 0-26.699 9.457-30.926 22.5h-38.615l-36.565-63.333 36.565-63.334h38.615c11.964 34.739 62.573 27.18 63.426-10-.856-37.187-51.469-44.733-63.426-10h-38.615l-39.452-68.333c-1.786-3.094-5.088-5-8.66-5h-78.905l-39.452-68.333c-1.786-3.094-5.088-5-8.66-5h-84.678c-3.572 0-6.874 1.906-8.66 5l-39.453 68.333h-38.615c-11.963-34.739-62.573-27.179-63.426 10.001.856 37.187 51.469 44.733 63.426 10h38.615l36.566 63.333-36.566 63.334h-38.615c-11.964-34.739-62.573-27.18-63.426 10 .856 37.187 51.469 44.733 63.426 10h38.615l36.566 63.333-36.566 63.333h-38.615c-11.964-34.739-62.573-27.18-63.426 10 .856 37.187 51.469 44.733 63.426 10h38.615l39.453 68.333c1.786 3.094 5.088 5 8.66 5h84.678c3.572 0 6.874-1.906 8.66-5l39.452-68.333h78.904c3.572 0 6.874-1.906 8.66-5l39.452-68.333h38.615c11.847 34.72 62.68 27.123 63.426-10 .001-17.921-14.578-32.501-32.499-32.501zm0-126.666c6.893 0 12.5 5.607 12.5 12.5-.687 16.583-24.316 16.578-25 0 0-6.893 5.607-12.5 12.5-12.5zm-86.861 12.5-36.565 63.333h-73.131l-36.565-63.333 36.566-63.334h73.131zm-360.141-60.834c-6.893 0-12.5-5.607-12.5-12.5.687-16.583 24.316-16.578 25 0 0 6.893-5.607 12.5-12.5 12.5zm123.428-75.833h73.131l36.565 63.333-36.565 63.333h-73.131l-36.566-63.333zm-123.428 222.5c-6.893 0-12.5-5.607-12.5-12.5.687-16.583 24.316-16.578 25 0 0 6.893-5.607 12.5-12.5 12.5zm123.428-75.834h73.131l36.565 63.333-36.565 63.333h-73.131l-36.566-63.333zm-123.428 222.501c-6.893 0-12.5-5.607-12.5-12.5.687-16.583 24.316-16.578 25 0 0 6.892-5.607 12.5-12.5 12.5zm196.559 50.833h-73.131l-36.566-63.333 36.566-63.333h73.131l36.565 63.333zm127.016-73.333h-73.131l-36.565-63.333 36.565-63.333h73.131l36.565 63.333zm123.427-50.834c-6.893 0-12.5-5.607-12.5-12.5.687-16.583 24.316-16.578 25 0 0 6.893-5.607 12.5-12.5 12.5z"})});case"split":return Object(j.jsxs)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",viewBox:"0 0 64 64",children:[" ",Object(j.jsx)("path",{d:"M12 24l-9 8 9 8m40-16l9 8-9 8m-16-8h25M3 32h25","stroke-width":"3","stroke-miterlimit":"10","stroke-linecap":"round",stroke:"#202020",fill:"none","data-name":"layer2","stroke-linejoin":"round"})," ",Object(j.jsx)("path",{d:"M36 10v44m-8-44v44","stroke-width":"3","stroke-miterlimit":"10","stroke-linecap":"round",stroke:"#202020",fill:"none","data-name":"layer1","stroke-linejoin":"round"})," "]});default:return null}},b={p2n_family:{name:"p2n family",description:"run family data acquisition",icon:"family"},p2n_image:{name:"p2n images",description:"Fetch images",icon:"image"},p2n_network:{name:"p2n networks",description:"Build various artefacts for data exploration based on network graphs",icon:"network"},p2n_freeplane:{name:"p2n freeplane",description:"Build mind map for Freeplane",icon:"nodes"},p2n_bibfile:{name:"p2n bibfile",description:"Export data in bibfile format",icon:"archive"},p2n_map:{name:"p2n maps",description:"Build maps of country coverage of patents, as well as applicants and inventors",icon:"map"},p2n_tables:{name:"p2n tables",description:"Export various artefacts for tabular data exploration",icon:"table"},p2n_carrot:{name:"p2n carrot",description:"Export data to XML suitable for using in Carro",icon:"carrot"},p2n_iramuteq:{name:"p2n iramuteq",description:"Fetch more data and export it to suitable format for using in Iramuteq",icon:"chart-pie"},p2n_cluster:{name:"p2n cluster",description:"Double clustering system based on non so trivial words",icon:"cluster"}};var x=function(){var e=n.a.useState(""),t=Object(d.a)(e,2),s=t[0],c=t[1],a=n.a.useState(""),r=Object(d.a)(a,2),x=r[0],m=r[1],u=n.a.useState(["p2n_content","p2n_gather_biblio","p2n_family","p2n_image","p2n_network","p2n_freeplane","p2n_bibfile","p2n_map","p2n_tables","p2n_carrot","p2n_iramuteq","p2n_cluster"]),p=Object(d.a)(u,2),f=p[0],O=p[1],w=n.a.useState({}),v=Object(d.a)(w,2),g=v[0],N=v[1],y=n.a.useState(!1),k=Object(d.a)(y,2),_=k[0],z=k[1],C=Object(i.f)();n.a.useEffect((function(){fetch("http://localhost:5000/api/v1/requests").then((function(e){return e.json()})).then((function(e){e.data&&N(e.data),console.log(e.data)}))}),[]);var M=n.a.useCallback((function(e){O((function(t){return t.includes(e)?Object(o.a)(t.filter((function(t){return t!==e}))):[].concat(Object(o.a)(t),[e])}))}),[O]),H=n.a.useCallback((function(e){e.preventDefault();var t=new FormData;t.append("p2n_req",s),t.append("p2n_dir",x),t.append("p2n_options",f.join(",")),t.append("p2n_auto",_?"true":"false"),console.log(t),fetch("http://localhost:5000/api/v1/requests",{method:"POST",body:t}).then((function(e){return e.json()})).then((function(e){console.log(e),C.push("/app/requests/"+e.data.p2n_dir)}))}),[s,x,f,C,_]);return Object(j.jsxs)("div",{className:"container mx-auto grid grid-cols-4 gap-4 items-start",children:[Object(j.jsxs)("div",{className:"col-start-1 bg-white p-8 rounded shadow",children:[Object(j.jsxs)("div",{className:"mb-6 flex flex-col",children:[Object(j.jsx)("h3",{className:"text-lg mb-2 font-bold",children:"Requ\xeates pr\xe9c\xe9dentes"}),g.done&&g.done.map((function(e){return Object(j.jsx)(l.b,{to:"/app/requests/"+e,children:e},e)})),!g.done&&Object(j.jsxs)("div",{className:"grid grid-cols-1 gap-2",children:[Object(j.jsx)("span",{className:"skeleton-box h-5 w-3/5 inline-block"}),Object(j.jsx)("span",{className:"skeleton-box h-5 w-1/2 inline-block"}),Object(j.jsx)("span",{className:"skeleton-box h-5 w-2/5 inline-block"})]})]}),Object(j.jsx)("hr",{class:"mb-3"}),Object(j.jsxs)("div",{class:"mb-6 flex flex-col",children:[Object(j.jsx)("h3",{className:"text-lg mb-2 font-bold",children:"Requ\xeates en cours"}),Object(j.jsx)("div",{className:"",children:Object(j.jsxs)("div",{className:"relative pt-1",children:[g.in_progress&&g.in_progress.map((function(e){return Object(j.jsxs)(l.b,{to:"/app/requests/"+e,children:[Object(j.jsx)("p",{class:"mb-1",children:e}),g.global_progress&&g.global_progress[e]&&Object(j.jsxs)("div",{className:"overflow-hidden h-2 mb-4 text-xs flex rounded bg-orange-200",children:[Object(j.jsx)("div",{style:{width:g.global_progress[e].done_step_count/g.global_progress[e].total_step_count*100+"%"},className:"shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-indigo-500"}),Object(j.jsx)("div",{style:{width:g.global_progress[e].progress_step_count/g.global_progress[e].total_step_count*100+"%"},className:"shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-orange-300"})]})]},e)})),!g.in_progress&&Object(j.jsxs)("div",{className:"grid grid-cols-1 gap-2",children:[Object(j.jsx)("span",{className:"skeleton-box h-5 w-3/5 inline-block"}),Object(j.jsx)("span",{className:"skeleton-box h-5 w-1/2 inline-block"}),Object(j.jsx)("span",{className:"skeleton-box h-5 w-2/5 inline-block"})]})]})})]})]}),Object(j.jsxs)("div",{className:"col-span-3 flex flex-col mb-12 bg-white p-8 rounded shadow ",children:[Object(j.jsx)("h1",{className:"text-3xl font-semibold mb-2 text-gray-900",children:"Patent2Net toolkit"}),Object(j.jsx)("hr",{}),Object(j.jsx)("div",{className:"mt-4",children:Object(j.jsxs)("form",{onSubmit:H,children:[Object(j.jsxs)("div",{children:[Object(j.jsx)("label",{className:"font-semibold",children:"Request in CQL format * :"}),Object(j.jsx)("p",{className:"pt-2 pb-2 text-sm italic text-gray-800",children:"Enter in the textbox a valid espacenet smart search query for your patent research."})]}),Object(j.jsx)("div",{className:"mb-2",children:Object(j.jsx)("input",{value:s,onChange:function(e){return c(e.target.value)},className:"px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border border-blueGray-300 outline-none focus:outline-none focus:ring w-full",type:"text",required:!0,placeholder:"TA=lentille",name:"p2n_req",id:"p2n_reqBtn"})}),Object(j.jsxs)("div",{children:[Object(j.jsx)("label",{className:"font-semibold",children:"Request Location * :"}),Object(j.jsx)("p",{className:"pt-2 pb-2 text-sm italic text-gray-800",children:"Enter in the textbox where your patent research will be stocked."})]}),Object(j.jsx)("div",{className:"mb-2",children:Object(j.jsx)("input",{value:x,onChange:function(e){return m(e.target.value)},className:"px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border border-blueGray-300 outline-none focus:outline-none focus:ring w-full",type:"text",required:!0,placeholder:"lentille",name:"p2n_dir",pattern:"[A-Za-z0-9_-]{1,}",title:"Use only lowercase [a-z], Uppercase [A-Z], Numbers[0-9], Underscore[_] and Hyphen [-]"})}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("label",{className:"font-semibold",children:"Request Options :"}),Object(j.jsx)("p",{className:"pt-2 pb-2 text-sm italic text-gray-800",children:"Click on the checkbox to specify the elements you need in your research:"}),Object(j.jsx)("div",{className:"grid grid-flow-row grid-cols-3 gap-2",children:Object.keys(b).map((function(e,t){var s=b[e];return Object(j.jsxs)("div",{class:f.includes(e)?"cursor-pointer box-border flex flex-col justify-center items-center rounded p-3 text-center border-2 border-indigo-600 text-indigo-600":"cursor-pointer box-border flex flex-col justify-center items-center border rounded p-3 text-center opacity-30",onClick:function(){return M(e)},children:[Object(j.jsx)("div",{className:"icon text-black",children:Object(j.jsx)(h,{name:s.icon})}),Object(j.jsx)("p",{class:"text-sm font-semibold pt-2",children:s.name}),Object(j.jsx)("p",{class:"text-xs pt-1",children:s.description})]})}))})]}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("label",{className:"font-semibold",children:"Request splitter:"}),Object(j.jsx)("div",{class:"w-1/2 pt-2",children:Object(j.jsxs)("div",{class:_?"cursor-pointer box-border flex flex-col justify-center items-center rounded p-3 text-center border-2 border-indigo-600 text-indigo-600":"cursor-pointer box-border flex flex-col justify-center items-center border rounded p-3 text-center opacity-30",onClick:function(){return z(!_)},children:[Object(j.jsx)("div",{className:"icon text-black",children:Object(j.jsx)(h,{name:"split"})}),Object(j.jsx)("p",{class:"text-sm font-semibold pt-2",children:"Use auto request spliter"}),Object(j.jsx)("p",{class:"text-xs pt-1",children:"It allows to exceed the limit of 2000 patents per request by splitting it into several sub-request"})]})})]}),Object(j.jsx)("div",{className:"mt-4 italic text-sm text-gray-800",children:"Fields marked with * are mandatory."}),Object(j.jsx)("input",{className:"w-64 focus:outline-none px-8 py-2 rounded-md font-semibold text-white bg-indigo-500 cursor-pointer mt-4",type:"submit",value:"Submit"})]})})]})]})},m=function(e){var t=e.fusion_list;return Object(j.jsx)("div",{className:"mt-4 p-4 border border-gray-200 rounded",children:Object(j.jsxs)("div",{className:"flex flex-row justify-between items-center",children:[Object(j.jsxs)("p",{className:"font-semibold mr-3",children:[!t.start&&!t.end&&"La fusion des donn\xe9es va commencer",t.start&&!t.end&&"Les donn\xe9es sont en cours de fusion",t.end&&"La fusion des donn\xe9es est termin\xe9"]}),!t.end&&Object(j.jsxs)("svg",{className:"animate-spin -ml-1 h-5 w-5 text-indigo-600",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})]})})},u=function(e){var t=e.dir,s=e.data,c=e.showLoading,a=n.a.useState(!1),r=Object(d.a)(a,2),i=r[0],o=r[1],h=n.a.useCallback((function(){o(!0),fetch("http://localhost:5000/api/v1/requests/"+t+"/interface",{method:"POST"}).then((function(e){return e.json()})).then((function(e){o(!1)}))}),[t]);return Object(j.jsxs)("div",{className:"pb-4 flex justify-between",children:[Object(j.jsxs)("div",{className:"flex items-center",children:[Object(j.jsx)(l.b,{to:"/app/requests",className:"focus:outline-none p-2 rounded-md font-semibold text-white bg-gray-600",children:Object(j.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M15 19l-7-7 7-7"})})}),Object(j.jsxs)("div",{className:"ml-4",children:[Object(j.jsx)("h1",{className:"text-3xl font-semibold leading-7",children:t}),Object(j.jsx)("h2",{className:"text-lg",children:s.cql&&s.cql.requete})]})]}),Object(j.jsxs)("div",{className:"flex items-center",children:[s.done&&Object(j.jsxs)(j.Fragment,{children:[Object(j.jsx)("button",{className:"focus:outline-none p-2 rounded-md font-semibold text-white bg-red-500 mr-2 flex justify-center items-center",onClick:h,children:i?Object(j.jsxs)("svg",{className:"animate-spin h-6 w-6 text-white",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]}):Object(j.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})})}),Object(j.jsx)("a",{target:"_blank",rel:"noreferrer",href:"/DATA/"+t+".html",className:"focus:outline-none px-8 py-2 rounded-md font-semibold text-white bg-indigo-500",children:"Voir les donn\xe9es"})]}),!s.done&&c&&Object(j.jsxs)("div",{className:"focus:outline-none px-4 py-2 rounded-md font-semibold text-white bg-indigo-400 flex justify-center items-center",children:[Object(j.jsxs)("svg",{className:"animate-spin -ml-1 mr-3 h-5 w-5 text-white",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]}),"Chargements"]})]})]})},p=function(){return Object(j.jsxs)("div",{className:"mt-4 p-4 border border-gray-200 flex flex-row justify-between rounded",children:[Object(j.jsx)("p",{children:"Verification du nombre de ressource associ\xe9 \xe0 la requete"}),Object(j.jsx)("div",{children:Object(j.jsxs)("svg",{className:"animate-spin -ml-1 h-5 w-5 text-indigo-600",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})})]})},f=(new Date).getFullYear(),O=Array.from({length:30},(function(e,t){return f-t})),w=function(e){var t=e.dir,s=e.to_be_found,c=n.a.useState(!1),a=Object(d.a)(c,2),r=a[0],l=a[1],i=n.a.useState(f),o=Object(d.a)(i,2),h=o[0],b=o[1],x=n.a.useMemo((function(){return s&&(s.amount>=1e4?"Plus de 10000":s.amount)}),[s]),m=n.a.useCallback((function(){var e=new FormData;e.append("date",h),fetch("http://localhost:5000/api/v1/requests/"+t+"/split",{method:"POST",body:e}).then((function(e){return e.json()})).then((function(e){}))}),[h,t]),u=n.a.useCallback((function(e){b(e),l(!1)}),[b]);return Object(j.jsxs)("div",{className:"mt-4 p-4 bg-indigo-600 flex flex-row justify-between rounded items-center text-white",children:[Object(j.jsxs)("div",{children:[Object(j.jsxs)("p",{className:"font-bold text-lg",children:[x," \xe9l\xe9ments ont \xe9t\xe9 trouv\xe9s"]}),Object(j.jsx)("p",{className:"text-sm",children:s.need_spliter?"\xc0 partir de quelle ann\xe9e voulez vous r\xe9cuperer les donn\xe9es ?":"Il n'est pas necessaire de d\xe9couper la requete, le traiement va bient\xf4t commencer"})]}),s.need_spliter&&Object(j.jsxs)("div",{className:"flex flex-row mt-1",children:[Object(j.jsx)("div",{className:"w-32",children:Object(j.jsx)("div",{children:Object(j.jsxs)("div",{className:"relative text-black",children:[Object(j.jsxs)("button",{type:"button",className:"relative w-full bg-white border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 font-semibold","aria-haspopup":"listbox","aria-expanded":"true","aria-labelledby":"listbox-label",onClick:function(){return l(!r)},children:[Object(j.jsx)("span",{className:"flex items-center",children:Object(j.jsx)("span",{className:"ml-3 block truncate",children:h})}),Object(j.jsx)("span",{className:"ml-3 absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none",children:Object(j.jsx)("svg",{className:"h-5 w-5 text-gray-400",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",fill:"currentColor","aria-hidden":"true",children:Object(j.jsx)("path",{"fill-rule":"evenodd",d:"M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z","clip-rule":"evenodd"})})})]}),Object(j.jsx)("ul",{style:{maxHeight:200},className:"absolute z-10 mt-2 w-full bg-white shadow-lg rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"+(r?" opacity-100":" transition ease-in duration-100 opacity-0"),tabindex:"-1",role:"listbox","aria-labelledby":"listbox-label","aria-activedescendant":"listbox-option-3",children:O.map((function(e){return Object(j.jsx)("li",{className:"text-gray-900 cursor-default select-none relative py-2 pl-3 pr-9",id:"listbox-option-0",role:"option",onClick:function(){return u(e)},children:Object(j.jsx)("div",{className:"flex items-center",children:Object(j.jsx)("span",{className:"font-normal ml-3 block truncate",children:e})})})}))})]})})}),Object(j.jsx)("button",{type:"button",className:"bg-green-500 ml-2 px-2 rounded","aria-label":"Suivant",onClick:function(){return m()},children:Object(j.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-6 w-6",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M17 8l4 4m0 0l-4 4m4-4H3"})})})]})]})},v=function(e){var t=e.process_list,s=e.hide_result;return Object(j.jsxs)("div",{className:"mt-4 p-4 border border-gray-200 rounded",children:[Object(j.jsxs)("div",{className:"flex flex-row justify-between items-center",children:[Object(j.jsxs)("p",{className:"font-semibold mr-3",children:[!t.start&&!t.end&&"La r\xe9cuperation des donn\xe9es va commencer",t.start&&!t.end&&"Les donn\xe9es sont en cours de r\xe9cup\xe9ration",t.end&&"La r\xe9cup\xe9ration des donn\xe9es est termin\xe9"]}),!t.end&&Object(j.jsxs)("svg",{className:"animate-spin -ml-1 h-5 w-5 text-indigo-600",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})]}),!s&&Object(j.jsxs)(j.Fragment,{children:[Object(j.jsx)("hr",{className:"border-gray-200 my-4"}),Object(j.jsx)("div",{children:t.queue_list&&t.queue_list.map((function(e){return Object(j.jsxs)("div",{className:"flex flex-row justify-between",children:[Object(j.jsx)("p",{children:e}),Object(j.jsx)("div",{children:t.done_list.includes(e)&&Object(j.jsx)("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4 text-indigo-600",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:Object(j.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"})})})]})}))})]})]})},g=function(e){var t=e.name,s=e.value,c=e.max_value,a=n.a.useMemo((function(){return s/c*100||0}),[s,c]),r=null===s||null===c?"En attente...":a+"%";return Object(j.jsxs)("div",{class:"ProgressBar",children:[Object(j.jsxs)("div",{class:"flex justify-between",children:[Object(j.jsx)("p",{children:t}),Object(j.jsx)("p",{children:r})]}),Object(j.jsx)("div",{class:"relative pt-1",children:Object(j.jsx)("div",{class:"overflow-hidden h-2 mb-4 text-xs flex rounded bg-orange-200",children:Object(j.jsx)("div",{style:{width:a+"%"},class:"shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-indigo-500"})})})]})},N=function(e){var t=e.data;return Object(j.jsxs)("div",{className:"mt-4 p-4 border border-gray-200 rounded",children:[Object(j.jsxs)("div",{className:"flex flex-row justify-between items-center",children:[Object(j.jsxs)("p",{className:"font-semibold mr-3",children:[!t.progress&&!t.done&&"La requete va bient\xf4t se lancer",t.progress&&!t.done&&"La requete est en cours",t.done&&"La requete est termin\xe9"]}),!t.done&&Object(j.jsxs)("svg",{className:"animate-spin -ml-1 h-5 w-5 text-indigo-600",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})]}),!1===t.done&&t.progress&&Object(j.jsxs)(j.Fragment,{children:[Object(j.jsx)("hr",{className:"border-gray-200 my-4"}),Object(j.jsx)("div",{children:Object.keys(t.progress).map((function(e,s){return Object(j.jsx)(g,{name:e,value:t.progress[e].value,max_value:t.progress[e].max_value},e)}))})]})]})},y=function(e){var t=e.spliter_result,s=e.hide_result;return Object(j.jsxs)("div",{className:"mt-4 p-4 border border-gray-200 rounded",children:[Object(j.jsxs)("div",{className:"flex flex-row justify-between",children:[Object(j.jsxs)("div",{className:"flex flex-row justify-between items-center",children:[Object(j.jsxs)("p",{className:"font-semibold mr-3",children:[!t.start&&!t.end&&"La s\xe9paration de la requete va commencer",t.start&&!t.end&&"S\xe9paration de la requete en cours",t.end&&"La s\xe9paration de la requete est termin\xe9"]}),!t.end&&Object(j.jsxs)("svg",{className:"animate-spin -ml-1 h-5 w-5 text-indigo-600",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})]}),Object(j.jsx)("p",{className:"font-semibold",children:t.cumulative?t.cumulative:0})]}),t.requests&&!s&&Object(j.jsxs)(j.Fragment,{children:[Object(j.jsx)("hr",{className:"border-gray-200 my-4"}),Object(j.jsx)("div",{children:t.requests&&t.requests.map((function(e){return Object(j.jsxs)("div",{className:"flex flex-row justify-between",children:[Object(j.jsx)("p",{children:e.name}),Object(j.jsx)("p",{children:e.find})]})}))})]})]})},k=function(){var e=Object(i.g)().dir,t=n.a.useState({}),s=Object(d.a)(t,2),c=s[0],a=s[1],r=n.a.useCallback((function(){fetch("http://localhost:5000/api/v1/requests/"+e).then((function(e){return e.json()})).then((function(e){200===e.code&&(console.log(e.data),a(e.data))}))}),[e]);n.a.useEffect((function(){r()}),[r]),n.a.useEffect((function(){console.log("Opening the SSE connection");var t=new EventSource("http://localhost:5000/api/v1/listen");return t.onmessage=function(t){var s=JSON.parse(t.data);console.log(s),s.data.directory===e&&r()},function(){t.close()}}),[r,e]);var l=n.a.useMemo((function(){return"SPLITER_RUN"===c.state}),[c]),o=n.a.useMemo((function(){return l&&c.data&&!c.data.to_be_found}),[c,l]),h=n.a.useMemo((function(){return l&&c.data&&c.data.spliter_result}),[c,l]),b=n.a.useMemo((function(){return l&&c.data&&c.data.to_be_found&&!h}),[c,l,h]),x=n.a.useMemo((function(){return l&&c.data&&c.data.process_list}),[c,l]),f=n.a.useMemo((function(){return l&&c.data&&c.data.fusion_list}),[c,l]),O=n.a.useMemo((function(){return b&&c.data.to_be_found}),[c,b]),g=n.a.useMemo((function(){return h&&c.data.spliter_result}),[c,h]),k=n.a.useMemo((function(){return x&&c.data.process_list}),[c,x]),_=n.a.useMemo((function(){return f&&c.data.fusion_list}),[c,f]),z=n.a.useMemo((function(){return f&&_.end}),[f,_]);return Object(j.jsx)("div",{className:"container mx-auto",children:Object(j.jsx)("div",{className:"flex justify-center items-center",children:Object(j.jsx)("div",{className:"flex flex-col w-full lg:w-3/5 mb-12 bg-white p-8 rounded shadow",children:c.cql?Object(j.jsxs)(j.Fragment,{children:[Object(j.jsx)(u,{dir:e,data:c,showLoading:!l}),Object(j.jsx)("hr",{className:"border-gray-200"}),l?Object(j.jsxs)(j.Fragment,{children:[o&&Object(j.jsx)(p,{}),b&&Object(j.jsx)(w,{dir:e,to_be_found:O}),h&&Object(j.jsx)(y,{spliter_result:g,hide_result:x}),x&&Object(j.jsx)(v,{process_list:k,hide_result:f}),f&&Object(j.jsx)(m,{fusion_list:_}),z&&Object(j.jsx)(N,{data:c})]}):Object(j.jsx)(j.Fragment,{children:Object(j.jsx)(N,{data:c})})]}):null})})})},_=function(){return Object(j.jsx)("div",{className:"container mx-auto",children:Object(j.jsx)("div",{className:"flex justify-center items-center",children:Object(j.jsxs)("div",{className:"flex flex-col w-full lg:w-3/5 mb-12 bg-white p-8 rounded shadow",children:[Object(j.jsxs)("div",{children:[Object(j.jsx)("h1",{className:"text-3xl font-semibold mb-2 text-gray-900",children:"Get Started"}),Object(j.jsx)("hr",{}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("h2",{className:"font-semibold",id:"Register",children:"Register the use of P2N"}),Object(j.jsx)("hr",{}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("p",{className:"text-gray-800 text-sm mb-4 text-justify",children:"You have first to register yourself at Espacenet and get a key to data access. So you must (if you already have it skip this step)"}),Object(j.jsxs)("ol",{className:"list-decimal text-gray-800 text-sm mb-3 text-justify",children:[Object(j.jsxs)("li",{children:["Go to the Open Patent Services (OPS) by opening the link :",Object(j.jsx)("br",{}),Object(j.jsx)("a",{className:"hover:underline",href:"https://www.epo.org/searching-for-patents/technical/espacenet/ops.html#tab1",children:" https://www.epo.org/searching-for-patents/technical/espacenet/ops.html#tab1"})]}),Object(j.jsxs)("li",{children:["Click on the \u201c",Object(j.jsx)("b",{children:"Register"}),"\u201d button and fulfill the form"]}),Object(j.jsx)("li",{children:"Wait until you receive the email confirmation of you register from EPO Developer Portal."}),Object(j.jsxs)("li",{children:["Log in the EPO Developer Portal :",Object(j.jsx)("br",{})," ",Object(j.jsx)("a",{className:"hover:underline",href:" https://developers.epo.org/user/login",children:"https://developers.epo.org/user/login"})," "]}),Object(j.jsxs)("li",{children:["Select the option \u201c",Object(j.jsx)("b",{children:"My apps"}),"\u201d"]}),Object(j.jsxs)("li",{children:["Create and register the \u201c",Object(j.jsx)("b",{children:"Patent2Net"}),"\u201d application"]}),Object(j.jsxs)("li",{children:[" The system returns the API credentials key and secret, similar to that shown bellow (this one is invalid, of course):",Object(j.jsx)("br",{}),Object(j.jsx)("pre",{className:"code border-dashed border-2 border-orange-600 bg-orange-100",children:"vmrr7AaAGIl794E6VunJ6PzjbkfajwLW,KHzH4fGM7opMhDDD"})]}),Object(j.jsx)("li",{children:"Copy/paste the key in the textbox and click on confirm. It will create a file in your install of Patent2Net who will let you have full use of it. "})]})]})]}),Object(j.jsx)("div",{className:"mt-4",children:Object(j.jsxs)("form",{action:"http://localhost:5000/get_started/stocked",method:"post",children:[Object(j.jsxs)("div",{children:[Object(j.jsx)("label",{className:"font-semibold",children:"cles-epo * :"}),Object(j.jsx)("p",{className:"pt-2 pb-2 text-sm italic text-gray-800",children:"Paste in the textbox the key provided by EPO."})]}),Object(j.jsx)("div",{className:"mb-2",children:Object(j.jsx)("input",{className:"px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border border-blueGray-300 outline-none focus:outline-none focus:ring w-full",type:"text",required:!0,placeholder:"vmrr7AaAGIl794E6VunJ6PzjbkfajwLW,KHzH4fGM7opMhDDD",name:"p2n_epo"})}),Object(j.jsx)("div",{className:"mt-4 italic text-sm text-gray-800",children:"Fields marked with * are mandatory."}),Object(j.jsx)("input",{className:"w-64 focus:outline-none px-8 py-2 rounded-md font-semibold text-white bg-indigo-500 cursor-pointer mt-4",type:"submit",value:"confirm",id:"pacing"})]})})]}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("h2",{className:"font-semibold",Id:"Archive_Content",children:"P2N Docker archive content"}),Object(j.jsx)("hr",{})]}),Object(j.jsx)("div",{className:"mt-2",children:Object(j.jsx)("div",{children:Object(j.jsxs)("ul",{className:"list-disc text-gray-800 text-sm mb-3 mt-3 text-justify ",children:[Object(j.jsxs)("li",{children:[" ",Object(j.jsx)("b",{children:"Dockerfile"})," : Mandatory for the install of P2N Docker"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Install_P2N.bat"})," : used to install all the P2N Content in Docker"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Run_P2N.bat"})," : Used to initiate P2N instance in Docker"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Stop_P2N.bat"})," : Used to stop P2N instance"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Copy Docker P2N"})," :",Object(j.jsxs)("ul",{children:[Object(j.jsx)("li",{children:"Copy_Docker_P2N.bat : Create a tar file with all the base content of your docker version"}),Object(j.jsx)("li",{children:"Load_Docker_P2N.bat : Import the tar file insde docker and create P2N image"})]})]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"P2N_Bash.bat"})," : Create a command prompt instance who interact with P2N Docker. ",Object(j.jsx)("a",{href:"https://docs.ip-tools.org/patent2net/usage/classic.html",target:"_blank",className:"hover:underline",children:Object(j.jsx)("i",{children:"Click here for more details."})})]})]})})}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("h2",{className:"font-semibold",Id:"Interface_Directory",children:"P2N Interface directories"}),Object(j.jsx)("hr",{})]}),Object(j.jsx)("div",{className:"mt-2",children:Object(j.jsx)("div",{children:Object(j.jsxs)("ul",{className:"list-disc text-gray-800 text-sm mb-3 mt-3 text-justify ",children:[Object(j.jsxs)("li",{children:[" ",Object(j.jsx)("b",{children:" Home"})," : Default page. Explain how PatentNet can help you"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Get Started"})," : Explain how to use P2N Docker"]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Requests"})," : form used to execute requests to the EPO database "]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Index"})," : Display all the results of P2N "]}),Object(j.jsxs)("li",{children:[Object(j.jsx)("b",{children:"Download Data"})," : create a zip folder with all the datas contained in Index. Downloaded on your local machine"]})]})})})]})})})},z=(s(31),function(e){var t=e.version,s=n.a.useState(!1),c=Object(d.a)(s,2),a=c[0],r=c[1],l=n.a.useCallback((function(){r(!0),fetch("http://localhost:5000/updateP2N").then((function(e){r(!1)}))}),[]);return Object(j.jsx)("div",{className:"container mx-auto",children:Object(j.jsx)("div",{className:"flex justify-center items-center",children:Object(j.jsxs)("div",{className:"flex flex-col w-full lg:w-3/5 mb-12 bg-white p-8 rounded shadow",children:[Object(j.jsxs)("h1",{className:"text-3xl font-semibold mb-2 text-gray-900",children:["Patent2Net Docker Version : ",Object(j.jsx)("span",{class:"font-normal",children:t})," "]}),Object(j.jsx)("hr",{}),Object(j.jsx)("div",{className:"mt-4",children:Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsxs)("p",{className:"text-gray-800 text-sm mb-4 text-justify",children:["Patent2Net is a toolkit for patent information processing and statistical analysis for education and science.",Object(j.jsx)("br",{}),"Patent2Net helps to collect, study and analyze patent data from the European Patent Office\u2019s Open Patent Services API (OPS). ",Object(j.jsx)("br",{}),"Patent2Net is a free software dedicated to :"]}),Object(j.jsxs)("ul",{className:"list-disc text-gray-800 text-sm mb-3 text-justify",children:[Object(j.jsx)("li",{children:"provide statistical analysis and representations of a set of patents."}),Object(j.jsx)("li",{children:"promote the use of patent information in the academic field, nano and small firms, developing countries."}),Object(j.jsx)("li",{children:"study and practice how to collect, treat and communicate \u201ctextual bibliographic information\u201d and learn the automation process."})]}),Object(j.jsx)("p",{className:"text-gray-800 text-sm mb-4 text-justify",children:"Contributions are always welcome!"})]})}),Object(j.jsx)("hr",{}),Object(j.jsxs)("div",{className:"mt-4",children:[Object(j.jsx)("p",{className:"text-gray-800 text-sm mb-4 text-justify",children:"To update your P2N version click on the button : "}),Object(j.jsxs)("button",{onClick:l,className:"w-64 focus:outline-none px-8 py-2 rounded-md font-semibold text-white bg-red-500 cursor-pointer mt-4 flex flex-ror justify-center items-center",children:["Update P2N",a&&Object(j.jsxs)("svg",{className:"animate-spin ml-1 h-5 w-5 text-white",xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24",children:[Object(j.jsx)("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"}),Object(j.jsx)("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"})]})]})]})]})})})}),C=function(){var e=n.a.useState({}),t=Object(d.a)(e,2),s=t[0],c=t[1];return n.a.useEffect((function(){fetch("http://localhost:5000/api/v1/requests").then((function(e){return e.json()})).then((function(e){e.data&&c(e.data),console.log(e.data)}))}),[]),Object(j.jsx)("div",{className:"container mx-auto",children:Object(j.jsx)("div",{className:"flex justify-center items-center",children:Object(j.jsx)("div",{className:"flex flex-col w-full lg:w-3/5 mb-12 bg-white p-8 rounded shadow",children:Object(j.jsxs)("div",{children:[Object(j.jsx)("h1",{className:"text-3xl font-semibold mb-2 text-gray-900",children:"Index"}),Object(j.jsx)("hr",{}),Object(j.jsx)("div",{className:"mt-4",children:s.done&&s.done.map((function(e){return Object(j.jsx)("div",{children:Object(j.jsx)("a",{rel:"noreferrer",target:"_blank",href:"http://localhost:5000/DATA/"+e+".html",children:e})},e)}))})]})})})})};r.a.render(Object(j.jsx)(n.a.StrictMode,{children:Object(j.jsxs)(l.a,{children:[Object(j.jsx)("nav",{className:"bg-indigo-600 p-2 mt-0 w-full z-10 top-0 shadow text-white",children:Object(j.jsxs)("div",{className:"container mx-auto flex flex-wrap items-center",children:[Object(j.jsx)("div",{className:"flex w-full md:w-1/2 justify-center md:justify-start font-extrabold",children:Object(j.jsx)("a",{className:"no-underline hover:no-underline",href:"/",children:Object(j.jsx)("span",{className:"text-2xl pl-2",children:" Patent2Net"})})}),Object(j.jsx)("div",{className:"flex w-full pt-2 content-center justify-between md:w-1/2 md:justify-end",children:Object(j.jsxs)("ul",{className:"list-reset flex justify-between flex-1 md:flex-none items-center",children:[Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)(l.b,{to:"/app/",className:"inline-block no-underline hover:underline py-2 px-4",children:"Home"})}),Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)(l.b,{to:"/app/get_started",className:"inline-block no-underline hover:underline py-2 px-4",children:"Get Started"})}),Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)(l.b,{to:"/app/requests",className:"inline-block py-2 px-4 no-underline font-medium",children:"Requests"})}),Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)(l.b,{to:"/app/index",className:"inline-block no-underline hover:underline py-2 px-4",children:"Index"})}),Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)("a",{href:"/downloadDat",className:"inline-block no-underline hover:underline py-2 px-4",children:"Download Data"})}),Object(j.jsx)("li",{className:"mr-3",children:Object(j.jsx)("a",{href:"/doc/_build/html/index.html",className:"inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-orange-500 hover:bg-white mt-4 lg:mt-0",children:"Documentation"})})]})})]})}),Object(j.jsx)("div",{className:"my-10",children:Object(j.jsxs)(i.c,{children:[Object(j.jsx)(i.a,{path:"/app/get_started",children:Object(j.jsx)(_,{})}),Object(j.jsx)(i.a,{path:"/app/requests/:dir",children:Object(j.jsx)(k,{})}),Object(j.jsx)(i.a,{path:"/app/requests",children:Object(j.jsx)(x,{})}),Object(j.jsx)(i.a,{path:"/app/index",children:Object(j.jsx)(C,{})}),Object(j.jsx)(i.a,{exact:!0,path:"/app/",children:Object(j.jsx)(z,{})})]})})]})}),document.getElementById("root"))}},[[32,1,2]]]); +//# sourceMappingURL=main.88ea6b9f.chunk.js.map \ No newline at end of file diff --git a/web_app/build/static/js/main.88ea6b9f.chunk.js.map b/web_app/build/static/js/main.88ea6b9f.chunk.js.map new file mode 100644 index 00000000..d33800b0 --- /dev/null +++ b/web_app/build/static/js/main.88ea6b9f.chunk.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["pages/icon.js","pages/Requests.js","pages/Request/FusionList/index.js","pages/Request/Header/index.js","pages/Request/PatentCount/index.js","pages/Request/PatentCountResult/index.js","pages/Request/ProcessList/index.js","components/ProgressBar.js","pages/Request/Progress/index.js","pages/Request/RequestSplit/index.js","pages/Request/index.js","pages/GetStarted.js","pages/Home.js","pages/DataIndex.js","index.js"],"names":["Icon","name","xmlns","className","viewBox","d","fill","stroke","strokeLinecap","strokeLinejoin","strokeWidth","x","y","stroke-width","stroke-miterlimit","stroke-linecap","data-name","stroke-linejoin","all_options","description","icon","App","React","useState","request","setRequest","directory","setDirectory","options","setOptions","requests","setRequests","p2nAuto","setP2nAuto","history","useHistory","useEffect","fetch","then","response","json","data","console","log","toggleCheckbox","useCallback","key","includes","filter","value","onSubmit","event","preventDefault","FormData","append","join","method","body","push","p2n_dir","done","map","to","class","in_progress","global_progress","style","done_step_count","total_step_count","progress_step_count","onChange","e","target","type","required","placeholder","id","pattern","title","Object","keys","index","option","onClick","FusionList","fusion_list","start","end","cx","cy","r","RequestHeader","dir","showLoading","isViewUpdate","setIsViewUpdate","updateView","cql","requete","rel","href","PatentCount","currentYear","Date","getFullYear","years","Array","from","length","_","i","PatentCountResult","to_be_found","yearOpen","setYearOpen","year","setYear","to_be_found_amount","useMemo","amount","runSpliter","onSelectYear","need_spliter","aria-haspopup","aria-expanded","aria-labelledby","aria-hidden","fill-rule","clip-rule","maxHeight","tabindex","role","aria-activedescendant","aria-label","ProcessList","process_list","hide_result","queue_list","file","done_list","ProgressBar","max_value","percent","text","Progress","progress","RequestSplit","spliter_result","cumulative","find","Request","useParams","setData","updateData","code","source","EventSource","onmessage","JSON","parse","close","isSpliterRun","state","showPatentCount","showRequestSplit","showPatentCountResult","showProgressList","showFusion","showRequestProgress","GetStarted","action","Id","Home","version","isUpdate","setIsUpdate","update","DataIndex","ReactDOM","render","StrictMode","path","Requests","exact","document","getElementById"],"mappings":"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","file":"static/js/main.88ea6b9f.chunk.js","sourcesContent":["\r\nconst Icon = ({ name }) => {\r\n\r\n switch(name) {\r\n case \"family\":\r\n return (\r\n \r\n )\r\n case \"image\":\r\n return (\r\n \r\n )\r\n case \"network\":\r\n return (\r\n \r\n )\r\n case \"nodes\":\r\n return (\r\n \r\n )\r\n case \"archive\":\r\n return (\r\n \r\n )\r\n case \"map\":\r\n return (\r\n \r\n )\r\n case \"table\":\r\n return (\r\n \r\n )\r\n case \"carrot\":\r\n return (\r\n \r\n )\r\n case \"chart-pie\":\r\n return (\r\n \r\n )\r\n case \"cluster\":\r\n return (\r\n \r\n )\r\n case \"infographic\":\r\n return (\r\n \r\n )\r\n case \"split\":\r\n return (\r\n \r\n )\r\n default:\r\n return null\r\n }\r\n}\r\n\r\nexport default Icon;","import React from \"react\";\nimport { useHistory } from \"react-router\";\nimport { Link } from \"react-router-dom\";\nimport Icon from \"./icon\";\n\nconst all_options = {\n \"p2n_family\": {\n name: \"p2n family\",\n description: \"run family data acquisition\",\n icon: \"family\"\n },\n \"p2n_image\": {\n name: \"p2n images\",\n description: \"Fetch images\",\n icon: \"image\"\n },\n \"p2n_network\": {\n name: \"p2n networks\",\n description: \"Build various artefacts for data exploration based on network graphs\",\n icon: \"network\"\n },\n \"p2n_freeplane\": {\n name: \"p2n freeplane\",\n description: \"Build mind map for Freeplane\",\n icon: \"nodes\"\n },\n \"p2n_bibfile\": {\n name: \"p2n bibfile\",\n description: \"Export data in bibfile format\",\n icon: \"archive\"\n },\n \"p2n_map\": {\n name: \"p2n maps\",\n description: \"Build maps of country coverage of patents, as well as applicants and inventors\",\n icon: \"map\"\n },\n \"p2n_tables\": {\n name: \"p2n tables\",\n description: \"Export various artefacts for tabular data exploration\",\n icon: \"table\"\n },\n \"p2n_carrot\": {\n name: \"p2n carrot\",\n description: \"Export data to XML suitable for using in Carro\",\n icon: \"carrot\"\n },\n \"p2n_iramuteq\": {\n name: \"p2n iramuteq\",\n description: \"Fetch more data and export it to suitable format for using in Iramuteq\",\n icon: \"chart-pie\"\n },\n \"p2n_cluster\": {\n name: \"p2n cluster\",\n description: \"Double clustering system based on non so trivial words\",\n icon: \"cluster\"\n },\n}\n\nfunction App() {\n\n const [ request, setRequest ] = React.useState(\"\");\n const [ directory, setDirectory ] = React.useState(\"\");\n const [ options, setOptions ] = React.useState([\n \"p2n_content\",\n \"p2n_gather_biblio\",\n \"p2n_family\",\n \"p2n_image\",\n \"p2n_network\",\n \"p2n_freeplane\",\n \"p2n_bibfile\",\n \"p2n_map\",\n \"p2n_tables\",\n \"p2n_carrot\",\n \"p2n_iramuteq\",\n \"p2n_cluster\",\n ]);\n const [ requests, setRequests ] = React.useState({});\n const [ p2nAuto, setP2nAuto ] = React.useState(false);\n\n const history = useHistory();\n\n React.useEffect(() => {\n fetch(\"http://localhost:5000/api/v1/requests\")\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {\n if (json.data) {\n setRequests(json.data)\n }\n console.log(json.data)\n });\n }, []);\n\n const toggleCheckbox = React.useCallback((key) => {\n setOptions((options) => !options.includes(key) ? [...options, key] : [...options.filter((value) => value !== key)] )\n }, [setOptions])\n\n const onSubmit = React.useCallback((event) => {\n event.preventDefault()\n\n const data = new FormData();\n data.append(\"p2n_req\", request);\n data.append(\"p2n_dir\", directory);\n data.append(\"p2n_options\", options.join(','));\n data.append(\"p2n_auto\", p2nAuto ? \"true\" : \"false\")\n\n console.log(data)\n\n fetch('http://localhost:5000/api/v1/requests', { \n method: 'POST',\n body: data\n })\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {\n console.log(json)\n history.push(\"/app/requests/\" + json.data.p2n_dir );\n });\n \n\n }, [request, directory, options, history, p2nAuto])\n\n return (\n
\n
\n \n
\n

Requêtes précédentes

\n\n { requests.done && requests.done.map((name) => (\n {name}\n ))}\n\n { !requests.done && (\n
\n \n \n \n
\n ) }\n
\n \n
\n\n
\n

Requêtes en cours

\n
\n
\n { requests.in_progress && requests.in_progress.map((name) => (\n \n

{ name }

\n {\n requests.global_progress && requests.global_progress[name] && (\n
\n
\n
\n
\n )\n }\n \n ))}\n\n { !requests.in_progress && (\n
\n \n \n \n
\n ) }\n
\n
\n
\n
\n \n
\n

Patent2Net toolkit

\n
\n
\n\n
\n
\n \n

Enter in the textbox a valid espacenet smart search query for your patent research.

\n
\n
\n setRequest(e.target.value)}\n className=\"px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border border-blueGray-300 outline-none focus:outline-none focus:ring w-full\"\n type=\"text\"\n required\n placeholder=\"TA=lentille\"\n name=\"p2n_req\"\n id=\"p2n_reqBtn\"\n />\n
\n\n
\n \n

Enter in the textbox where your patent research will be stocked.

\n
\n
\n setDirectory(e.target.value)}\n className=\"px-3 py-4 placeholder-blueGray-300 text-blueGray-600 relative bg-white bg-white rounded text-base border border-blueGray-300 outline-none focus:outline-none focus:ring w-full\" \n type=\"text\" \n required \n placeholder=\"lentille\" \n name=\"p2n_dir\" pattern=\"[A-Za-z0-9_-]{1,}\" \n title=\"Use only lowercase [a-z], Uppercase [A-Z], Numbers[0-9], Underscore[_] and Hyphen [-]\" \n />\n
\t\t\t\t\n\n
\n \n

Click on the checkbox to specify the elements you need in your research:

\n \n
\n {Object.keys(all_options).map((key, index) => {\n let option = all_options[key]\n return (\n
toggleCheckbox(key)}\n >\n
\n \n
\n

{option[\"name\"]}

\n

{option[\"description\"]}

\n
\n //

\n // toggleCheckbox(key) }\n // />\n // \n //

\n )\n })}\n
\n
\n
\n \n
\n
setP2nAuto(!p2nAuto)}\n >\n
\n \n
\n

Use auto request spliter

\n

\n It allows to exceed the limit of 2000 patents per request by splitting it into several sub-request\n

\n
\n
\n
\n
\n Fields marked with * are mandatory.\n
\n \n
\n
\n
\n
\n );\n}\n\nexport default App;\n","\nconst FusionList = ({ fusion_list }) => (\n
\n
\n

\n { (!fusion_list.start && !fusion_list.end) && \"La fusion des données va commencer\" }\n { (fusion_list.start && !fusion_list.end) && \"Les données sont en cours de fusion\" }\n { (fusion_list.end) && \"La fusion des données est terminé\" }\n

\n { !fusion_list.end && (\n \n \n \n \n )}\n
\n
\n)\n\nexport default FusionList","import React from \"react\";\nimport { Link } from \"react-router-dom\";\n\nconst RequestHeader = ({ dir, data, showLoading }) => {\n\n const [isViewUpdate, setIsViewUpdate] = React.useState(false);\n\n const updateView = React.useCallback(() => {\n setIsViewUpdate(true)\n fetch('http://localhost:5000/api/v1/requests/' + dir + \"/interface\", { \n method: 'POST'\n })\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {\n setIsViewUpdate(false)\n });\n }, [dir])\n\n\n return (\n
\n
\n \n \n \n \n \n
\n

{ dir }

\n

{ data.cql && data.cql.requete }

\n
\n
\n
\n { \n data.done && (\n <>\n \n \n Voir les données\n \n \n ) \n }\n {\n !data.done && showLoading && (\n \n \n \n \n \n Chargements\n
\n )\n }\n\n
\n \n )\n\n}\n\nexport default RequestHeader;","\nconst PatentCount = () => (\n
\n

Verification du nombre de ressource associé à la requete

\n
\n \n \n \n \n
\n
\n)\n\nexport default PatentCount","import React from \"react\"\n\nconst currentYear = new Date().getFullYear();\nconst years = Array.from({length: 30}, (_, i) => currentYear - i)\n\nconst PatentCountResult = ({ dir, to_be_found }) => {\n\n const [yearOpen, setYearOpen] = React.useState(false);\n const [year, setYear] = React.useState(currentYear)\n\n const to_be_found_amount = React.useMemo(() => (\n to_be_found && (to_be_found.amount >= 10000 ? `Plus de 10000` : to_be_found.amount)\n ), [to_be_found])\n\n const runSpliter = React.useCallback(() => {\n const data = new FormData();\n data.append(\"date\", year);\n\n fetch('http://localhost:5000/api/v1/requests/' + dir + \"/split\", { \n method: 'POST',\n body: data\n })\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {});\n }, [year, dir])\n\n const onSelectYear = React.useCallback((year) => {\n setYear(year)\n setYearOpen(false)\n }, [setYear])\n\n return (\n
\n
\n

{to_be_found_amount} éléments ont été trouvés

\n

\n {\n to_be_found.need_spliter ?\n \"À partir de quelle année voulez vous récuperer les données ?\" : \n \"Il n'est pas necessaire de découper la requete, le traiement va bientôt commencer\"\n }\n

\n
\n {\n to_be_found.need_spliter && (\n
\n
\n
\n
\n \n\n
    \n \n { years.map((year) => (\n
  • onSelectYear(year)}>\n
    \n \n \n { year }\n \n
    \n
  • \n ))}\n
\n
\n
\n
\n \n
\n )\n }\n \n
\n )\n\n}\n\nexport default PatentCountResult","\nconst ProcessList = ({ process_list, hide_result }) => (\n
\n
\n

\n { (!process_list.start && !process_list.end) && \"La récuperation des données va commencer\" }\n { (process_list.start && !process_list.end) && \"Les données sont en cours de récupération\" }\n { (process_list.end) && \"La récupération des données est terminé\" }\n

\n { !process_list.end && (\n \n \n \n \n )}\n
\n \n {\n !hide_result && (\n <>\n
\n
\n { process_list.queue_list && process_list.queue_list.map((file) => (\n
\n

{file}

\n
\n {\n process_list.done_list.includes(file) && (\n \n \n \n )\n }\n
\n
\n ))}\n
\n \n )\n }\n \n \n
\n)\n\n\n\nexport default ProcessList","import React from \"react\"\n\nconst ProgressBar = ({ name, value, max_value }) => {\n\n const percent = React.useMemo(() => (value / max_value * 100) || 0, [value, max_value])\n const text = value === null || max_value === null ? \"En attente...\" : percent + \"%\"\n\n\n return (\n
\n
\n

{ name }

\n

{ text }

\n
\n
\n
\n
\n
\n
\n
\n )\n}\n\nexport default ProgressBar","import ProgressBar from \"../../../components/ProgressBar\";\n\nconst Progress = ({ data }) => (\n
\n
\n

\n { (!data.progress && !data.done) && \"La requete va bientôt se lancer\" }\n { (data.progress && !data.done) && \"La requete est en cours\" }\n { (data.done) && \"La requete est terminé\" }\n

\n { !data.done && (\n \n \n \n \n )}\n
\n {\n (data.done === false && data.progress && (\n <>\n
\n
\n {Object.keys(data.progress).map((key, index) => (\n \n ))} \n
\n \n ))\n }\n
\n)\n\nexport default Progress","\nconst RequestSplit = ({spliter_result, hide_result}) => {\n \n return (\n
\n
\n
\n

\n { (!spliter_result.start && !spliter_result.end) && \"La séparation de la requete va commencer\" }\n { (spliter_result.start && !spliter_result.end) && \"Séparation de la requete en cours\" }\n { (spliter_result.end) && \"La séparation de la requete est terminé\" }\n\n

\n { !spliter_result.end && (\n \n \n \n \n )}\n
\n

{ (spliter_result.cumulative) ? spliter_result.cumulative : 0 }

\n
\n { spliter_result.requests && !hide_result && (\n <>\n
\n
\n { spliter_result.requests && spliter_result.requests.map((request) => (\n
\n

{request.name}

\n

{request.find}

\n
\n ))}\n
\n \n )}\n\n
\n )\n}\n\nexport default RequestSplit","import React from \"react\";\nimport { useHistory, useParams } from \"react-router\";\nimport { Link } from \"react-router-dom\";\nimport FusionList from \"./FusionList\";\nimport RequestHeader from \"./Header\";\nimport PatentCount from \"./PatentCount\";\nimport PatentCountResult from \"./PatentCountResult\";\nimport ProcessList from \"./ProcessList\";\nimport Progress from \"./Progress\";\nimport RequestSplit from \"./RequestSplit\";\n\n\nconst Request = () => {\n let { dir } = useParams();\n\n const [data, setData] = React.useState({});\n\n const updateData = React.useCallback(() => {\n fetch(\"http://localhost:5000/api/v1/requests/\" + dir)\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {\n if(json.code === 200) {\n console.log(json.data)\n setData(json.data)\n }\n });\n }, [dir])\n \n React.useEffect(() => {\n updateData()\n }, [updateData]);\n\n React.useEffect(() => {\n console.log(\"Opening the SSE connection\")\n var source = new EventSource(\"http://localhost:5000/api/v1/listen\");\n source.onmessage = function(event) {\n const data = JSON.parse(event.data)\n console.log(data)\n if(data.data.directory === dir) {\n updateData()\n }\n }\n return () => {\n source.close()\n }\n }, [updateData, dir])\n \n const isSpliterRun = React.useMemo(() => (\n data.state === \"SPLITER_RUN\"\n ), [data])\n\n const showPatentCount = React.useMemo(() => (\n isSpliterRun && data.data && !data.data.to_be_found\n ), [data, isSpliterRun])\n\n const showRequestSplit = React.useMemo(() => (\n isSpliterRun && data.data && data.data.spliter_result\n ), [data, isSpliterRun])\n\n const showPatentCountResult = React.useMemo(() => (\n isSpliterRun && data.data && data.data.to_be_found && !showRequestSplit\n ), [data, isSpliterRun, showRequestSplit])\n\n const showProgressList = React.useMemo(() => (\n isSpliterRun && data.data && data.data.process_list\n ), [data, isSpliterRun])\n\n const showFusion = React.useMemo(() => (\n isSpliterRun && data.data && data.data.fusion_list\n ), [data, isSpliterRun])\n\n const to_be_found = React.useMemo(() => showPatentCountResult && data.data.to_be_found, [data, showPatentCountResult])\n\n const spliter_result = React.useMemo(() => showRequestSplit && data.data.spliter_result, [data, showRequestSplit])\n\n const process_list = React.useMemo(() => showProgressList && data.data.process_list, [data, showProgressList])\n\n const fusion_list = React.useMemo(() => showFusion && data.data.fusion_list, [data, showFusion])\n\n const showRequestProgress = React.useMemo(() => (\n showFusion && fusion_list.end\n ), [showFusion, fusion_list])\n\n return (\n
\n
\n
\n {\n data.cql ? (\n <>\n \n
\n {\n !isSpliterRun ? \n (\n <>\n \n \n ) : (\n <>\n {\n showPatentCount && ( )\n }\n {\n showPatentCountResult && ( )\n }\n {\n showRequestSplit && ( )\n }\n {\n showProgressList && ( )\n }\n {\n showFusion && ( )\n }\n {\n showRequestProgress && ( )\n }\n \n )\n }\n \n \n ) : null\n }\n
\n
\n
\n ) \n}\n\nexport default Request;","\nconst GetStarted = () => {\n \n return (\n
\n
\n
\n
\n

Get Started

\n
\n \n
\n\n

Register the use of P2N

\n
\n\n
\n

You have first to register yourself at Espacenet and get a key to data access. So you must (if you already have it skip this step)\n

\t\n \n
    \n
  1. Go to the Open Patent Services (OPS) by opening the link :
    \n https://www.epo.org/searching-for-patents/technical/espacenet/ops.html#tab1
  2. \n
  3. Click on the “Register” button and fulfill the form
  4. \n
  5. Wait until you receive the email confirmation of you register from EPO Developer Portal.
  6. \n
  7. Log in the EPO Developer Portal :
    https://developers.epo.org/user/login
  8. \n
  9. Select the option “My apps
  10. \n
  11. Create and register the “Patent2Net” application
  12. \n
  13. The system returns the API credentials key and secret, similar to that shown bellow (this one is invalid, of course):
    \n
    vmrr7AaAGIl794E6VunJ6PzjbkfajwLW,KHzH4fGM7opMhDDD
    \n
  14. \n
  15. Copy/paste the key in the textbox and click on confirm. It will create a file in your install of Patent2Net who will let you have full use of it.
  16. \n
\n \n
\n
\n
\n
\n
\n \n

Paste in the textbox the key provided by EPO.

\n
\n
\n \n
\n\n \n
\n Fields marked with * are mandatory.\n
\n \n
\n
\n
\n
\n

P2N Docker archive content

\n
\n
\n
\n
\n
    \n
  • Dockerfile : Mandatory for the install of P2N Docker
  • \n
  • Install_P2N.bat : used to install all the P2N Content in Docker
  • \n
  • Run_P2N.bat : Used to initiate P2N instance in Docker
  • \n
  • Stop_P2N.bat : Used to stop P2N instance
  • \n
  • Copy Docker P2N :\n
      \n
    • Copy_Docker_P2N.bat : Create a tar file with all the base content of your docker version
    • \n
    • Load_Docker_P2N.bat : Import the tar file insde docker and create P2N image
    • \n
    \n
  • \n
  • P2N_Bash.bat : Create a command prompt instance who interact with P2N Docker. Click here for more details.
  • \n
\n
\n
\n
\n

P2N Interface directories

\n
\n
\n
\n
\n
    \n
  • Home : Default page. Explain how PatentNet can help you
  • \n
  • Get Started : Explain how to use P2N Docker
  • \n
  • Requests : form used to execute requests to the EPO database
  • \n
  • Index : Display all the results of P2N
  • \n
  • Download Data : create a zip folder with all the datas contained in Index. Downloaded on your local machine
  • \n
\n
\n
\n
\n
\n
\n )\n}\n\nexport default GetStarted;","import React from \"react\"\n\nconst Home = ({version}) => {\n\n const [isUpdate, setIsUpdate] = React.useState(false)\n\n const update = React.useCallback(() => {\n setIsUpdate(true)\n fetch(\"http://localhost:5000/updateP2N\")\n .then(function(response) {\n setIsUpdate(false)\n })\n }, [])\n\n return (\n
\n
\n
\n

Patent2Net Docker Version : {version}

\n
\n
\n
\n

Patent2Net is a toolkit for patent information processing and statistical analysis for education and science.
\n Patent2Net helps to collect, study and analyze patent data from the European Patent Office’s Open Patent Services API (OPS).
\n Patent2Net is a free software dedicated to :\n

\t\n \n
    \n
  • provide statistical analysis and representations of a set of patents.
  • \n
  • promote the use of patent information in the academic field, nano and small firms,\n developing countries.
  • \n
  • study and practice how to collect, treat and communicate “textual bibliographic information”\n and learn the automation process.
  • \n
\n \n

Contributions are always welcome!\n

\n
\n
\n
\n
\n

To update your P2N version click on the button :

\n \n
\n
\n
\n
\n )\n}\n\nexport default Home","import React from \"react\";\nimport { Link } from \"react-router-dom\";\n\nconst DataIndex = () => {\n const [ requests, setRequests ] = React.useState({});\n \n React.useEffect(() => {\n fetch(\"http://localhost:5000/api/v1/requests\")\n .then(function(response) {\n return response.json();\n })\n .then(function(json) {\n if (json.data) {\n setRequests(json.data)\n }\n console.log(json.data)\n });\n }, []);\n \n return (\n
\n
\n
\n
\n

Index

\n
\n \n
\n { requests.done && requests.done.map((name) => (\n
\n {name}\n
\n ))}\n
\n
\n
\n
\n
\n )\n}\n\nexport default DataIndex","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport {\n BrowserRouter as Router,\n Switch,\n Route,\n Link,\n Redirect\n} from \"react-router-dom\";\nimport Requests from './pages/Requests';\nimport Request from './pages/Request/index';\nimport GetStarted from './pages/GetStarted';\nimport './index.css'\nimport Home from './pages/Home';\nimport DataIndex from './pages/DataIndex';\n\nReactDOM.render(\n \n \n \n {/* A looks through its children s and\n renders the first one that matches the current URL. */}\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n
\n
,\n document.getElementById('root')\n);\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\n// reportWebVitals();\n"],"sourceRoot":""} \ No newline at end of file diff --git a/web_app/src/pages/Requests.js b/web_app/src/pages/Requests.js index 1084d063..09fc732f 100644 --- a/web_app/src/pages/Requests.js +++ b/web_app/src/pages/Requests.js @@ -1,47 +1,58 @@ import React from "react"; import { useHistory } from "react-router"; import { Link } from "react-router-dom"; +import Icon from "./icon"; const all_options = { "p2n_family": { name: "p2n family", - description: "run family data acquisition" + description: "run family data acquisition", + icon: "family" }, "p2n_image": { name: "p2n images", - description: "Fetch images" + description: "Fetch images", + icon: "image" }, "p2n_network": { name: "p2n networks", - description: "Build various artefacts for data exploration based on network graphs" + description: "Build various artefacts for data exploration based on network graphs", + icon: "network" }, "p2n_freeplane": { name: "p2n freeplane", - description: "Build mind map for Freeplane" + description: "Build mind map for Freeplane", + icon: "nodes" }, "p2n_bibfile": { name: "p2n bibfile", - description: "Export data in bibfile format" + description: "Export data in bibfile format", + icon: "archive" }, "p2n_map": { name: "p2n maps", - description: "Build maps of country coverage of patents, as well as applicants and inventors" + description: "Build maps of country coverage of patents, as well as applicants and inventors", + icon: "map" }, "p2n_tables": { name: "p2n tables", - description: "Export various artefacts for tabular data exploration" + description: "Export various artefacts for tabular data exploration", + icon: "table" }, "p2n_carrot": { name: "p2n carrot", - description: "Export data to XML suitable for using in Carro" + description: "Export data to XML suitable for using in Carro", + icon: "carrot" }, "p2n_iramuteq": { name: "p2n iramuteq", - description: "Fetch more data and export it to suitable format for using in Iramuteq" + description: "Fetch more data and export it to suitable format for using in Iramuteq", + icon: "chart-pie" }, "p2n_cluster": { name: "p2n cluster", - description: "Double clustering system based on non so trivial words" + description: "Double clustering system based on non so trivial words", + icon: "cluster" }, } @@ -213,33 +224,60 @@ function App() {

Click on the checkbox to specify the elements you need in your research:

- {Object.keys(all_options).map((key, index) => { - let option = all_options[key] - return ( -

- toggleCheckbox(key) } - /> - -

- ) - })} +
+ {Object.keys(all_options).map((key, index) => { + let option = all_options[key] + return ( +
toggleCheckbox(key)} + > +
+ +
+

{option["name"]}

+

{option["description"]}

+
+ //

+ // toggleCheckbox(key) } + // /> + // + //

+ ) + })} +
- - setP2nAuto(!p2nAuto) } - /> + +
+
setP2nAuto(!p2nAuto)} + > +
+ +
+

Use auto request spliter

+

+ It allows to exceed the limit of 2000 patents per request by splitting it into several sub-request +

+
+
- -
Fields marked with * are mandatory.
diff --git a/web_app/src/pages/icon.js b/web_app/src/pages/icon.js new file mode 100644 index 00000000..c85b2619 --- /dev/null +++ b/web_app/src/pages/icon.js @@ -0,0 +1,58 @@ + +const Icon = ({ name }) => { + + switch(name) { + case "family": + return ( + + ) + case "image": + return ( + + ) + case "network": + return ( + + ) + case "nodes": + return ( + + ) + case "archive": + return ( + + ) + case "map": + return ( + + ) + case "table": + return ( + + ) + case "carrot": + return ( + + ) + case "chart-pie": + return ( + + ) + case "cluster": + return ( + + ) + case "infographic": + return ( + + ) + case "split": + return ( + + ) + default: + return null + } +} + +export default Icon; \ No newline at end of file From 5ea9c23dd8da399843efd71c6f56763eeeaf25d7 Mon Sep 17 00:00:00 2001 From: romaric-g Date: Thu, 20 May 2021 11:16:41 +0200 Subject: [PATCH 4/8] new graph recipes system --- .../{Graph-recipes => Graph-recipes-0}/app.css | 0 .../media/{Graph-recipes => Graph-recipes-0}/app.js | 0 .../assets/FileSaver.min.js | 0 .../assets/ace/ace.js | 0 .../assets/ace/ext-beautify.js | 0 .../assets/ace/ext-chromevox.js | 0 .../assets/ace/ext-elastic_tabstops_lite.js | 0 .../assets/ace/ext-emmet.js | 0 .../assets/ace/ext-error_marker.js | 0 .../assets/ace/ext-keybinding_menu.js | 0 .../assets/ace/ext-language_tools.js | 0 .../assets/ace/ext-linking.js | 0 .../assets/ace/ext-modelist.js | 0 .../assets/ace/ext-old_ie.js | 0 .../assets/ace/ext-searchbox.js | 0 .../assets/ace/ext-settings_menu.js | 0 .../assets/ace/ext-spellcheck.js | 0 .../assets/ace/ext-split.js | 0 .../assets/ace/ext-static_highlight.js | 0 .../assets/ace/ext-statusbar.js | 0 .../assets/ace/ext-textarea.js | 0 .../assets/ace/ext-themelist.js | 0 .../assets/ace/ext-whitespace.js | 0 .../assets/ace/keybinding-emacs.js | 0 .../assets/ace/keybinding-vim.js | 0 .../assets/ace/mode-asciidoc.js | 0 .../assets/ace/mode-javascript.js | 0 .../assets/ace/mode-json.js | 0 .../assets/ace/mode-markdown.js | 0 .../assets/ace/mode-svg.js | 0 .../assets/ace/mode-text.js | 0 .../assets/ace/snippets/abap.js | 0 .../assets/ace/snippets/abc.js | 0 .../assets/ace/snippets/actionscript.js | 0 .../assets/ace/snippets/ada.js | 0 .../assets/ace/snippets/apache_conf.js | 0 .../assets/ace/snippets/applescript.js | 0 .../assets/ace/snippets/asciidoc.js | 0 .../assets/ace/snippets/assembly_x86.js | 0 .../assets/ace/snippets/autohotkey.js | 0 .../assets/ace/snippets/batchfile.js | 0 .../assets/ace/snippets/c9search.js | 0 .../assets/ace/snippets/c_cpp.js | 0 .../assets/ace/snippets/cirru.js | 0 .../assets/ace/snippets/clojure.js | 0 .../assets/ace/snippets/cobol.js | 0 .../assets/ace/snippets/coffee.js | 0 .../assets/ace/snippets/coldfusion.js | 0 .../assets/ace/snippets/csharp.js | 0 .../assets/ace/snippets/css.js | 0 .../assets/ace/snippets/curly.js | 0 .../assets/ace/snippets/d.js | 0 .../assets/ace/snippets/dart.js | 0 .../assets/ace/snippets/diff.js | 0 .../assets/ace/snippets/django.js | 0 .../assets/ace/snippets/dockerfile.js | 0 .../assets/ace/snippets/dot.js | 0 .../assets/ace/snippets/eiffel.js | 0 .../assets/ace/snippets/ejs.js | 0 .../assets/ace/snippets/elixir.js | 0 .../assets/ace/snippets/elm.js | 0 .../assets/ace/snippets/erlang.js | 0 .../assets/ace/snippets/forth.js | 0 .../assets/ace/snippets/ftl.js | 0 .../assets/ace/snippets/gcode.js | 0 .../assets/ace/snippets/gherkin.js | 0 .../assets/ace/snippets/gitignore.js | 0 .../assets/ace/snippets/glsl.js | 0 .../assets/ace/snippets/golang.js | 0 .../assets/ace/snippets/groovy.js | 0 .../assets/ace/snippets/haml.js | 0 .../assets/ace/snippets/handlebars.js | 0 .../assets/ace/snippets/haskell.js | 0 .../assets/ace/snippets/haxe.js | 0 .../assets/ace/snippets/html.js | 0 .../assets/ace/snippets/html_ruby.js | 0 .../assets/ace/snippets/ini.js | 0 .../assets/ace/snippets/io.js | 0 .../assets/ace/snippets/jack.js | 0 .../assets/ace/snippets/jade.js | 0 .../assets/ace/snippets/java.js | 0 .../assets/ace/snippets/javascript.js | 0 .../assets/ace/snippets/json.js | 0 .../assets/ace/snippets/jsoniq.js | 0 .../assets/ace/snippets/jsp.js | 0 .../assets/ace/snippets/jsx.js | 0 .../assets/ace/snippets/julia.js | 0 .../assets/ace/snippets/latex.js | 0 .../assets/ace/snippets/lean.js | 0 .../assets/ace/snippets/less.js | 0 .../assets/ace/snippets/liquid.js | 0 .../assets/ace/snippets/lisp.js | 0 .../assets/ace/snippets/live_script.js | 0 .../assets/ace/snippets/livescript.js | 0 .../assets/ace/snippets/logiql.js | 0 .../assets/ace/snippets/lsl.js | 0 .../assets/ace/snippets/lua.js | 0 .../assets/ace/snippets/luapage.js | 0 .../assets/ace/snippets/lucene.js | 0 .../assets/ace/snippets/makefile.js | 0 .../assets/ace/snippets/markdown.js | 0 .../assets/ace/snippets/mask.js | 0 .../assets/ace/snippets/matlab.js | 0 .../assets/ace/snippets/mel.js | 0 .../assets/ace/snippets/mips_assembler.js | 0 .../assets/ace/snippets/mipsassembler.js | 0 .../assets/ace/snippets/mushcode.js | 0 .../assets/ace/snippets/mysql.js | 0 .../assets/ace/snippets/nix.js | 0 .../assets/ace/snippets/objectivec.js | 0 .../assets/ace/snippets/ocaml.js | 0 .../assets/ace/snippets/pascal.js | 0 .../assets/ace/snippets/perl.js | 0 .../assets/ace/snippets/pgsql.js | 0 .../assets/ace/snippets/php.js | 0 .../assets/ace/snippets/plain_text.js | 0 .../assets/ace/snippets/powershell.js | 0 .../assets/ace/snippets/praat.js | 0 .../assets/ace/snippets/prolog.js | 0 .../assets/ace/snippets/properties.js | 0 .../assets/ace/snippets/protobuf.js | 0 .../assets/ace/snippets/python.js | 0 .../assets/ace/snippets/r.js | 0 .../assets/ace/snippets/rdoc.js | 0 .../assets/ace/snippets/rhtml.js | 0 .../assets/ace/snippets/ruby.js | 0 .../assets/ace/snippets/rust.js | 0 .../assets/ace/snippets/sass.js | 0 .../assets/ace/snippets/scad.js | 0 .../assets/ace/snippets/scala.js | 0 .../assets/ace/snippets/scheme.js | 0 .../assets/ace/snippets/scss.js | 0 .../assets/ace/snippets/sh.js | 0 .../assets/ace/snippets/sjs.js | 0 .../assets/ace/snippets/smarty.js | 0 .../assets/ace/snippets/snippets.js | 0 .../assets/ace/snippets/soy_template.js | 0 .../assets/ace/snippets/space.js | 0 .../assets/ace/snippets/sql.js | 0 .../assets/ace/snippets/stylus.js | 0 .../assets/ace/snippets/svg.js | 0 .../assets/ace/snippets/tcl.js | 0 .../assets/ace/snippets/tex.js | 0 .../assets/ace/snippets/text.js | 0 .../assets/ace/snippets/textile.js | 0 .../assets/ace/snippets/toml.js | 0 .../assets/ace/snippets/twig.js | 0 .../assets/ace/snippets/typescript.js | 0 .../assets/ace/snippets/vala.js | 0 .../assets/ace/snippets/vbscript.js | 0 .../assets/ace/snippets/velocity.js | 0 .../assets/ace/snippets/verilog.js | 0 .../assets/ace/snippets/vhdl.js | 0 .../assets/ace/snippets/xml.js | 0 .../assets/ace/snippets/xquery.js | 0 .../assets/ace/snippets/yaml.js | 0 .../assets/ace/theme-chrome.js | 0 .../assets/ace/theme-clouds.js | 0 .../assets/ace/theme-clouds_midnight.js | 0 .../assets/ace/theme-twilight.js | 0 .../assets/ace/worker-javascript.js | 0 .../assets/ace/worker-json.js | 0 .../assets/doc/attributestapas.png | Bin .../assets/doc/cloud_dark.png | Bin .../assets/doc/cloud_default.png | Bin .../assets/doc/fuzzyclusters_blurry.png | Bin .../assets/doc/fuzzyclusters_category.png | Bin .../assets/doc/fuzzyclusters_contour.png | Bin .../assets/doc/fuzzyclusters_language.png | Bin .../assets/doc/pixeldeluxe_halo0.png | Bin .../assets/doc/pixeldeluxe_halo10.png | Bin .../assets/doc/pixeldeluxe_halo100.png | Bin .../assets/doc/voronoi_nosize_illimited.png | Bin .../assets/doc/voronoi_nosize_limited.png | Bin .../assets/doc/voronoi_size_illimited.png | Bin .../assets/doc/voronoi_size_limited.png | Bin .../assets/gexf.min.js | 0 .../assets/visual.png | Bin .../{Graph-recipes => Graph-recipes-0}/bundle2.js | 0 .../{Graph-recipes => Graph-recipes-0}/index.html | 0 .../jsEditor.html | 0 .../{Graph-recipes => Graph-recipes-0}/lcd-sav.html | 0 .../{Graph-recipes => Graph-recipes-0}/lcd.html | 0 .../{Graph-recipes => Graph-recipes-0}/lcd.svg | 0 .../{Graph-recipes => Graph-recipes-0}/lcd2.html | 0 .../{Graph-recipes => Graph-recipes-0}/medialab.png | Bin Patent2Net/media/Graph-recipes-0/meta.json | 10 ++++++++++ .../recipes/_recipes_list_.js | 0 .../recipes/attributes.js | 0 .../recipes/betweenness.js | 0 .../recipes/cloud.js | 0 .../recipes/deluxecanvas.js | 0 .../recipes/deluxesvg.js | 0 .../recipes/empty.js | 0 .../recipes/forceatlas2.js | 0 .../recipes/fulldiagnostic.js | 0 .../recipes/fuzzyclusters.js | 0 .../recipes/heatmap.js | 0 .../recipes/partition.js | 0 .../recipes/sigma-AppliInv.js | 0 .../recipes/sigma.js | 0 .../recipes/sigmaSav.js | 0 .../recipes/simplecanvas.js | 0 .../recipes/simplesvg.js | 0 .../recipes/voronoi.js | 0 .../sample rio+20.gexf | 0 .../{Graph-recipes => Graph-recipes-0}/utils.js | 0 .../view_board/board-sav.html | 0 .../view_board/board.html | 0 .../view_board/board.js | 0 .../view_board/board1.html | 0 .../view_upload/upload.html | 0 .../view_upload/upload.js | 0 Patent2Net/media/graph-recipes | 1 + 214 files changed, 11 insertions(+) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/app.css (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/app.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/FileSaver.min.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ace.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-beautify.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-chromevox.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-elastic_tabstops_lite.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-emmet.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-error_marker.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-keybinding_menu.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-language_tools.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-linking.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-modelist.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-old_ie.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-searchbox.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-settings_menu.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-spellcheck.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-split.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-static_highlight.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-statusbar.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-textarea.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-themelist.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/ext-whitespace.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/keybinding-emacs.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/keybinding-vim.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/mode-asciidoc.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/mode-javascript.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/mode-json.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/mode-markdown.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/mode-svg.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/mode-text.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/abap.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/abc.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/actionscript.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/ada.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/apache_conf.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/applescript.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/asciidoc.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/assembly_x86.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/autohotkey.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/batchfile.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/c9search.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/c_cpp.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/cirru.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/clojure.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/cobol.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/coffee.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/coldfusion.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/csharp.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/css.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/curly.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/d.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/dart.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/diff.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/django.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/dockerfile.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/dot.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/eiffel.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/ejs.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/elixir.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/elm.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/erlang.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/forth.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/ftl.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/gcode.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/gherkin.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/gitignore.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/glsl.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/golang.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/groovy.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/haml.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/handlebars.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/haskell.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/haxe.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/html.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/html_ruby.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/ini.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/io.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/jack.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/jade.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/java.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/javascript.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/json.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/jsoniq.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/jsp.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/jsx.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/julia.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/latex.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/lean.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/less.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/liquid.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/lisp.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/live_script.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/livescript.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/logiql.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/lsl.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/lua.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/luapage.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/lucene.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/makefile.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/markdown.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/mask.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/matlab.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/mel.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/mips_assembler.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/mipsassembler.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/mushcode.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/mysql.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/nix.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/objectivec.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/ocaml.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/pascal.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/perl.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/pgsql.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/php.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/plain_text.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/powershell.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/praat.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/prolog.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/properties.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/protobuf.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/python.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/r.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/rdoc.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/rhtml.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/ruby.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/rust.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/sass.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/scad.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/scala.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/scheme.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/scss.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/sh.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/sjs.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/smarty.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/snippets.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/soy_template.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/space.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/sql.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/stylus.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/svg.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/tcl.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/tex.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/text.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/textile.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/toml.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/twig.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/typescript.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/vala.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/vbscript.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/velocity.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/verilog.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/vhdl.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/xml.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/xquery.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/snippets/yaml.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/theme-chrome.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/theme-clouds.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/theme-clouds_midnight.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/theme-twilight.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/worker-javascript.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/ace/worker-json.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/attributestapas.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/cloud_dark.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/cloud_default.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/fuzzyclusters_blurry.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/fuzzyclusters_category.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/fuzzyclusters_contour.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/fuzzyclusters_language.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/pixeldeluxe_halo0.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/pixeldeluxe_halo10.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/pixeldeluxe_halo100.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/voronoi_nosize_illimited.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/voronoi_nosize_limited.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/voronoi_size_illimited.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/doc/voronoi_size_limited.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/gexf.min.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/assets/visual.png (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/bundle2.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/index.html (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/jsEditor.html (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/lcd-sav.html (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/lcd.html (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/lcd.svg (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/lcd2.html (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/medialab.png (100%) create mode 100644 Patent2Net/media/Graph-recipes-0/meta.json rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/_recipes_list_.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/attributes.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/betweenness.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/cloud.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/deluxecanvas.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/deluxesvg.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/empty.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/forceatlas2.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/fulldiagnostic.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/fuzzyclusters.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/heatmap.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/partition.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/sigma-AppliInv.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/sigma.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/sigmaSav.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/simplecanvas.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/simplesvg.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/recipes/voronoi.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/sample rio+20.gexf (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/utils.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/view_board/board-sav.html (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/view_board/board.html (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/view_board/board.js (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/view_board/board1.html (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/view_upload/upload.html (100%) rename Patent2Net/media/{Graph-recipes => Graph-recipes-0}/view_upload/upload.js (100%) create mode 160000 Patent2Net/media/graph-recipes diff --git a/Patent2Net/media/Graph-recipes/app.css b/Patent2Net/media/Graph-recipes-0/app.css similarity index 100% rename from Patent2Net/media/Graph-recipes/app.css rename to Patent2Net/media/Graph-recipes-0/app.css diff --git a/Patent2Net/media/Graph-recipes/app.js b/Patent2Net/media/Graph-recipes-0/app.js similarity index 100% rename from Patent2Net/media/Graph-recipes/app.js rename to Patent2Net/media/Graph-recipes-0/app.js diff --git a/Patent2Net/media/Graph-recipes/assets/FileSaver.min.js b/Patent2Net/media/Graph-recipes-0/assets/FileSaver.min.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/FileSaver.min.js rename to Patent2Net/media/Graph-recipes-0/assets/FileSaver.min.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ace.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ace.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ace.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ace.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-beautify.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-beautify.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-beautify.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-beautify.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-chromevox.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-chromevox.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-chromevox.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-chromevox.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-elastic_tabstops_lite.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-elastic_tabstops_lite.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-elastic_tabstops_lite.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-elastic_tabstops_lite.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-emmet.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-emmet.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-emmet.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-emmet.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-error_marker.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-error_marker.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-error_marker.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-error_marker.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-keybinding_menu.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-keybinding_menu.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-keybinding_menu.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-keybinding_menu.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-language_tools.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-language_tools.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-language_tools.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-language_tools.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-linking.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-linking.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-linking.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-linking.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-modelist.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-modelist.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-modelist.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-modelist.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-old_ie.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-old_ie.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-old_ie.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-old_ie.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-searchbox.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-searchbox.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-searchbox.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-searchbox.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-settings_menu.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-settings_menu.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-settings_menu.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-settings_menu.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-spellcheck.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-spellcheck.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-spellcheck.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-spellcheck.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-split.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-split.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-split.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-split.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-static_highlight.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-static_highlight.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-static_highlight.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-static_highlight.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-statusbar.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-statusbar.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-statusbar.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-statusbar.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-textarea.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-textarea.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-textarea.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-textarea.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-themelist.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-themelist.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-themelist.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-themelist.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/ext-whitespace.js b/Patent2Net/media/Graph-recipes-0/assets/ace/ext-whitespace.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/ext-whitespace.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/ext-whitespace.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/keybinding-emacs.js b/Patent2Net/media/Graph-recipes-0/assets/ace/keybinding-emacs.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/keybinding-emacs.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/keybinding-emacs.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/keybinding-vim.js b/Patent2Net/media/Graph-recipes-0/assets/ace/keybinding-vim.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/keybinding-vim.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/keybinding-vim.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/mode-asciidoc.js b/Patent2Net/media/Graph-recipes-0/assets/ace/mode-asciidoc.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/mode-asciidoc.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/mode-asciidoc.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/mode-javascript.js b/Patent2Net/media/Graph-recipes-0/assets/ace/mode-javascript.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/mode-javascript.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/mode-javascript.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/mode-json.js b/Patent2Net/media/Graph-recipes-0/assets/ace/mode-json.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/mode-json.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/mode-json.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/mode-markdown.js b/Patent2Net/media/Graph-recipes-0/assets/ace/mode-markdown.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/mode-markdown.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/mode-markdown.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/mode-svg.js b/Patent2Net/media/Graph-recipes-0/assets/ace/mode-svg.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/mode-svg.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/mode-svg.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/mode-text.js b/Patent2Net/media/Graph-recipes-0/assets/ace/mode-text.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/mode-text.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/mode-text.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/abap.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/abap.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/abap.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/abap.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/abc.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/abc.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/abc.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/abc.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/actionscript.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/actionscript.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/actionscript.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/actionscript.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/ada.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ada.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/ada.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ada.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/apache_conf.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/apache_conf.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/apache_conf.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/apache_conf.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/applescript.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/applescript.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/applescript.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/applescript.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/asciidoc.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/asciidoc.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/asciidoc.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/asciidoc.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/assembly_x86.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/assembly_x86.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/assembly_x86.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/assembly_x86.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/autohotkey.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/autohotkey.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/autohotkey.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/autohotkey.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/batchfile.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/batchfile.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/batchfile.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/batchfile.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/c9search.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/c9search.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/c9search.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/c9search.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/c_cpp.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/c_cpp.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/c_cpp.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/c_cpp.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/cirru.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/cirru.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/cirru.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/cirru.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/clojure.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/clojure.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/clojure.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/clojure.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/cobol.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/cobol.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/cobol.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/cobol.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/coffee.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/coffee.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/coffee.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/coffee.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/coldfusion.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/coldfusion.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/coldfusion.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/coldfusion.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/csharp.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/csharp.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/csharp.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/csharp.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/css.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/css.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/css.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/css.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/curly.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/curly.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/curly.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/curly.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/d.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/d.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/d.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/d.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/dart.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/dart.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/dart.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/dart.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/diff.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/diff.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/diff.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/diff.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/django.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/django.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/django.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/django.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/dockerfile.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/dockerfile.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/dockerfile.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/dockerfile.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/dot.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/dot.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/dot.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/dot.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/eiffel.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/eiffel.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/eiffel.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/eiffel.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/ejs.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ejs.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/ejs.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ejs.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/elixir.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/elixir.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/elixir.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/elixir.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/elm.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/elm.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/elm.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/elm.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/erlang.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/erlang.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/erlang.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/erlang.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/forth.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/forth.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/forth.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/forth.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/ftl.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ftl.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/ftl.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ftl.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/gcode.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/gcode.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/gcode.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/gcode.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/gherkin.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/gherkin.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/gherkin.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/gherkin.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/gitignore.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/gitignore.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/gitignore.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/gitignore.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/glsl.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/glsl.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/glsl.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/glsl.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/golang.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/golang.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/golang.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/golang.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/groovy.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/groovy.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/groovy.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/groovy.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/haml.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/haml.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/haml.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/haml.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/handlebars.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/handlebars.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/handlebars.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/handlebars.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/haskell.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/haskell.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/haskell.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/haskell.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/haxe.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/haxe.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/haxe.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/haxe.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/html.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/html.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/html.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/html.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/html_ruby.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/html_ruby.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/html_ruby.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/html_ruby.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/ini.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ini.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/ini.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ini.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/io.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/io.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/io.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/io.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/jack.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/jack.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/jack.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/jack.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/jade.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/jade.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/jade.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/jade.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/java.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/java.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/java.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/java.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/javascript.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/javascript.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/javascript.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/javascript.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/json.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/json.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/json.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/json.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/jsoniq.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/jsoniq.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/jsoniq.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/jsoniq.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/jsp.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/jsp.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/jsp.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/jsp.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/jsx.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/jsx.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/jsx.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/jsx.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/julia.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/julia.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/julia.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/julia.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/latex.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/latex.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/latex.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/latex.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/lean.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/lean.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/lean.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/lean.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/less.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/less.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/less.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/less.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/liquid.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/liquid.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/liquid.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/liquid.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/lisp.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/lisp.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/lisp.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/lisp.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/live_script.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/live_script.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/live_script.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/live_script.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/livescript.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/livescript.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/livescript.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/livescript.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/logiql.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/logiql.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/logiql.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/logiql.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/lsl.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/lsl.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/lsl.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/lsl.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/lua.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/lua.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/lua.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/lua.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/luapage.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/luapage.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/luapage.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/luapage.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/lucene.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/lucene.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/lucene.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/lucene.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/makefile.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/makefile.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/makefile.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/makefile.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/markdown.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/markdown.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/markdown.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/markdown.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/mask.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mask.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/mask.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mask.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/matlab.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/matlab.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/matlab.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/matlab.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/mel.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mel.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/mel.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mel.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/mips_assembler.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mips_assembler.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/mips_assembler.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mips_assembler.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/mipsassembler.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mipsassembler.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/mipsassembler.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mipsassembler.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/mushcode.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mushcode.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/mushcode.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mushcode.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/mysql.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mysql.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/mysql.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/mysql.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/nix.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/nix.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/nix.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/nix.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/objectivec.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/objectivec.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/objectivec.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/objectivec.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/ocaml.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ocaml.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/ocaml.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ocaml.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/pascal.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/pascal.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/pascal.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/pascal.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/perl.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/perl.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/perl.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/perl.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/pgsql.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/pgsql.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/pgsql.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/pgsql.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/php.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/php.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/php.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/php.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/plain_text.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/plain_text.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/plain_text.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/plain_text.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/powershell.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/powershell.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/powershell.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/powershell.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/praat.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/praat.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/praat.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/praat.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/prolog.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/prolog.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/prolog.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/prolog.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/properties.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/properties.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/properties.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/properties.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/protobuf.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/protobuf.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/protobuf.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/protobuf.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/python.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/python.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/python.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/python.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/r.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/r.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/r.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/r.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/rdoc.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/rdoc.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/rdoc.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/rdoc.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/rhtml.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/rhtml.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/rhtml.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/rhtml.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/ruby.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ruby.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/ruby.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/ruby.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/rust.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/rust.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/rust.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/rust.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/sass.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/sass.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/sass.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/sass.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/scad.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/scad.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/scad.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/scad.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/scala.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/scala.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/scala.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/scala.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/scheme.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/scheme.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/scheme.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/scheme.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/scss.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/scss.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/scss.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/scss.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/sh.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/sh.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/sh.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/sh.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/sjs.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/sjs.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/sjs.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/sjs.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/smarty.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/smarty.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/smarty.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/smarty.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/snippets.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/snippets.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/snippets.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/snippets.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/soy_template.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/soy_template.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/soy_template.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/soy_template.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/space.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/space.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/space.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/space.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/sql.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/sql.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/sql.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/sql.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/stylus.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/stylus.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/stylus.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/stylus.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/svg.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/svg.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/svg.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/svg.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/tcl.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/tcl.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/tcl.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/tcl.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/tex.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/tex.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/tex.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/tex.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/text.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/text.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/text.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/text.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/textile.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/textile.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/textile.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/textile.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/toml.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/toml.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/toml.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/toml.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/twig.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/twig.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/twig.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/twig.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/typescript.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/typescript.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/typescript.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/typescript.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/vala.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/vala.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/vala.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/vala.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/vbscript.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/vbscript.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/vbscript.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/vbscript.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/velocity.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/velocity.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/velocity.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/velocity.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/verilog.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/verilog.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/verilog.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/verilog.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/vhdl.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/vhdl.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/vhdl.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/vhdl.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/xml.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/xml.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/xml.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/xml.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/xquery.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/xquery.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/xquery.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/xquery.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/snippets/yaml.js b/Patent2Net/media/Graph-recipes-0/assets/ace/snippets/yaml.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/snippets/yaml.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/snippets/yaml.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/theme-chrome.js b/Patent2Net/media/Graph-recipes-0/assets/ace/theme-chrome.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/theme-chrome.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/theme-chrome.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/theme-clouds.js b/Patent2Net/media/Graph-recipes-0/assets/ace/theme-clouds.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/theme-clouds.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/theme-clouds.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/theme-clouds_midnight.js b/Patent2Net/media/Graph-recipes-0/assets/ace/theme-clouds_midnight.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/theme-clouds_midnight.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/theme-clouds_midnight.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/theme-twilight.js b/Patent2Net/media/Graph-recipes-0/assets/ace/theme-twilight.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/theme-twilight.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/theme-twilight.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/worker-javascript.js b/Patent2Net/media/Graph-recipes-0/assets/ace/worker-javascript.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/worker-javascript.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/worker-javascript.js diff --git a/Patent2Net/media/Graph-recipes/assets/ace/worker-json.js b/Patent2Net/media/Graph-recipes-0/assets/ace/worker-json.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/ace/worker-json.js rename to Patent2Net/media/Graph-recipes-0/assets/ace/worker-json.js diff --git a/Patent2Net/media/Graph-recipes/assets/doc/attributestapas.png b/Patent2Net/media/Graph-recipes-0/assets/doc/attributestapas.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/attributestapas.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/attributestapas.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/cloud_dark.png b/Patent2Net/media/Graph-recipes-0/assets/doc/cloud_dark.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/cloud_dark.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/cloud_dark.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/cloud_default.png b/Patent2Net/media/Graph-recipes-0/assets/doc/cloud_default.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/cloud_default.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/cloud_default.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/fuzzyclusters_blurry.png b/Patent2Net/media/Graph-recipes-0/assets/doc/fuzzyclusters_blurry.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/fuzzyclusters_blurry.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/fuzzyclusters_blurry.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/fuzzyclusters_category.png b/Patent2Net/media/Graph-recipes-0/assets/doc/fuzzyclusters_category.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/fuzzyclusters_category.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/fuzzyclusters_category.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/fuzzyclusters_contour.png b/Patent2Net/media/Graph-recipes-0/assets/doc/fuzzyclusters_contour.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/fuzzyclusters_contour.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/fuzzyclusters_contour.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/fuzzyclusters_language.png b/Patent2Net/media/Graph-recipes-0/assets/doc/fuzzyclusters_language.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/fuzzyclusters_language.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/fuzzyclusters_language.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/pixeldeluxe_halo0.png b/Patent2Net/media/Graph-recipes-0/assets/doc/pixeldeluxe_halo0.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/pixeldeluxe_halo0.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/pixeldeluxe_halo0.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/pixeldeluxe_halo10.png b/Patent2Net/media/Graph-recipes-0/assets/doc/pixeldeluxe_halo10.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/pixeldeluxe_halo10.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/pixeldeluxe_halo10.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/pixeldeluxe_halo100.png b/Patent2Net/media/Graph-recipes-0/assets/doc/pixeldeluxe_halo100.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/pixeldeluxe_halo100.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/pixeldeluxe_halo100.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/voronoi_nosize_illimited.png b/Patent2Net/media/Graph-recipes-0/assets/doc/voronoi_nosize_illimited.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/voronoi_nosize_illimited.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/voronoi_nosize_illimited.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/voronoi_nosize_limited.png b/Patent2Net/media/Graph-recipes-0/assets/doc/voronoi_nosize_limited.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/voronoi_nosize_limited.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/voronoi_nosize_limited.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/voronoi_size_illimited.png b/Patent2Net/media/Graph-recipes-0/assets/doc/voronoi_size_illimited.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/voronoi_size_illimited.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/voronoi_size_illimited.png diff --git a/Patent2Net/media/Graph-recipes/assets/doc/voronoi_size_limited.png b/Patent2Net/media/Graph-recipes-0/assets/doc/voronoi_size_limited.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/doc/voronoi_size_limited.png rename to Patent2Net/media/Graph-recipes-0/assets/doc/voronoi_size_limited.png diff --git a/Patent2Net/media/Graph-recipes/assets/gexf.min.js b/Patent2Net/media/Graph-recipes-0/assets/gexf.min.js similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/gexf.min.js rename to Patent2Net/media/Graph-recipes-0/assets/gexf.min.js diff --git a/Patent2Net/media/Graph-recipes/assets/visual.png b/Patent2Net/media/Graph-recipes-0/assets/visual.png similarity index 100% rename from Patent2Net/media/Graph-recipes/assets/visual.png rename to Patent2Net/media/Graph-recipes-0/assets/visual.png diff --git a/Patent2Net/media/Graph-recipes/bundle2.js b/Patent2Net/media/Graph-recipes-0/bundle2.js similarity index 100% rename from Patent2Net/media/Graph-recipes/bundle2.js rename to Patent2Net/media/Graph-recipes-0/bundle2.js diff --git a/Patent2Net/media/Graph-recipes/index.html b/Patent2Net/media/Graph-recipes-0/index.html similarity index 100% rename from Patent2Net/media/Graph-recipes/index.html rename to Patent2Net/media/Graph-recipes-0/index.html diff --git a/Patent2Net/media/Graph-recipes/jsEditor.html b/Patent2Net/media/Graph-recipes-0/jsEditor.html similarity index 100% rename from Patent2Net/media/Graph-recipes/jsEditor.html rename to Patent2Net/media/Graph-recipes-0/jsEditor.html diff --git a/Patent2Net/media/Graph-recipes/lcd-sav.html b/Patent2Net/media/Graph-recipes-0/lcd-sav.html similarity index 100% rename from Patent2Net/media/Graph-recipes/lcd-sav.html rename to Patent2Net/media/Graph-recipes-0/lcd-sav.html diff --git a/Patent2Net/media/Graph-recipes/lcd.html b/Patent2Net/media/Graph-recipes-0/lcd.html similarity index 100% rename from Patent2Net/media/Graph-recipes/lcd.html rename to Patent2Net/media/Graph-recipes-0/lcd.html diff --git a/Patent2Net/media/Graph-recipes/lcd.svg b/Patent2Net/media/Graph-recipes-0/lcd.svg similarity index 100% rename from Patent2Net/media/Graph-recipes/lcd.svg rename to Patent2Net/media/Graph-recipes-0/lcd.svg diff --git a/Patent2Net/media/Graph-recipes/lcd2.html b/Patent2Net/media/Graph-recipes-0/lcd2.html similarity index 100% rename from Patent2Net/media/Graph-recipes/lcd2.html rename to Patent2Net/media/Graph-recipes-0/lcd2.html diff --git a/Patent2Net/media/Graph-recipes/medialab.png b/Patent2Net/media/Graph-recipes-0/medialab.png similarity index 100% rename from Patent2Net/media/Graph-recipes/medialab.png rename to Patent2Net/media/Graph-recipes-0/medialab.png diff --git a/Patent2Net/media/Graph-recipes-0/meta.json b/Patent2Net/media/Graph-recipes-0/meta.json new file mode 100644 index 00000000..52709cf2 --- /dev/null +++ b/Patent2Net/media/Graph-recipes-0/meta.json @@ -0,0 +1,10 @@ +{ + "name": "Graph Recipes", + "authors": ["Mathieu Jacomy"], + "url": "http://tools.medialab.sciences-po.fr/graph-recipes/", + "source": "https://github.com/medialab/graph-recipes", + "licence": "LGPL/CECILL-C", + "visual": "http://tools.medialab.sciences-po.fr/graph-recipes/assets/visual.png", + "description": "Graph Recipes is an environment to apply JS scripts to your network. Compute metrics, produce images, and tinker with Graphology.", + "doc": "https://github.com/medialab/graph-recipes/wiki" +} \ No newline at end of file diff --git a/Patent2Net/media/Graph-recipes/recipes/_recipes_list_.js b/Patent2Net/media/Graph-recipes-0/recipes/_recipes_list_.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/_recipes_list_.js rename to Patent2Net/media/Graph-recipes-0/recipes/_recipes_list_.js diff --git a/Patent2Net/media/Graph-recipes/recipes/attributes.js b/Patent2Net/media/Graph-recipes-0/recipes/attributes.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/attributes.js rename to Patent2Net/media/Graph-recipes-0/recipes/attributes.js diff --git a/Patent2Net/media/Graph-recipes/recipes/betweenness.js b/Patent2Net/media/Graph-recipes-0/recipes/betweenness.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/betweenness.js rename to Patent2Net/media/Graph-recipes-0/recipes/betweenness.js diff --git a/Patent2Net/media/Graph-recipes/recipes/cloud.js b/Patent2Net/media/Graph-recipes-0/recipes/cloud.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/cloud.js rename to Patent2Net/media/Graph-recipes-0/recipes/cloud.js diff --git a/Patent2Net/media/Graph-recipes/recipes/deluxecanvas.js b/Patent2Net/media/Graph-recipes-0/recipes/deluxecanvas.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/deluxecanvas.js rename to Patent2Net/media/Graph-recipes-0/recipes/deluxecanvas.js diff --git a/Patent2Net/media/Graph-recipes/recipes/deluxesvg.js b/Patent2Net/media/Graph-recipes-0/recipes/deluxesvg.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/deluxesvg.js rename to Patent2Net/media/Graph-recipes-0/recipes/deluxesvg.js diff --git a/Patent2Net/media/Graph-recipes/recipes/empty.js b/Patent2Net/media/Graph-recipes-0/recipes/empty.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/empty.js rename to Patent2Net/media/Graph-recipes-0/recipes/empty.js diff --git a/Patent2Net/media/Graph-recipes/recipes/forceatlas2.js b/Patent2Net/media/Graph-recipes-0/recipes/forceatlas2.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/forceatlas2.js rename to Patent2Net/media/Graph-recipes-0/recipes/forceatlas2.js diff --git a/Patent2Net/media/Graph-recipes/recipes/fulldiagnostic.js b/Patent2Net/media/Graph-recipes-0/recipes/fulldiagnostic.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/fulldiagnostic.js rename to Patent2Net/media/Graph-recipes-0/recipes/fulldiagnostic.js diff --git a/Patent2Net/media/Graph-recipes/recipes/fuzzyclusters.js b/Patent2Net/media/Graph-recipes-0/recipes/fuzzyclusters.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/fuzzyclusters.js rename to Patent2Net/media/Graph-recipes-0/recipes/fuzzyclusters.js diff --git a/Patent2Net/media/Graph-recipes/recipes/heatmap.js b/Patent2Net/media/Graph-recipes-0/recipes/heatmap.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/heatmap.js rename to Patent2Net/media/Graph-recipes-0/recipes/heatmap.js diff --git a/Patent2Net/media/Graph-recipes/recipes/partition.js b/Patent2Net/media/Graph-recipes-0/recipes/partition.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/partition.js rename to Patent2Net/media/Graph-recipes-0/recipes/partition.js diff --git a/Patent2Net/media/Graph-recipes/recipes/sigma-AppliInv.js b/Patent2Net/media/Graph-recipes-0/recipes/sigma-AppliInv.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/sigma-AppliInv.js rename to Patent2Net/media/Graph-recipes-0/recipes/sigma-AppliInv.js diff --git a/Patent2Net/media/Graph-recipes/recipes/sigma.js b/Patent2Net/media/Graph-recipes-0/recipes/sigma.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/sigma.js rename to Patent2Net/media/Graph-recipes-0/recipes/sigma.js diff --git a/Patent2Net/media/Graph-recipes/recipes/sigmaSav.js b/Patent2Net/media/Graph-recipes-0/recipes/sigmaSav.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/sigmaSav.js rename to Patent2Net/media/Graph-recipes-0/recipes/sigmaSav.js diff --git a/Patent2Net/media/Graph-recipes/recipes/simplecanvas.js b/Patent2Net/media/Graph-recipes-0/recipes/simplecanvas.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/simplecanvas.js rename to Patent2Net/media/Graph-recipes-0/recipes/simplecanvas.js diff --git a/Patent2Net/media/Graph-recipes/recipes/simplesvg.js b/Patent2Net/media/Graph-recipes-0/recipes/simplesvg.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/simplesvg.js rename to Patent2Net/media/Graph-recipes-0/recipes/simplesvg.js diff --git a/Patent2Net/media/Graph-recipes/recipes/voronoi.js b/Patent2Net/media/Graph-recipes-0/recipes/voronoi.js similarity index 100% rename from Patent2Net/media/Graph-recipes/recipes/voronoi.js rename to Patent2Net/media/Graph-recipes-0/recipes/voronoi.js diff --git a/Patent2Net/media/Graph-recipes/sample rio+20.gexf b/Patent2Net/media/Graph-recipes-0/sample rio+20.gexf similarity index 100% rename from Patent2Net/media/Graph-recipes/sample rio+20.gexf rename to Patent2Net/media/Graph-recipes-0/sample rio+20.gexf diff --git a/Patent2Net/media/Graph-recipes/utils.js b/Patent2Net/media/Graph-recipes-0/utils.js similarity index 100% rename from Patent2Net/media/Graph-recipes/utils.js rename to Patent2Net/media/Graph-recipes-0/utils.js diff --git a/Patent2Net/media/Graph-recipes/view_board/board-sav.html b/Patent2Net/media/Graph-recipes-0/view_board/board-sav.html similarity index 100% rename from Patent2Net/media/Graph-recipes/view_board/board-sav.html rename to Patent2Net/media/Graph-recipes-0/view_board/board-sav.html diff --git a/Patent2Net/media/Graph-recipes/view_board/board.html b/Patent2Net/media/Graph-recipes-0/view_board/board.html similarity index 100% rename from Patent2Net/media/Graph-recipes/view_board/board.html rename to Patent2Net/media/Graph-recipes-0/view_board/board.html diff --git a/Patent2Net/media/Graph-recipes/view_board/board.js b/Patent2Net/media/Graph-recipes-0/view_board/board.js similarity index 100% rename from Patent2Net/media/Graph-recipes/view_board/board.js rename to Patent2Net/media/Graph-recipes-0/view_board/board.js diff --git a/Patent2Net/media/Graph-recipes/view_board/board1.html b/Patent2Net/media/Graph-recipes-0/view_board/board1.html similarity index 100% rename from Patent2Net/media/Graph-recipes/view_board/board1.html rename to Patent2Net/media/Graph-recipes-0/view_board/board1.html diff --git a/Patent2Net/media/Graph-recipes/view_upload/upload.html b/Patent2Net/media/Graph-recipes-0/view_upload/upload.html similarity index 100% rename from Patent2Net/media/Graph-recipes/view_upload/upload.html rename to Patent2Net/media/Graph-recipes-0/view_upload/upload.html diff --git a/Patent2Net/media/Graph-recipes/view_upload/upload.js b/Patent2Net/media/Graph-recipes-0/view_upload/upload.js similarity index 100% rename from Patent2Net/media/Graph-recipes/view_upload/upload.js rename to Patent2Net/media/Graph-recipes-0/view_upload/upload.js diff --git a/Patent2Net/media/graph-recipes b/Patent2Net/media/graph-recipes new file mode 160000 index 00000000..000c343b --- /dev/null +++ b/Patent2Net/media/graph-recipes @@ -0,0 +1 @@ +Subproject commit 000c343b2a20bef1b81cb6d8cc452e12fde9de80 From 4f79177fa6bd678f7a8574c7e9ea04a578ecc135 Mon Sep 17 00:00:00 2001 From: romaric-g Date: Thu, 20 May 2021 11:25:16 +0200 Subject: [PATCH 5/8] graph-recipes --- Patent2Net/media/graph-recipes | 1 - Patent2Net/media/graph-recipes/.gitattributes | 17 + Patent2Net/media/graph-recipes/.gitignore | 53 + Patent2Net/media/graph-recipes/README.md | 30 + Patent2Net/media/graph-recipes/app/app.css | 183 + Patent2Net/media/graph-recipes/app/app.js | 498 + .../graph-recipes/app/assets/FileSaver.min.js | 2 + .../media/graph-recipes/app/assets/ace/ace.js | 18280 ++ .../app/assets/ace/ext-beautify.js | 334 + .../app/assets/ace/ext-chromevox.js | 541 + .../assets/ace/ext-elastic_tabstops_lite.js | 275 + .../graph-recipes/app/assets/ace/ext-emmet.js | 1190 + .../app/assets/ace/ext-error_marker.js | 6 + .../app/assets/ace/ext-keybinding_menu.js | 170 + .../app/assets/ace/ext-language_tools.js | 1936 + .../app/assets/ace/ext-linking.js | 52 + .../app/assets/ace/ext-modelist.js | 190 + .../app/assets/ace/ext-old_ie.js | 494 + .../app/assets/ace/ext-searchbox.js | 409 + .../app/assets/ace/ext-settings_menu.js | 640 + .../app/assets/ace/ext-spellcheck.js | 71 + .../graph-recipes/app/assets/ace/ext-split.js | 246 + .../app/assets/ace/ext-static_highlight.js | 154 + .../app/assets/ace/ext-statusbar.js | 51 + .../app/assets/ace/ext-textarea.js | 632 + .../app/assets/ace/ext-themelist.js | 58 + .../app/assets/ace/ext-whitespace.js | 181 + .../app/assets/ace/keybinding-emacs.js | 1182 + .../app/assets/ace/keybinding-vim.js | 5387 + .../app/assets/ace/mode-asciidoc.js | 342 + .../app/assets/ace/mode-javascript.js | 1025 + .../graph-recipes/app/assets/ace/mode-json.js | 668 + .../app/assets/ace/mode-markdown.js | 2820 + .../graph-recipes/app/assets/ace/mode-svg.js | 1802 + .../graph-recipes/app/assets/ace/mode-text.js | 1 + .../app/assets/ace/snippets/abap.js | 7 + .../app/assets/ace/snippets/abc.js | 38 + .../app/assets/ace/snippets/actionscript.js | 159 + .../app/assets/ace/snippets/ada.js | 7 + .../app/assets/ace/snippets/apache_conf.js | 7 + .../app/assets/ace/snippets/applescript.js | 7 + .../app/assets/ace/snippets/asciidoc.js | 7 + .../app/assets/ace/snippets/assembly_x86.js | 7 + .../app/assets/ace/snippets/autohotkey.js | 7 + .../app/assets/ace/snippets/batchfile.js | 7 + .../app/assets/ace/snippets/c9search.js | 7 + .../app/assets/ace/snippets/c_cpp.js | 138 + .../app/assets/ace/snippets/cirru.js | 7 + .../app/assets/ace/snippets/clojure.js | 97 + .../app/assets/ace/snippets/cobol.js | 7 + .../app/assets/ace/snippets/coffee.js | 102 + .../app/assets/ace/snippets/coldfusion.js | 7 + .../app/assets/ace/snippets/csharp.js | 7 + .../app/assets/ace/snippets/css.js | 974 + .../app/assets/ace/snippets/curly.js | 7 + .../app/assets/ace/snippets/d.js | 7 + .../app/assets/ace/snippets/dart.js | 90 + .../app/assets/ace/snippets/diff.js | 18 + .../app/assets/ace/snippets/django.js | 115 + .../app/assets/ace/snippets/dockerfile.js | 7 + .../app/assets/ace/snippets/dot.js | 7 + .../app/assets/ace/snippets/eiffel.js | 7 + .../app/assets/ace/snippets/ejs.js | 7 + .../app/assets/ace/snippets/elixir.js | 7 + .../app/assets/ace/snippets/elm.js | 7 + .../app/assets/ace/snippets/erlang.js | 167 + .../app/assets/ace/snippets/forth.js | 7 + .../app/assets/ace/snippets/ftl.js | 7 + .../app/assets/ace/snippets/gcode.js | 7 + .../app/assets/ace/snippets/gherkin.js | 7 + .../app/assets/ace/snippets/gitignore.js | 7 + .../app/assets/ace/snippets/glsl.js | 7 + .../app/assets/ace/snippets/golang.js | 7 + .../app/assets/ace/snippets/groovy.js | 7 + .../app/assets/ace/snippets/haml.js | 27 + .../app/assets/ace/snippets/handlebars.js | 7 + .../app/assets/ace/snippets/haskell.js | 89 + .../app/assets/ace/snippets/haxe.js | 7 + .../app/assets/ace/snippets/html.js | 835 + .../app/assets/ace/snippets/html_ruby.js | 7 + .../app/assets/ace/snippets/ini.js | 7 + .../app/assets/ace/snippets/io.js | 69 + .../app/assets/ace/snippets/jack.js | 7 + .../app/assets/ace/snippets/jade.js | 7 + .../app/assets/ace/snippets/java.js | 241 + .../app/assets/ace/snippets/javascript.js | 189 + .../app/assets/ace/snippets/json.js | 7 + .../app/assets/ace/snippets/jsoniq.js | 68 + .../app/assets/ace/snippets/jsp.js | 106 + .../app/assets/ace/snippets/jsx.js | 7 + .../app/assets/ace/snippets/julia.js | 7 + .../app/assets/ace/snippets/latex.js | 7 + .../app/assets/ace/snippets/lean.js | 7 + .../app/assets/ace/snippets/less.js | 7 + .../app/assets/ace/snippets/liquid.js | 7 + .../app/assets/ace/snippets/lisp.js | 7 + .../app/assets/ace/snippets/live_script.js | 7 + .../app/assets/ace/snippets/livescript.js | 7 + .../app/assets/ace/snippets/logiql.js | 7 + .../app/assets/ace/snippets/lsl.js | 1073 + .../app/assets/ace/snippets/lua.js | 28 + .../app/assets/ace/snippets/luapage.js | 7 + .../app/assets/ace/snippets/lucene.js | 7 + .../app/assets/ace/snippets/makefile.js | 11 + .../app/assets/ace/snippets/markdown.js | 95 + .../app/assets/ace/snippets/mask.js | 7 + .../app/assets/ace/snippets/matlab.js | 7 + .../app/assets/ace/snippets/mel.js | 7 + .../app/assets/ace/snippets/mips_assembler.js | 7 + .../app/assets/ace/snippets/mipsassembler.js | 7 + .../app/assets/ace/snippets/mushcode.js | 7 + .../app/assets/ace/snippets/mysql.js | 7 + .../app/assets/ace/snippets/nix.js | 7 + .../app/assets/ace/snippets/objectivec.js | 7 + .../app/assets/ace/snippets/ocaml.js | 7 + .../app/assets/ace/snippets/pascal.js | 7 + .../app/assets/ace/snippets/perl.js | 354 + .../app/assets/ace/snippets/pgsql.js | 7 + .../app/assets/ace/snippets/php.js | 283 + .../app/assets/ace/snippets/plain_text.js | 7 + .../app/assets/ace/snippets/powershell.js | 7 + .../app/assets/ace/snippets/praat.js | 7 + .../app/assets/ace/snippets/prolog.js | 7 + .../app/assets/ace/snippets/properties.js | 7 + .../app/assets/ace/snippets/protobuf.js | 7 + .../app/assets/ace/snippets/python.js | 165 + .../app/assets/ace/snippets/r.js | 128 + .../app/assets/ace/snippets/rdoc.js | 7 + .../app/assets/ace/snippets/rhtml.js | 7 + .../app/assets/ace/snippets/ruby.js | 935 + .../app/assets/ace/snippets/rust.js | 7 + .../app/assets/ace/snippets/sass.js | 7 + .../app/assets/ace/snippets/scad.js | 7 + .../app/assets/ace/snippets/scala.js | 7 + .../app/assets/ace/snippets/scheme.js | 7 + .../app/assets/ace/snippets/scss.js | 7 + .../app/assets/ace/snippets/sh.js | 90 + .../app/assets/ace/snippets/sjs.js | 7 + .../app/assets/ace/snippets/smarty.js | 7 + .../app/assets/ace/snippets/snippets.js | 16 + .../app/assets/ace/snippets/soy_template.js | 7 + .../app/assets/ace/snippets/space.js | 7 + .../app/assets/ace/snippets/sql.js | 33 + .../app/assets/ace/snippets/stylus.js | 7 + .../app/assets/ace/snippets/svg.js | 7 + .../app/assets/ace/snippets/tcl.js | 99 + .../app/assets/ace/snippets/tex.js | 197 + .../app/assets/ace/snippets/text.js | 7 + .../app/assets/ace/snippets/textile.js | 37 + .../app/assets/ace/snippets/toml.js | 7 + .../app/assets/ace/snippets/twig.js | 7 + .../app/assets/ace/snippets/typescript.js | 7 + .../app/assets/ace/snippets/vala.js | 193 + .../app/assets/ace/snippets/vbscript.js | 7 + .../app/assets/ace/snippets/velocity.js | 36 + .../app/assets/ace/snippets/verilog.js | 7 + .../app/assets/ace/snippets/vhdl.js | 7 + .../app/assets/ace/snippets/xml.js | 7 + .../app/assets/ace/snippets/xquery.js | 68 + .../app/assets/ace/snippets/yaml.js | 7 + .../app/assets/ace/theme-chrome.js | 128 + .../app/assets/ace/theme-clouds.js | 96 + .../app/assets/ace/theme-clouds_midnight.js | 97 + .../app/assets/ace/theme-twilight.js | 110 + .../app/assets/ace/worker-javascript.js | 11019 ++ .../app/assets/ace/worker-json.js | 2318 + .../app/assets/doc/attributestapas.png | Bin 0 -> 14835 bytes .../app/assets/doc/cloud_dark.png | Bin 0 -> 98545 bytes .../app/assets/doc/cloud_default.png | Bin 0 -> 152261 bytes .../app/assets/doc/fuzzyclusters_blurry.png | Bin 0 -> 58281 bytes .../app/assets/doc/fuzzyclusters_category.png | Bin 0 -> 83784 bytes .../app/assets/doc/fuzzyclusters_contour.png | Bin 0 -> 45057 bytes .../app/assets/doc/fuzzyclusters_language.png | Bin 0 -> 85755 bytes .../app/assets/doc/pixeldeluxe_halo0.png | Bin 0 -> 190900 bytes .../app/assets/doc/pixeldeluxe_halo10.png | Bin 0 -> 189079 bytes .../app/assets/doc/pixeldeluxe_halo100.png | Bin 0 -> 115304 bytes .../assets/doc/voronoi_nosize_illimited.png | Bin 0 -> 46144 bytes .../app/assets/doc/voronoi_nosize_limited.png | Bin 0 -> 69305 bytes .../app/assets/doc/voronoi_size_illimited.png | Bin 0 -> 39535 bytes .../app/assets/doc/voronoi_size_limited.png | Bin 0 -> 113146 bytes .../graph-recipes/app/assets/gexf.min.js | 2 + .../media/graph-recipes/app/assets/visual.png | Bin 0 -> 1094203 bytes Patent2Net/media/graph-recipes/app/bundle.js | 132643 +++++++++++++++ Patent2Net/media/graph-recipes/app/index.html | 46 + .../media/graph-recipes/app/jsEditor.html | 3 + Patent2Net/media/graph-recipes/app/lcd.html | 2 + Patent2Net/media/graph-recipes/app/lcd.svg | 1518 + .../media/graph-recipes/app/medialab.png | Bin 0 -> 4177 bytes Patent2Net/media/graph-recipes/app/meta.json | 10 + .../app/recipes/_recipes_list_.js | 79 + .../graph-recipes/app/recipes/attributes.js | 76 + .../graph-recipes/app/recipes/betweenness.js | 196 + .../media/graph-recipes/app/recipes/cloud.js | 455 + .../graph-recipes/app/recipes/deluxecanvas.js | 386 + .../graph-recipes/app/recipes/deluxesvg.js | 613 + .../media/graph-recipes/app/recipes/empty.js | 1 + .../graph-recipes/app/recipes/forceatlas2.js | 24 + .../app/recipes/fulldiagnostic.js | 339 + .../app/recipes/fuzzyclusters.js | 422 + .../graph-recipes/app/recipes/heatmap.js | 185 + .../graph-recipes/app/recipes/partition.js | 1010 + .../media/graph-recipes/app/recipes/sigma.js | 129 + .../graph-recipes/app/recipes/simplecanvas.js | 182 + .../graph-recipes/app/recipes/simplesvg.js | 260 + .../graph-recipes/app/recipes/voronoi.js | 216 + .../graph-recipes/app/sample rio+20.gexf | 11424 ++ .../media/graph-recipes/app/settings.json | 12 + Patent2Net/media/graph-recipes/app/utils.js | 4 + .../graph-recipes/app/view_board/board.html | 99 + .../graph-recipes/app/view_board/board.js | 107 + .../graph-recipes/app/view_upload/upload.html | 55 + .../graph-recipes/app/view_upload/upload.js | 243 + Patent2Net/media/graph-recipes/meta.json | 10 + Patent2Net/media/graph-recipes/package.json | 38 + .../media/graph-recipes/webpack.config.js | 14 + 215 files changed, 212477 insertions(+), 1 deletion(-) delete mode 160000 Patent2Net/media/graph-recipes create mode 100644 Patent2Net/media/graph-recipes/.gitattributes create mode 100644 Patent2Net/media/graph-recipes/.gitignore create mode 100644 Patent2Net/media/graph-recipes/README.md create mode 100644 Patent2Net/media/graph-recipes/app/app.css create mode 100644 Patent2Net/media/graph-recipes/app/app.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/FileSaver.min.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ace.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-beautify.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-chromevox.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-elastic_tabstops_lite.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-emmet.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-error_marker.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-keybinding_menu.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-language_tools.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-linking.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-modelist.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-old_ie.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-searchbox.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-settings_menu.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-spellcheck.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-split.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-static_highlight.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-statusbar.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-textarea.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-themelist.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/ext-whitespace.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/keybinding-emacs.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/keybinding-vim.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/mode-asciidoc.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/mode-javascript.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/mode-json.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/mode-markdown.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/mode-svg.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/mode-text.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/abap.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/abc.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/actionscript.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/ada.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/apache_conf.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/applescript.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/asciidoc.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/assembly_x86.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/autohotkey.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/batchfile.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/c9search.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/c_cpp.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/cirru.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/clojure.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/cobol.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/coffee.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/coldfusion.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/csharp.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/css.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/curly.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/d.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/dart.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/diff.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/django.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/dockerfile.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/dot.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/eiffel.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/ejs.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/elixir.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/elm.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/erlang.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/forth.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/ftl.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/gcode.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/gherkin.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/gitignore.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/glsl.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/golang.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/groovy.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/haml.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/handlebars.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/haskell.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/haxe.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/html.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/html_ruby.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/ini.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/io.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/jack.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/jade.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/java.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/javascript.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/json.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsoniq.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsp.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsx.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/julia.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/latex.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/lean.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/less.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/liquid.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/lisp.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/live_script.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/livescript.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/logiql.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/lsl.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/lua.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/luapage.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/lucene.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/makefile.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/markdown.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/mask.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/matlab.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/mel.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/mips_assembler.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/mipsassembler.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/mushcode.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/mysql.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/nix.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/objectivec.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/ocaml.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/pascal.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/perl.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/pgsql.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/php.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/plain_text.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/powershell.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/praat.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/prolog.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/properties.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/protobuf.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/python.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/r.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/rdoc.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/rhtml.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/ruby.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/rust.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/sass.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/scad.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/scala.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/scheme.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/scss.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/sh.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/sjs.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/smarty.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/snippets.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/soy_template.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/space.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/sql.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/stylus.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/svg.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/tcl.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/tex.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/text.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/textile.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/toml.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/twig.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/typescript.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/vala.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/vbscript.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/velocity.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/verilog.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/vhdl.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/xml.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/xquery.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/snippets/yaml.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/theme-chrome.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/theme-clouds.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/theme-clouds_midnight.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/theme-twilight.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/worker-javascript.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/ace/worker-json.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/attributestapas.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/cloud_dark.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/cloud_default.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/fuzzyclusters_blurry.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/fuzzyclusters_category.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/fuzzyclusters_contour.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/fuzzyclusters_language.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/pixeldeluxe_halo0.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/pixeldeluxe_halo10.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/pixeldeluxe_halo100.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/voronoi_nosize_illimited.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/voronoi_nosize_limited.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/voronoi_size_illimited.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/doc/voronoi_size_limited.png create mode 100644 Patent2Net/media/graph-recipes/app/assets/gexf.min.js create mode 100644 Patent2Net/media/graph-recipes/app/assets/visual.png create mode 100644 Patent2Net/media/graph-recipes/app/bundle.js create mode 100644 Patent2Net/media/graph-recipes/app/index.html create mode 100644 Patent2Net/media/graph-recipes/app/jsEditor.html create mode 100644 Patent2Net/media/graph-recipes/app/lcd.html create mode 100644 Patent2Net/media/graph-recipes/app/lcd.svg create mode 100644 Patent2Net/media/graph-recipes/app/medialab.png create mode 100644 Patent2Net/media/graph-recipes/app/meta.json create mode 100644 Patent2Net/media/graph-recipes/app/recipes/_recipes_list_.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/attributes.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/betweenness.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/cloud.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/deluxecanvas.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/deluxesvg.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/empty.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/forceatlas2.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/fulldiagnostic.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/fuzzyclusters.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/heatmap.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/partition.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/sigma.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/simplecanvas.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/simplesvg.js create mode 100644 Patent2Net/media/graph-recipes/app/recipes/voronoi.js create mode 100644 Patent2Net/media/graph-recipes/app/sample rio+20.gexf create mode 100644 Patent2Net/media/graph-recipes/app/settings.json create mode 100644 Patent2Net/media/graph-recipes/app/utils.js create mode 100644 Patent2Net/media/graph-recipes/app/view_board/board.html create mode 100644 Patent2Net/media/graph-recipes/app/view_board/board.js create mode 100644 Patent2Net/media/graph-recipes/app/view_upload/upload.html create mode 100644 Patent2Net/media/graph-recipes/app/view_upload/upload.js create mode 100644 Patent2Net/media/graph-recipes/meta.json create mode 100644 Patent2Net/media/graph-recipes/package.json create mode 100644 Patent2Net/media/graph-recipes/webpack.config.js diff --git a/Patent2Net/media/graph-recipes b/Patent2Net/media/graph-recipes deleted file mode 160000 index 000c343b..00000000 --- a/Patent2Net/media/graph-recipes +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 000c343b2a20bef1b81cb6d8cc452e12fde9de80 diff --git a/Patent2Net/media/graph-recipes/.gitattributes b/Patent2Net/media/graph-recipes/.gitattributes new file mode 100644 index 00000000..bdb0cabc --- /dev/null +++ b/Patent2Net/media/graph-recipes/.gitattributes @@ -0,0 +1,17 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/Patent2Net/media/graph-recipes/.gitignore b/Patent2Net/media/graph-recipes/.gitignore new file mode 100644 index 00000000..63fb58c1 --- /dev/null +++ b/Patent2Net/media/graph-recipes/.gitignore @@ -0,0 +1,53 @@ +node_modules/* +bower_components/* + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + +.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Bundled JS +package-lock.json diff --git a/Patent2Net/media/graph-recipes/README.md b/Patent2Net/media/graph-recipes/README.md new file mode 100644 index 00000000..cf8cd35e --- /dev/null +++ b/Patent2Net/media/graph-recipes/README.md @@ -0,0 +1,30 @@ +# Graph Recipes + +A small static website in Angular to tinker with networks, based on Graphology. + +## Install + +### Install the dependencies & build the code + +``` +# This will install the deps & build the code for production +npm install + +# To rebuild the code manually +npm run build +``` + +### Dev commands + +``` +# Just watch the files & retranspile (e.g. when serving app with Apache) +npm run watch + +# Watch the files & serve the application on localhost:3000 +npm run dev +``` + +## Usage +The website is in the app folder. Browse, upload a GEXF network, pick a script (they are called "recipes") and execute it. + +The scripts do a number of things: compute statistics, give informations, draw images, and more. diff --git a/Patent2Net/media/graph-recipes/app/app.css b/Patent2Net/media/graph-recipes/app/app.css new file mode 100644 index 00000000..04892187 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/app.css @@ -0,0 +1,183 @@ +#sidecol { + width: 300px; +} + +.command-zone { + font-family: 'Raleway', sans-serif; + overflow-y: auto; +} + +.network-info { + padding: 12px; +} + +.content { + overflow-y: auto; + overflow-x: hidden; +} + +.fancy-text { + font-family: 'Raleway', sans-serif; + font-size: 1.2em; + color: #534b45; + background-color: #EDE9E2; +} + +.fancy-text .main-title { + font-family: 'Lobster', cursive; + font-weight: 400; + font-size: 2.6em; + margin-top: 0; + margin-bottom: 12px; +} + +h1 .subtitle { + font-family: 'Raleway', cursive; + font-weight: 300; + font-size: 0.6em; + display: block; +} + +/* Links */ +a { + transition: color .4s; + color: #53aaea; + text-decoration: none; +} + +a:link, +a:visited { color: #53aaea; } +a:hover { color: #7FDBFF; } +a:active { + transition: color .3s; + color: #007BE6; +} + +/* Menu items */ +.menu-container { + overflow-y: auto; +} +.menu-item { + cursor: pointer; +} +.menu-item:hover { + background-color: #dbedf0; +} +.menu-item h3 { + font-family: 'Lobster', cursive; + font-weight: 400; + font-size: 1.4em; + margin: 0; +} +.menu-item p { + margin: 0; +} + +h3.script-title { + font-family: 'Lobster', cursive; + font-weight: 400; + font-size: 1.4em; + margin: 0; + padding: 0; +} + +/* Uploader */ +.upload-background { + background-color: #7595af; +} +.upload-area-container{ + user-select: none; + outline: none; + cursor: pointer; +} +.upload-area-container .upload-area{ + background-color: #FFFFFF; + box-sizing: border-box; + width: 100%; + height: 100%; + border-radius: 2px; + box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.3); + + -webkit-transition: background-color .2s; + transition: background-color .2s; +} +.upload-area-container:hover .upload-area, .upload-area-container.over .upload-area{ + background-color: #53aaea; +} +.upload-area-container.loading .upload-area{ + background-color: #46b8da; +} +.upload-area-container.success .upload-area{ + background-color: #5cb85c; +} +.upload-area-container.error .upload-area{ + background-color: #FF0000; +} +.upload-text-main{ + font-family: 'Raleway', sans-serif; + font-size: 28px; +} +.upload-area-container:hover .upload-text-main, +.upload-area-container.over .upload-text-main, +.upload-area-container.loading .upload-text-main, +.upload-area-container.success .upload-text-main +{ + color: #FFF; +} +.upload-text-sub{ + font-family: 'Raleway', sans-serif; + color: #AAA; + font-size: 16px; +} +.upload-area-container:hover .upload-text-sub, +.upload-area-container.over .upload-text-sub +{ + color: #FFF; +} +.upload-area-container.loading .upload-text-sub, +.upload-area-container.success .upload-text-sub +{ + display: none; +} + +.upload-info { + position: absolute; + top: 12px; + left: 12px; + bottom: 12px; + right: 12px; + color: #A28D8D; +} + +.upload-info img { + opacity: 0.5; +} + +.upload-info h1 { + font-size: 3.2em; + font-weight: 200; + margin-top: 0px; + margin-bottom: 3px; +} + +/* JS editor */ +#js-editor-container { + overflow: hidden; +} +.shortcut-info { + font-size: 0.8em; + opacity: 0.6; +} +.exec-button-row { + padding-bottom: 6px; +} + +/* Playground */ +#playground { + background-color: #FFF; + overflow: auto; +} +#dummy-font-div { + /* Load the fonts we plan to use in the canvas */ + font-family: 'Open Sans Condensed', sans-serif; +} \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/app.js b/Patent2Net/media/graph-recipes/app/app.js new file mode 100644 index 00000000..ca13dad9 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/app.js @@ -0,0 +1,498 @@ +'use strict'; + +window.app = (settings) => { + + window.settings = settings || {} + console.log(settings) + + // Requiring module's CSS + require('angular-material/angular-material.min.css'); + + // Requiring angular-related modules that will spit things in the global scope + require('angular'); + require('angular-animate'); + require('angular-aria'); + require('angular-material'); + require('angular-route'); + + // Making some modules global for the custom scripts to consume + var d3 = require('d3'); + window.d3 = d3; + var numeric = require('numeric'); + window.numeric = numeric; + + // Requiring some graphology libraries we are going to make global for the user + var graphology = require('graphology'); + + graphology.library = require('graphology-library/browser'); + window.graphology = graphology; + window.Graph = graphology; + + var randomLayout = graphology.library.layout.random; + + var forceAtlas2Layout = graphology.library.layoutForceAtlas2; + window.layout = { + random: randomLayout, + forceAtlas2: forceAtlas2Layout + }; + + window.ForceAtlas2Layout = graphology.library.FA2Layout; + + window.louvain = graphology.library.communitiesLouvain; + + // Requiring sigma + window.SigmaWebGLRenderer = require('sigma/renderers/webgl').default; + + // Requiring own modules + require('./view_upload/upload.js'); + require('./view_board/board.js'); + require('./recipes/_recipes_list_.js'); + + // Declare app level module which depends on views, and components + angular.module('graphrecipes', [ + 'ngRoute', + 'ngMaterial', + 'graphrecipes.view_upload', + 'graphrecipes.view_board', + 'graphrecipes.recipes_list' + ]). + config(['$routeProvider', function($routeProvider) { + $routeProvider.otherwise({redirectTo: '/upload'}); + }]) + + // Filters + .filter('number', function() { + return function(d) { + return +d + } + }) + .filter('percent', function() { + return function(d) { + return Math.round(+d*100)+'%' + } + }) + + // Service + .factory('cache', function(){ + var ns = {} + ns.recipes = {} + return ns + }) + + + // Directives + .directive('jsEditor', function ($timeout, $interval, $http, cache) { + return { + restrict: 'A', + scope: { + file: '=', + remind: '=' + }, + templateUrl: 'jsEditor.html', + link: function(scope, element, attrs, ctrl) { + if (scope.remind) { + $timeout(function(){ + // INITIALIZATION + if(cache.recipes[scope.file]){ + document.querySelector('#js-editor').textContent = cache.recipes[scope.file] + } + initAceJS() + }) + } else { + $http.get(scope.file).then(function (data) { + $timeout(function(){ + // INITIALIZATION + if(data.data){ + document.querySelector('#js-editor').textContent = data.data + cache.recipes[scope.file] = data.data + } + initAceJS() + }) + }) + } + scope.$on('$destroy', function(){ + if (window.editor) { + window.editor.destroy() + } + }) + scope.codeKeyPress = function(e){ + if((e.which == 13 || e.which == 10) && (e.ctrlKey || e.shiftKey)){ + scope.$parent.executeScript() + } + } + + function initAceJS() { + // Init Ace JS editor panel + // Note: we keep editor in global scope to be able to edit settings from the console + window.editor = ace.edit("js-editor"); + window.editor.setTheme("ace/theme/clouds"); + window.editor.setFontSize(14) + window.editor.getSession().setMode("ace/mode/javascript"); + window.editor.on('change', function(){ + $timeout(function(){ + cache.recipes[scope.file] = window.editor.getValue() + scope.$apply() + }) + }) + } + } + } + }) + + .directive('lcd', function ($timeout, $interval) { + return { + restrict: 'A', + scope: { + animStatus: '=' + }, + templateUrl: 'lcd.html', + link: function(scope, element, attrs, ctrl) { + var obj = element.find('object') + var sprites = [ + "wait", + "smokesmall", + "smokebig", + "splash", + "casserole", + "flyingfoodbit", + "cookoven", + "cooktop1", + "cooktop2", + "cooklegs", + "cookarmknife1", + "cookarmknife2", + "cookarmknife3", + "foodcut", + "foodbits", + "foodstackbottom", + "foodstackmiddle", + "foodstacktop", + "cooksleeping", + "zzz", + "ovenfood", + "closedovendoor", + "openovendoor", + "closeddoor", + "opendoor", + "cookstanding", + "cookarmnote", + "pen3", + "pen2", + "pen1", + "cookserving", + "cookbubble", + "clientbubble", + "menu", + "spoon", + "dish", + "clientarm1", + "clientarm2", + "flyingdishpiece1", + "flyingdishpiece2", + "clienthead1", + "clienthead2", + "clienthead3", + "thinkbubble", + "background" + ] + var animIntervals = [] + + // obj.removeClass("ng-hide"); + + $timeout(function(){ + // sprites.forEach(hideSprite) + scope.$watch('animStatus', applyStatus) + }, 100) + + function hideSprite(s) { + if (obj[0].contentDocument) + obj[0].contentDocument.getElementById(s).style.display = "none" + } + + function showSprite(s) { + if (obj[0].contentDocument) + obj[0].contentDocument.getElementById(s).style.display = "inline" + } + + function applyStatus(e, os, ns) { + if (os != ns) { + animIntervals.forEach(function(promise){ + $interval.cancel(promise) + }) + sprites.forEach(hideSprite) + switch (scope.animStatus) { + case 'off': + // Nothing to do, everything off by default + break; + + case 'error': + sprites + .filter(function(){return Math.random()>0.5}) + .forEach(function(sprite){ + showSprite(sprite) + }) + break; + + case 'waiting': + showSprite('background') + showSprite('closeddoor') + showSprite('openovendoor') + showSprite('cooksleeping') + showSprite('clienthead3') + break; + + case 'choose-recipe': + showSprite('background') + showSprite('foodstacktop') + showSprite('foodstackmiddle') + showSprite('foodstackbottom') + showSprite('closeddoor') + showSprite('closedovendoor') + showSprite('cooksleeping') + addAnimInterval([ + {'zzz': true}, {'zzz': false} + ], 600) + addAnimInterval([ + {'clienthead3': true , 'thinkbubble': true , 'clienthead1': false, 'clientarm1': false, 'menu': false}, + {'clienthead3': false, 'thinkbubble': false, 'clienthead1': true , 'clientarm1': true , 'menu': true} + ], 1500) + break; + + case 'edit-script': + showSprite('background') + showSprite('foodstacktop') + showSprite('foodstackmiddle') + showSprite('foodstackbottom') + showSprite('opendoor') + showSprite('closedovendoor') + showSprite('clientarm1') + showSprite('cookstanding') + showSprite('menu') + addAnimInterval([ + { + 'clienthead1': false, + 'clienthead2': true, + 'clientbubble': true, + 'cookbubble': false + }, + { + 'clienthead1': true, + 'clienthead2': false, + 'clientbubble': false, + 'cookbubble': true + } + ], 9*75) + addAnimInterval([ + {'cookarmnote': true, 'pen1': true}, + {'pen1': false, 'pen2': true}, + {'pen2': false, 'pen3': true}, + {'pen3': false, 'pen2': true}, + {'pen2': false, 'pen1': true}, + {'pen1': false, 'pen2': true}, + {'pen2': false, 'pen3': true}, + {'pen3': false, 'pen2': true}, + {'pen2': false, 'pen1': true}, + {'pen1': false, 'cookarmnote': false}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {} + ], 75) + break; + + case 'cooking': + showSprite('background') + showSprite('closeddoor') + showSprite('closedovendoor') + showSprite('clienthead3') + showSprite('casserole') + addAnimInterval([ + { + 'foodcut': true, + 'cooklegs': true, + 'splash': false, + 'cooktop1': false, + 'cooktop2': true, + 'cookarmknife1': true + }, + {'cookarmknife1': false, 'cookarmknife2': true}, + {'cookarmknife2': false, 'cookarmknife3': true, 'foodbits': true}, + {'cookarmknife3': false, 'cookarmknife2': true}, + {'cookarmknife2': false, 'cookarmknife1': true, 'foodbits': false}, + {'cookarmknife1': false, 'cookarmknife2': true}, + {'cookarmknife2': false, 'cookarmknife3': true, 'foodbits': true}, + {'cookarmknife3': false, 'cookarmknife2': true}, + {'cookarmknife2': false, 'cookarmknife1': true, 'foodbits': false}, + {'cookarmknife1': false, 'cookarmknife2': true}, + {'cookarmknife2': false, 'cookarmknife3': true, 'foodbits': true}, + { + 'cookarmknife3': false, + 'foodbits': false, + 'foodcut': false, + 'cooktop2': false, + 'cooktop1': true, + }, + {'flyingfoodbit': true}, + { + 'flyingfoodbit': false, + 'splash': true + } + ], 50) + + addAnimInterval([ + { + 'foodstackbottom': true, + 'foodstackmiddle': true + }, + {'foodstackmiddle': false}, + {'foodstackbottom': false} + ], 14*50) + + // Phase 2 + $timeout(function(){ + if (scope.animStatus != 'cooking') { return } + animIntervals.forEach(function(promise){ + $interval.cancel(promise) + }) + sprites.forEach(hideSprite) + showSprite('background') + showSprite('clienthead3') + showSprite('closeddoor') + addAnimInterval([ + { + 'cookoven': true, + 'openovendoor': true, + 'casserole': true + }, + {'casserole': false, 'ovenfood': true}, + {'openovendoor': false, 'closedovendoor': true} + ], 150) + + // Phase 3 + $timeout(function(){ + if (scope.animStatus != 'cooking') { return } + animIntervals.forEach(function(promise){ + $interval.cancel(promise) + }) + sprites.forEach(hideSprite) + showSprite('background') + showSprite('clienthead3') + showSprite('closeddoor') + showSprite('closedovendoor') + showSprite('ovenfood') + showSprite('cooksleeping') + showSprite('wait') + addAnimInterval([ + {'zzz': true}, {'zzz': false} + ], 600) + addAnimInterval([ + {'smokebig': true, 'smokesmall': false}, {'smokebig': false, 'smokesmall': true} + ], 800) + + }, 3*150) + + }, 14*50*3) + + break; + + case 'service': + showSprite('background') + showSprite('closeddoor') + showSprite('clienthead3') + addAnimInterval([ + { + 'closedovendoor': true, + 'cookoven': true, + 'ovenfood': true + }, + {'closedovendoor': false, 'openovendoor': true}, + { + 'ovenfood': false, + 'cookoven': false, + 'closeddoor': false, + 'opendoor': true, + 'cookserving': true, + }, + {'clienthead3': false, 'clienthead2': true}, + {'cookserving': false, 'cookstanding': true, 'dish': true}, + { + 'clienthead2': false, + 'clienthead1': true, + 'clientarm1': true, + 'spoon': true, + 'cookstanding': false, + 'opendoor': false, + 'closeddoor': true, + 'cooksleeping': true + } + ], 300) + + // Phase 2 + $timeout(function(){ + if (scope.animStatus != 'service') { return } + animIntervals.forEach(function(promise){ + $interval.cancel(promise) + }) + sprites.forEach(hideSprite) + showSprite('background') + showSprite('closeddoor') + showSprite('openovendoor') + showSprite('cooksleeping') + showSprite('dish') + addAnimInterval([ + {'zzz': true}, {'zzz': false} + ], 600) + addAnimInterval([ + { + 'clienthead1': false, + 'clienthead2': true, + 'clientarm1': true, + 'spoon': true + }, + { + 'clientarm1': false, + 'spoon': false, + 'clientarm2': true + }, + {'flyingdishpiece1': true}, + {'flyingdishpiece1': false, 'flyingdishpiece2': true, 'clientarm2': false, 'clientarm1': true}, + {'clienthead2': false, 'clienthead1': true, 'flyingdishpiece2': false, 'spoon': true} + ], 100) + }, 6*300) + } + } + } + + function addAnimInterval(sequence, delay) { + var sprite + for(sprite in sequence[0]) { + if (sequence[0][sprite]) { + showSprite(sprite) + } else { + hideSprite(sprite) + } + } + + var count = 0 + var interval = $interval(function(){ + count = count + 1 + var moment = sequence[count%sequence.length] + for(sprite in moment) { + if (moment[sprite]) { + showSprite(sprite) + } else { + hideSprite(sprite) + } + } + }, delay || 500) + animIntervals.push(interval) + } + } + } + }) + +} diff --git a/Patent2Net/media/graph-recipes/app/assets/FileSaver.min.js b/Patent2Net/media/graph-recipes/app/assets/FileSaver.min.js new file mode 100644 index 00000000..eb062f25 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/FileSaver.min.js @@ -0,0 +1,2 @@ +/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ +var saveAs=saveAs||function(view){"use strict";if(typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var doc=view.document,get_URL=function(){return view.URL||view.webkitURL||view},save_link=doc.createElementNS("http://www.w3.org/1999/xhtml","a"),can_use_save_link="download"in save_link,click=function(node){var event=new MouseEvent("click");node.dispatchEvent(event)},is_safari=/Version\/[\d\.]+.*Safari/.test(navigator.userAgent),webkit_req_fs=view.webkitRequestFileSystem,req_fs=view.requestFileSystem||webkit_req_fs||view.mozRequestFileSystem,throw_outside=function(ex){(view.setImmediate||view.setTimeout)(function(){throw ex},0)},force_saveable_type="application/octet-stream",fs_min_size=0,arbitrary_revoke_timeout=500,revoke=function(file){var revoker=function(){if(typeof file==="string"){get_URL().revokeObjectURL(file)}else{file.remove()}};if(view.chrome){revoker()}else{setTimeout(revoker,arbitrary_revoke_timeout)}},dispatch=function(filesaver,event_types,event){event_types=[].concat(event_types);var i=event_types.length;while(i--){var listener=filesaver["on"+event_types[i]];if(typeof listener==="function"){try{listener.call(filesaver,event||filesaver)}catch(ex){throw_outside(ex)}}}},auto_bom=function(blob){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)){return new Blob(["\ufeff",blob],{type:blob.type})}return blob},FileSaver=function(blob,name,no_auto_bom){if(!no_auto_bom){blob=auto_bom(blob)}var filesaver=this,type=blob.type,blob_changed=false,object_url,target_view,dispatch_all=function(){dispatch(filesaver,"writestart progress write writeend".split(" "))},fs_error=function(){if(target_view&&is_safari&&typeof FileReader!=="undefined"){var reader=new FileReader;reader.onloadend=function(){var base64Data=reader.result;target_view.location.href="data:attachment/file"+base64Data.slice(base64Data.search(/[,;]/));filesaver.readyState=filesaver.DONE;dispatch_all()};reader.readAsDataURL(blob);filesaver.readyState=filesaver.INIT;return}if(blob_changed||!object_url){object_url=get_URL().createObjectURL(blob)}if(target_view){target_view.location.href=object_url}else{var new_tab=view.open(object_url,"_blank");if(new_tab==undefined&&is_safari){view.location.href=object_url}}filesaver.readyState=filesaver.DONE;dispatch_all();revoke(object_url)},abortable=function(func){return function(){if(filesaver.readyState!==filesaver.DONE){return func.apply(this,arguments)}}},create_if_not_found={create:true,exclusive:false},slice;filesaver.readyState=filesaver.INIT;if(!name){name="download"}if(can_use_save_link){object_url=get_URL().createObjectURL(blob);setTimeout(function(){save_link.href=object_url;save_link.download=name;click(save_link);dispatch_all();revoke(object_url);filesaver.readyState=filesaver.DONE});return}if(view.chrome&&type&&type!==force_saveable_type){slice=blob.slice||blob.webkitSlice;blob=slice.call(blob,0,blob.size,force_saveable_type);blob_changed=true}if(webkit_req_fs&&name!=="download"){name+=".download"}if(type===force_saveable_type||webkit_req_fs){target_view=view}if(!req_fs){fs_error();return}fs_min_size+=blob.size;req_fs(view.TEMPORARY,fs_min_size,abortable(function(fs){fs.root.getDirectory("saved",create_if_not_found,abortable(function(dir){var save=function(){dir.getFile(name,create_if_not_found,abortable(function(file){file.createWriter(abortable(function(writer){writer.onwriteend=function(event){target_view.location.href=file.toURL();filesaver.readyState=filesaver.DONE;dispatch(filesaver,"writeend",event);revoke(file)};writer.onerror=function(){var error=writer.error;if(error.code!==error.ABORT_ERR){fs_error()}};"writestart progress write abort".split(" ").forEach(function(event){writer["on"+event]=filesaver["on"+event]});writer.write(blob);filesaver.abort=function(){writer.abort();filesaver.readyState=filesaver.DONE};filesaver.readyState=filesaver.WRITING}),fs_error)}),fs_error)};dir.getFile(name,{create:false},abortable(function(file){file.remove();save()}),abortable(function(ex){if(ex.code===ex.NOT_FOUND_ERR){save()}else{fs_error()}}))}),fs_error)}),fs_error)},FS_proto=FileSaver.prototype,saveAs=function(blob,name,no_auto_bom){return new FileSaver(blob,name,no_auto_bom)};if(typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob){return function(blob,name,no_auto_bom){if(!no_auto_bom){blob=auto_bom(blob)}return navigator.msSaveOrOpenBlob(blob,name||"download")}}FS_proto.abort=function(){var filesaver=this;filesaver.readyState=filesaver.DONE;dispatch(filesaver,"abort")};FS_proto.readyState=FS_proto.INIT=0;FS_proto.WRITING=1;FS_proto.DONE=2;FS_proto.error=FS_proto.onwritestart=FS_proto.onprogress=FS_proto.onwrite=FS_proto.onabort=FS_proto.onerror=FS_proto.onwriteend=null;return saveAs}(typeof self!=="undefined"&&self||typeof window!=="undefined"&&window||this.content);if(typeof module!=="undefined"&&module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&&define!==null&&define.amd!=null){define([],function(){return saveAs})} diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ace.js b/Patent2Net/media/graph-recipes/app/assets/ace/ace.js new file mode 100644 index 00000000..ac42277b --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ace.js @@ -0,0 +1,18280 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +/** + * Define a module along with a payload + * @param module a name for the payload + * @param payload a function to call with (require, exports, module) params + */ + +(function() { + +var ACE_NAMESPACE = ""; + +var global = (function() { return this; })(); +if (!global && typeof window != "undefined") global = window; // strict mode + + +if (!ACE_NAMESPACE && typeof requirejs !== "undefined") + return; + + +var define = function(module, deps, payload) { + if (typeof module !== "string") { + if (define.original) + define.original.apply(this, arguments); + else { + console.error("dropping module because define wasn\'t a string."); + console.trace(); + } + return; + } + if (arguments.length == 2) + payload = deps; + if (!define.modules[module]) { + define.payloads[module] = payload; + define.modules[module] = null; + } +}; + +define.modules = {}; +define.payloads = {}; + +/** + * Get at functionality define()ed using the function above + */ +var _require = function(parentId, module, callback) { + if (typeof module === "string") { + var payload = lookup(parentId, module); + if (payload != undefined) { + callback && callback(); + return payload; + } + } else if (Object.prototype.toString.call(module) === "[object Array]") { + var params = []; + for (var i = 0, l = module.length; i < l; ++i) { + var dep = lookup(parentId, module[i]); + if (dep == undefined && require.original) + return; + params.push(dep); + } + return callback && callback.apply(null, params) || true; + } +}; + +var require = function(module, callback) { + var packagedModule = _require("", module, callback); + if (packagedModule == undefined && require.original) + return require.original.apply(this, arguments); + return packagedModule; +}; + +var normalizeModule = function(parentId, moduleName) { + // normalize plugin requires + if (moduleName.indexOf("!") !== -1) { + var chunks = moduleName.split("!"); + return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]); + } + // normalize relative requires + if (moduleName.charAt(0) == ".") { + var base = parentId.split("/").slice(0, -1).join("/"); + moduleName = base + "/" + moduleName; + + while(moduleName.indexOf(".") !== -1 && previous != moduleName) { + var previous = moduleName; + moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); + } + } + return moduleName; +}; + +/** + * Internal function to lookup moduleNames and resolve them by calling the + * definition function if needed. + */ +var lookup = function(parentId, moduleName) { + moduleName = normalizeModule(parentId, moduleName); + + var module = define.modules[moduleName]; + if (!module) { + module = define.payloads[moduleName]; + if (typeof module === 'function') { + var exports = {}; + var mod = { + id: moduleName, + uri: '', + exports: exports, + packaged: true + }; + + var req = function(module, callback) { + return _require(moduleName, module, callback); + }; + + var returnValue = module(req, exports, mod); + exports = returnValue || mod.exports; + define.modules[moduleName] = exports; + delete define.payloads[moduleName]; + } + module = define.modules[moduleName] = exports || module; + } + return module; +}; + +function exportAce(ns) { + var root = global; + if (ns) { + if (!global[ns]) + global[ns] = {}; + root = global[ns]; + } + + if (!root.define || !root.define.packaged) { + define.original = root.define; + root.define = define; + root.define.packaged = true; + } + + if (!root.require || !root.require.packaged) { + require.original = root.require; + root.require = require; + root.require.packaged = true; + } +} + +exportAce(ACE_NAMESPACE); + +})(); + +define("ace/lib/regexp",["require","exports","module"], function(require, exports, module) { +"use strict"; + + var real = { + exec: RegExp.prototype.exec, + test: RegExp.prototype.test, + match: String.prototype.match, + replace: String.prototype.replace, + split: String.prototype.split + }, + compliantExecNpcg = real.exec.call(/()??/, "")[1] === undefined, // check `exec` handling of nonparticipating capturing groups + compliantLastIndexIncrement = function () { + var x = /^/g; + real.test.call(x, ""); + return !x.lastIndex; + }(); + + if (compliantLastIndexIncrement && compliantExecNpcg) + return; + RegExp.prototype.exec = function (str) { + var match = real.exec.apply(this, arguments), + name, r2; + if ( typeof(str) == 'string' && match) { + if (!compliantExecNpcg && match.length > 1 && indexOf(match, "") > -1) { + r2 = RegExp(this.source, real.replace.call(getNativeFlags(this), "g", "")); + real.replace.call(str.slice(match.index), r2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undefined) + match[i] = undefined; + } + }); + } + if (this._xregexp && this._xregexp.captureNames) { + for (var i = 1; i < match.length; i++) { + name = this._xregexp.captureNames[i - 1]; + if (name) + match[name] = match[i]; + } + } + if (!compliantLastIndexIncrement && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + } + return match; + }; + if (!compliantLastIndexIncrement) { + RegExp.prototype.test = function (str) { + var match = real.exec.call(this, str); + if (match && this.global && !match[0].length && (this.lastIndex > match.index)) + this.lastIndex--; + return !!match; + }; + } + + function getNativeFlags (regex) { + return (regex.global ? "g" : "") + + (regex.ignoreCase ? "i" : "") + + (regex.multiline ? "m" : "") + + (regex.extended ? "x" : "") + // Proposed for ES4; included in AS3 + (regex.sticky ? "y" : ""); + } + + function indexOf (array, item, from) { + if (Array.prototype.indexOf) // Use the native array method if available + return array.indexOf(item, from); + for (var i = from || 0; i < array.length; i++) { + if (array[i] === item) + return i; + } + return -1; + } + +}); + +define("ace/lib/es5-shim",["require","exports","module"], function(require, exports, module) { + +function Empty() {} + +if (!Function.prototype.bind) { + Function.prototype.bind = function bind(that) { // .length is 1 + var target = this; + if (typeof target != "function") { + throw new TypeError("Function.prototype.bind called on incompatible " + target); + } + var args = slice.call(arguments, 1); // for normal call + var bound = function () { + + if (this instanceof bound) { + + var result = target.apply( + this, + args.concat(slice.call(arguments)) + ); + if (Object(result) === result) { + return result; + } + return this; + + } else { + return target.apply( + that, + args.concat(slice.call(arguments)) + ); + + } + + }; + if(target.prototype) { + Empty.prototype = target.prototype; + bound.prototype = new Empty(); + Empty.prototype = null; + } + return bound; + }; +} +var call = Function.prototype.call; +var prototypeOfArray = Array.prototype; +var prototypeOfObject = Object.prototype; +var slice = prototypeOfArray.slice; +var _toString = call.bind(prototypeOfObject.toString); +var owns = call.bind(prototypeOfObject.hasOwnProperty); +var defineGetter; +var defineSetter; +var lookupGetter; +var lookupSetter; +var supportsAccessors; +if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) { + defineGetter = call.bind(prototypeOfObject.__defineGetter__); + defineSetter = call.bind(prototypeOfObject.__defineSetter__); + lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); + lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); +} +if ([1,2].splice(0).length != 2) { + if(function() { // test IE < 9 to splice bug - see issue #138 + function makeArray(l) { + var a = new Array(l+2); + a[0] = a[1] = 0; + return a; + } + var array = [], lengthBefore; + + array.splice.apply(array, makeArray(20)); + array.splice.apply(array, makeArray(26)); + + lengthBefore = array.length; //46 + array.splice(5, 0, "XXX"); // add one element + + lengthBefore + 1 == array.length + + if (lengthBefore + 1 == array.length) { + return true;// has right splice implementation without bugs + } + }()) {//IE 6/7 + var array_splice = Array.prototype.splice; + Array.prototype.splice = function(start, deleteCount) { + if (!arguments.length) { + return []; + } else { + return array_splice.apply(this, [ + start === void 0 ? 0 : start, + deleteCount === void 0 ? (this.length - start) : deleteCount + ].concat(slice.call(arguments, 2))) + } + }; + } else {//IE8 + Array.prototype.splice = function(pos, removeCount){ + var length = this.length; + if (pos > 0) { + if (pos > length) + pos = length; + } else if (pos == void 0) { + pos = 0; + } else if (pos < 0) { + pos = Math.max(length + pos, 0); + } + + if (!(pos+removeCount < length)) + removeCount = length - pos; + + var removed = this.slice(pos, pos+removeCount); + var insert = slice.call(arguments, 2); + var add = insert.length; + if (pos === length) { + if (add) { + this.push.apply(this, insert); + } + } else { + var remove = Math.min(removeCount, length - pos); + var tailOldPos = pos + remove; + var tailNewPos = tailOldPos + add - remove; + var tailCount = length - tailOldPos; + var lengthAfterRemove = length - remove; + + if (tailNewPos < tailOldPos) { // case A + for (var i = 0; i < tailCount; ++i) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } else if (tailNewPos > tailOldPos) { // case B + for (i = tailCount; i--; ) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } // else, add == remove (nothing to do) + + if (add && pos === lengthAfterRemove) { + this.length = lengthAfterRemove; // truncate array + this.push.apply(this, insert); + } else { + this.length = lengthAfterRemove + add; // reserves space + for (i = 0; i < add; ++i) { + this[pos+i] = insert[i]; + } + } + } + return removed; + }; + } +} +if (!Array.isArray) { + Array.isArray = function isArray(obj) { + return _toString(obj) == "[object Array]"; + }; +} +var boxedString = Object("a"), + splitString = boxedString[0] != "a" || !(0 in boxedString); + +if (!Array.prototype.forEach) { + Array.prototype.forEach = function forEach(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + thisp = arguments[1], + i = -1, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + while (++i < length) { + if (i in self) { + fun.call(thisp, self[i], i, object); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function map(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = Array(length), + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) + result[i] = fun.call(thisp, self[i], i, object); + } + return result; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function filter(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = [], + value, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) { + value = self[i]; + if (fun.call(thisp, value, i, object)) { + result.push(value); + } + } + } + return result; + }; +} +if (!Array.prototype.every) { + Array.prototype.every = function every(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && !fun.call(thisp, self[i], i, object)) { + return false; + } + } + return true; + }; +} +if (!Array.prototype.some) { + Array.prototype.some = function some(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, object)) { + return true; + } + } + return false; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function reduce(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduce of empty array with no initial value"); + } + + var i = 0; + var result; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i++]; + break; + } + if (++i >= length) { + throw new TypeError("reduce of empty array with no initial value"); + } + } while (true); + } + + for (; i < length; i++) { + if (i in self) { + result = fun.call(void 0, result, self[i], i, object); + } + } + + return result; + }; +} +if (!Array.prototype.reduceRight) { + Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + + var result, i = length - 1; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i--]; + break; + } + if (--i < 0) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + } while (true); + } + + do { + if (i in this) { + result = fun.call(void 0, result, self[i], i, object); + } + } while (i--); + + return result; + }; +} +if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) { + Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + + var i = 0; + if (arguments.length > 1) { + i = toInteger(arguments[1]); + } + i = i >= 0 ? i : Math.max(0, length + i); + for (; i < length; i++) { + if (i in self && self[i] === sought) { + return i; + } + } + return -1; + }; +} +if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) { + Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + var i = length - 1; + if (arguments.length > 1) { + i = Math.min(i, toInteger(arguments[1])); + } + i = i >= 0 ? i : length - Math.abs(i); + for (; i >= 0; i--) { + if (i in self && sought === self[i]) { + return i; + } + } + return -1; + }; +} +if (!Object.getPrototypeOf) { + Object.getPrototypeOf = function getPrototypeOf(object) { + return object.__proto__ || ( + object.constructor ? + object.constructor.prototype : + prototypeOfObject + ); + }; +} +if (!Object.getOwnPropertyDescriptor) { + var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + + "non-object: "; + Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT + object); + if (!owns(object, property)) + return; + + var descriptor, getter, setter; + descriptor = { enumerable: true, configurable: true }; + if (supportsAccessors) { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + + var getter = lookupGetter(object, property); + var setter = lookupSetter(object, property); + object.__proto__ = prototype; + + if (getter || setter) { + if (getter) descriptor.get = getter; + if (setter) descriptor.set = setter; + return descriptor; + } + } + descriptor.value = object[property]; + return descriptor; + }; +} +if (!Object.getOwnPropertyNames) { + Object.getOwnPropertyNames = function getOwnPropertyNames(object) { + return Object.keys(object); + }; +} +if (!Object.create) { + var createEmpty; + if (Object.prototype.__proto__ === null) { + createEmpty = function () { + return { "__proto__": null }; + }; + } else { + createEmpty = function () { + var empty = {}; + for (var i in empty) + empty[i] = null; + empty.constructor = + empty.hasOwnProperty = + empty.propertyIsEnumerable = + empty.isPrototypeOf = + empty.toLocaleString = + empty.toString = + empty.valueOf = + empty.__proto__ = null; + return empty; + } + } + + Object.create = function create(prototype, properties) { + var object; + if (prototype === null) { + object = createEmpty(); + } else { + if (typeof prototype != "object") + throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); + var Type = function () {}; + Type.prototype = prototype; + object = new Type(); + object.__proto__ = prototype; + } + if (properties !== void 0) + Object.defineProperties(object, properties); + return object; + }; +} + +function doesDefinePropertyWork(object) { + try { + Object.defineProperty(object, "sentinel", {}); + return "sentinel" in object; + } catch (exception) { + } +} +if (Object.defineProperty) { + var definePropertyWorksOnObject = doesDefinePropertyWork({}); + var definePropertyWorksOnDom = typeof document == "undefined" || + doesDefinePropertyWork(document.createElement("div")); + if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { + var definePropertyFallback = Object.defineProperty; + } +} + +if (!Object.defineProperty || definePropertyFallback) { + var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; + var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " + var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + + "on this javascript engine"; + + Object.defineProperty = function defineProperty(object, property, descriptor) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT_TARGET + object); + if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) + throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); + if (definePropertyFallback) { + try { + return definePropertyFallback.call(Object, object, property, descriptor); + } catch (exception) { + } + } + if (owns(descriptor, "value")) { + + if (supportsAccessors && (lookupGetter(object, property) || + lookupSetter(object, property))) + { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + delete object[property]; + object[property] = descriptor.value; + object.__proto__ = prototype; + } else { + object[property] = descriptor.value; + } + } else { + if (!supportsAccessors) + throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); + if (owns(descriptor, "get")) + defineGetter(object, property, descriptor.get); + if (owns(descriptor, "set")) + defineSetter(object, property, descriptor.set); + } + + return object; + }; +} +if (!Object.defineProperties) { + Object.defineProperties = function defineProperties(object, properties) { + for (var property in properties) { + if (owns(properties, property)) + Object.defineProperty(object, property, properties[property]); + } + return object; + }; +} +if (!Object.seal) { + Object.seal = function seal(object) { + return object; + }; +} +if (!Object.freeze) { + Object.freeze = function freeze(object) { + return object; + }; +} +try { + Object.freeze(function () {}); +} catch (exception) { + Object.freeze = (function freeze(freezeObject) { + return function freeze(object) { + if (typeof object == "function") { + return object; + } else { + return freezeObject(object); + } + }; + })(Object.freeze); +} +if (!Object.preventExtensions) { + Object.preventExtensions = function preventExtensions(object) { + return object; + }; +} +if (!Object.isSealed) { + Object.isSealed = function isSealed(object) { + return false; + }; +} +if (!Object.isFrozen) { + Object.isFrozen = function isFrozen(object) { + return false; + }; +} +if (!Object.isExtensible) { + Object.isExtensible = function isExtensible(object) { + if (Object(object) === object) { + throw new TypeError(); // TODO message + } + var name = ''; + while (owns(object, name)) { + name += '?'; + } + object[name] = true; + var returnValue = owns(object, name); + delete object[name]; + return returnValue; + }; +} +if (!Object.keys) { + var hasDontEnumBug = true, + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + dontEnumsLength = dontEnums.length; + + for (var key in {"toString": null}) { + hasDontEnumBug = false; + } + + Object.keys = function keys(object) { + + if ( + (typeof object != "object" && typeof object != "function") || + object === null + ) { + throw new TypeError("Object.keys called on a non-object"); + } + + var keys = []; + for (var name in object) { + if (owns(object, name)) { + keys.push(name); + } + } + + if (hasDontEnumBug) { + for (var i = 0, ii = dontEnumsLength; i < ii; i++) { + var dontEnum = dontEnums[i]; + if (owns(object, dontEnum)) { + keys.push(dontEnum); + } + } + } + return keys; + }; + +} +if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; +} +var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + + "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + + "\u2029\uFEFF"; +if (!String.prototype.trim || ws.trim()) { + ws = "[" + ws + "]"; + var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), + trimEndRegexp = new RegExp(ws + ws + "*$"); + String.prototype.trim = function trim() { + return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); + }; +} + +function toInteger(n) { + n = +n; + if (n !== n) { // isNaN + n = 0; + } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + return n; +} + +function isPrimitive(input) { + var type = typeof input; + return ( + input === null || + type === "undefined" || + type === "boolean" || + type === "number" || + type === "string" + ); +} + +function toPrimitive(input) { + var val, valueOf, toString; + if (isPrimitive(input)) { + return input; + } + valueOf = input.valueOf; + if (typeof valueOf === "function") { + val = valueOf.call(input); + if (isPrimitive(val)) { + return val; + } + } + toString = input.toString; + if (typeof toString === "function") { + val = toString.call(input); + if (isPrimitive(val)) { + return val; + } + } + throw new TypeError(); +} +var toObject = function (o) { + if (o == null) { // this matches both null and undefined + throw new TypeError("can't convert "+o+" to object"); + } + return Object(o); +}; + +}); + +define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"], function(require, exports, module) { +"use strict"; + +require("./regexp"); +require("./es5-shim"); + +}); + +define("ace/lib/dom",["require","exports","module"], function(require, exports, module) { +"use strict"; + +var XHTML_NS = "http://www.w3.org/1999/xhtml"; + +exports.getDocumentHead = function(doc) { + if (!doc) + doc = document; + return doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement; +} + +exports.createElement = function(tag, ns) { + return document.createElementNS ? + document.createElementNS(ns || XHTML_NS, tag) : + document.createElement(tag); +}; + +exports.hasCssClass = function(el, name) { + var classes = (el.className || "").split(/\s+/g); + return classes.indexOf(name) !== -1; +}; +exports.addCssClass = function(el, name) { + if (!exports.hasCssClass(el, name)) { + el.className += " " + name; + } +}; +exports.removeCssClass = function(el, name) { + var classes = el.className.split(/\s+/g); + while (true) { + var index = classes.indexOf(name); + if (index == -1) { + break; + } + classes.splice(index, 1); + } + el.className = classes.join(" "); +}; + +exports.toggleCssClass = function(el, name) { + var classes = el.className.split(/\s+/g), add = true; + while (true) { + var index = classes.indexOf(name); + if (index == -1) { + break; + } + add = false; + classes.splice(index, 1); + } + if(add) + classes.push(name); + + el.className = classes.join(" "); + return add; +}; +exports.setCssClass = function(node, className, include) { + if (include) { + exports.addCssClass(node, className); + } else { + exports.removeCssClass(node, className); + } +}; + +exports.hasCssString = function(id, doc) { + var index = 0, sheets; + doc = doc || document; + + if (doc.createStyleSheet && (sheets = doc.styleSheets)) { + while (index < sheets.length) + if (sheets[index++].owningElement.id === id) return true; + } else if ((sheets = doc.getElementsByTagName("style"))) { + while (index < sheets.length) + if (sheets[index++].id === id) return true; + } + + return false; +}; + +exports.importCssString = function importCssString(cssText, id, doc) { + doc = doc || document; + if (id && exports.hasCssString(id, doc)) + return null; + + var style; + + if (doc.createStyleSheet) { + style = doc.createStyleSheet(); + style.cssText = cssText; + if (id) + style.owningElement.id = id; + } else { + style = doc.createElementNS + ? doc.createElementNS(XHTML_NS, "style") + : doc.createElement("style"); + + style.appendChild(doc.createTextNode(cssText)); + if (id) + style.id = id; + + exports.getDocumentHead(doc).appendChild(style); + } +}; + +exports.importCssStylsheet = function(uri, doc) { + if (doc.createStyleSheet) { + doc.createStyleSheet(uri); + } else { + var link = exports.createElement('link'); + link.rel = 'stylesheet'; + link.href = uri; + + exports.getDocumentHead(doc).appendChild(link); + } +}; + +exports.getInnerWidth = function(element) { + return ( + parseInt(exports.computedStyle(element, "paddingLeft"), 10) + + parseInt(exports.computedStyle(element, "paddingRight"), 10) + + element.clientWidth + ); +}; + +exports.getInnerHeight = function(element) { + return ( + parseInt(exports.computedStyle(element, "paddingTop"), 10) + + parseInt(exports.computedStyle(element, "paddingBottom"), 10) + + element.clientHeight + ); +}; + + +if (typeof document == "undefined") + return; + +if (window.pageYOffset !== undefined) { + exports.getPageScrollTop = function() { + return window.pageYOffset; + }; + + exports.getPageScrollLeft = function() { + return window.pageXOffset; + }; +} +else { + exports.getPageScrollTop = function() { + return document.body.scrollTop; + }; + + exports.getPageScrollLeft = function() { + return document.body.scrollLeft; + }; +} + +if (window.getComputedStyle) + exports.computedStyle = function(element, style) { + if (style) + return (window.getComputedStyle(element, "") || {})[style] || ""; + return window.getComputedStyle(element, "") || {}; + }; +else + exports.computedStyle = function(element, style) { + if (style) + return element.currentStyle[style]; + return element.currentStyle; + }; + +exports.scrollbarWidth = function(document) { + var inner = exports.createElement("ace_inner"); + inner.style.width = "100%"; + inner.style.minWidth = "0px"; + inner.style.height = "200px"; + inner.style.display = "block"; + + var outer = exports.createElement("ace_outer"); + var style = outer.style; + + style.position = "absolute"; + style.left = "-10000px"; + style.overflow = "hidden"; + style.width = "200px"; + style.minWidth = "0px"; + style.height = "150px"; + style.display = "block"; + + outer.appendChild(inner); + + var body = document.documentElement; + body.appendChild(outer); + + var noScrollbar = inner.offsetWidth; + + style.overflow = "scroll"; + var withScrollbar = inner.offsetWidth; + + if (noScrollbar == withScrollbar) { + withScrollbar = outer.clientWidth; + } + + body.removeChild(outer); + + return noScrollbar-withScrollbar; +}; +exports.setInnerHtml = function(el, innerHtml) { + var element = el.cloneNode(false);//document.createElement("div"); + element.innerHTML = innerHtml; + el.parentNode.replaceChild(element, el); + return element; +}; + +if ("textContent" in document.documentElement) { + exports.setInnerText = function(el, innerText) { + el.textContent = innerText; + }; + + exports.getInnerText = function(el) { + return el.textContent; + }; +} +else { + exports.setInnerText = function(el, innerText) { + el.innerText = innerText; + }; + + exports.getInnerText = function(el) { + return el.innerText; + }; +} + +exports.getParentWindow = function(document) { + return document.defaultView || document.parentWindow; +}; + +}); + +define("ace/lib/oop",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.inherits = function(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); +}; + +exports.mixin = function(obj, mixin) { + for (var key in mixin) { + obj[key] = mixin[key]; + } + return obj; +}; + +exports.implement = function(proto, mixin) { + exports.mixin(proto, mixin); +}; + +}); + +define("ace/lib/keys",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop"], function(require, exports, module) { +"use strict"; + +require("./fixoldbrowsers"); + +var oop = require("./oop"); +var Keys = (function() { + var ret = { + MODIFIER_KEYS: { + 16: 'Shift', 17: 'Ctrl', 18: 'Alt', 224: 'Meta' + }, + + KEY_MODS: { + "ctrl": 1, "alt": 2, "option" : 2, "shift": 4, + "super": 8, "meta": 8, "command": 8, "cmd": 8 + }, + + FUNCTION_KEYS : { + 8 : "Backspace", + 9 : "Tab", + 13 : "Return", + 19 : "Pause", + 27 : "Esc", + 32 : "Space", + 33 : "PageUp", + 34 : "PageDown", + 35 : "End", + 36 : "Home", + 37 : "Left", + 38 : "Up", + 39 : "Right", + 40 : "Down", + 44 : "Print", + 45 : "Insert", + 46 : "Delete", + 96 : "Numpad0", + 97 : "Numpad1", + 98 : "Numpad2", + 99 : "Numpad3", + 100: "Numpad4", + 101: "Numpad5", + 102: "Numpad6", + 103: "Numpad7", + 104: "Numpad8", + 105: "Numpad9", + '-13': "NumpadEnter", + 112: "F1", + 113: "F2", + 114: "F3", + 115: "F4", + 116: "F5", + 117: "F6", + 118: "F7", + 119: "F8", + 120: "F9", + 121: "F10", + 122: "F11", + 123: "F12", + 144: "Numlock", + 145: "Scrolllock" + }, + + PRINTABLE_KEYS: { + 32: ' ', 48: '0', 49: '1', 50: '2', 51: '3', 52: '4', 53: '5', + 54: '6', 55: '7', 56: '8', 57: '9', 59: ';', 61: '=', 65: 'a', + 66: 'b', 67: 'c', 68: 'd', 69: 'e', 70: 'f', 71: 'g', 72: 'h', + 73: 'i', 74: 'j', 75: 'k', 76: 'l', 77: 'm', 78: 'n', 79: 'o', + 80: 'p', 81: 'q', 82: 'r', 83: 's', 84: 't', 85: 'u', 86: 'v', + 87: 'w', 88: 'x', 89: 'y', 90: 'z', 107: '+', 109: '-', 110: '.', + 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`', 219: '[', + 220: '\\',221: ']', 222: '\'' + } + }; + var name, i; + for (i in ret.FUNCTION_KEYS) { + name = ret.FUNCTION_KEYS[i].toLowerCase(); + ret[name] = parseInt(i, 10); + } + for (i in ret.PRINTABLE_KEYS) { + name = ret.PRINTABLE_KEYS[i].toLowerCase(); + ret[name] = parseInt(i, 10); + } + oop.mixin(ret, ret.MODIFIER_KEYS); + oop.mixin(ret, ret.PRINTABLE_KEYS); + oop.mixin(ret, ret.FUNCTION_KEYS); + ret.enter = ret["return"]; + ret.escape = ret.esc; + ret.del = ret["delete"]; + ret[173] = '-'; + + (function() { + var mods = ["cmd", "ctrl", "alt", "shift"]; + for (var i = Math.pow(2, mods.length); i--;) { + ret.KEY_MODS[i] = mods.filter(function(x) { + return i & ret.KEY_MODS[x]; + }).join("-") + "-"; + } + })(); + + ret.KEY_MODS[0] = ""; + ret.KEY_MODS[-1] = "input-"; + + return ret; +})(); +oop.mixin(exports, Keys); + +exports.keyCodeToString = function(keyCode) { + var keyString = Keys[keyCode]; + if (typeof keyString != "string") + keyString = String.fromCharCode(keyCode); + return keyString.toLowerCase(); +}; + +}); + +define("ace/lib/useragent",["require","exports","module"], function(require, exports, module) { +"use strict"; +exports.OS = { + LINUX: "LINUX", + MAC: "MAC", + WINDOWS: "WINDOWS" +}; +exports.getOS = function() { + if (exports.isMac) { + return exports.OS.MAC; + } else if (exports.isLinux) { + return exports.OS.LINUX; + } else { + return exports.OS.WINDOWS; + } +}; +if (typeof navigator != "object") + return; + +var os = (navigator.platform.match(/mac|win|linux/i) || ["other"])[0].toLowerCase(); +var ua = navigator.userAgent; +exports.isWin = (os == "win"); +exports.isMac = (os == "mac"); +exports.isLinux = (os == "linux"); +exports.isIE = + (navigator.appName == "Microsoft Internet Explorer" || navigator.appName.indexOf("MSAppHost") >= 0) + ? parseFloat((ua.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]) + : parseFloat((ua.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]); // for ie + +exports.isOldIE = exports.isIE && exports.isIE < 9; +exports.isGecko = exports.isMozilla = (window.Controllers || window.controllers) && window.navigator.product === "Gecko"; +exports.isOldGecko = exports.isGecko && parseInt((ua.match(/rv\:(\d+)/)||[])[1], 10) < 4; +exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]"; +exports.isWebKit = parseFloat(ua.split("WebKit/")[1]) || undefined; + +exports.isChrome = parseFloat(ua.split(" Chrome/")[1]) || undefined; + +exports.isAIR = ua.indexOf("AdobeAIR") >= 0; + +exports.isIPad = ua.indexOf("iPad") >= 0; + +exports.isTouchPad = ua.indexOf("TouchPad") >= 0; + +exports.isChromeOS = ua.indexOf(" CrOS ") >= 0; + +}); + +define("ace/lib/event",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(require, exports, module) { +"use strict"; + +var keys = require("./keys"); +var useragent = require("./useragent"); + +exports.addListener = function(elem, type, callback) { + if (elem.addEventListener) { + return elem.addEventListener(type, callback, false); + } + if (elem.attachEvent) { + var wrapper = function() { + callback.call(elem, window.event); + }; + callback._wrapper = wrapper; + elem.attachEvent("on" + type, wrapper); + } +}; + +exports.removeListener = function(elem, type, callback) { + if (elem.removeEventListener) { + return elem.removeEventListener(type, callback, false); + } + if (elem.detachEvent) { + elem.detachEvent("on" + type, callback._wrapper || callback); + } +}; +exports.stopEvent = function(e) { + exports.stopPropagation(e); + exports.preventDefault(e); + return false; +}; + +exports.stopPropagation = function(e) { + if (e.stopPropagation) + e.stopPropagation(); + else + e.cancelBubble = true; +}; + +exports.preventDefault = function(e) { + if (e.preventDefault) + e.preventDefault(); + else + e.returnValue = false; +}; +exports.getButton = function(e) { + if (e.type == "dblclick") + return 0; + if (e.type == "contextmenu" || (useragent.isMac && (e.ctrlKey && !e.altKey && !e.shiftKey))) + return 2; + if (e.preventDefault) { + return e.button; + } + else { + return {1:0, 2:2, 4:1}[e.button]; + } +}; + +exports.capture = function(el, eventHandler, releaseCaptureHandler) { + function onMouseUp(e) { + eventHandler && eventHandler(e); + releaseCaptureHandler && releaseCaptureHandler(e); + + exports.removeListener(document, "mousemove", eventHandler, true); + exports.removeListener(document, "mouseup", onMouseUp, true); + exports.removeListener(document, "dragstart", onMouseUp, true); + } + + exports.addListener(document, "mousemove", eventHandler, true); + exports.addListener(document, "mouseup", onMouseUp, true); + exports.addListener(document, "dragstart", onMouseUp, true); + + return onMouseUp; +}; + +exports.addMouseWheelListener = function(el, callback) { + if ("onmousewheel" in el) { + exports.addListener(el, "mousewheel", function(e) { + var factor = 8; + if (e.wheelDeltaX !== undefined) { + e.wheelX = -e.wheelDeltaX / factor; + e.wheelY = -e.wheelDeltaY / factor; + } else { + e.wheelX = 0; + e.wheelY = -e.wheelDelta / factor; + } + callback(e); + }); + } else if ("onwheel" in el) { + exports.addListener(el, "wheel", function(e) { + var factor = 0.35; + switch (e.deltaMode) { + case e.DOM_DELTA_PIXEL: + e.wheelX = e.deltaX * factor || 0; + e.wheelY = e.deltaY * factor || 0; + break; + case e.DOM_DELTA_LINE: + case e.DOM_DELTA_PAGE: + e.wheelX = (e.deltaX || 0) * 5; + e.wheelY = (e.deltaY || 0) * 5; + break; + } + + callback(e); + }); + } else { + exports.addListener(el, "DOMMouseScroll", function(e) { + if (e.axis && e.axis == e.HORIZONTAL_AXIS) { + e.wheelX = (e.detail || 0) * 5; + e.wheelY = 0; + } else { + e.wheelX = 0; + e.wheelY = (e.detail || 0) * 5; + } + callback(e); + }); + } +}; + +exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbackName) { + var clicks = 0; + var startX, startY, timer; + var eventNames = { + 2: "dblclick", + 3: "tripleclick", + 4: "quadclick" + }; + + exports.addListener(el, "mousedown", function(e) { + if (exports.getButton(e) !== 0) { + clicks = 0; + } else if (e.detail > 1) { + clicks++; + if (clicks > 4) + clicks = 1; + } else { + clicks = 1; + } + if (useragent.isIE) { + var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5; + if (!timer || isNewClick) + clicks = 1; + if (timer) + clearTimeout(timer); + timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600); + + if (clicks == 1) { + startX = e.clientX; + startY = e.clientY; + } + } + + e._clicks = clicks; + + eventHandler[callbackName]("mousedown", e); + + if (clicks > 4) + clicks = 0; + else if (clicks > 1) + return eventHandler[callbackName](eventNames[clicks], e); + }); + + if (useragent.isOldIE) { + exports.addListener(el, "dblclick", function(e) { + clicks = 2; + if (timer) + clearTimeout(timer); + timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600); + eventHandler[callbackName]("mousedown", e); + eventHandler[callbackName](eventNames[clicks], e); + }); + } +}; + +var getModifierHash = useragent.isMac && useragent.isOpera && !("KeyboardEvent" in window) + ? function(e) { + return 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0); + } + : function(e) { + return 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0); + }; + +exports.getModifierString = function(e) { + return keys.KEY_MODS[getModifierHash(e)]; +}; + +function normalizeCommandKeys(callback, e, keyCode) { + var hashId = getModifierHash(e); + + if (!useragent.isMac && pressedKeys) { + if (pressedKeys[91] || pressedKeys[92]) + hashId |= 8; + if (pressedKeys.altGr) { + if ((3 & hashId) != 3) + pressedKeys.altGr = 0; + else + return; + } + if (keyCode === 18 || keyCode === 17) { + var location = "location" in e ? e.location : e.keyLocation; + if (keyCode === 17 && location === 1) { + if (pressedKeys[keyCode] == 1) + ts = e.timeStamp; + } else if (keyCode === 18 && hashId === 3 && location === 2) { + var dt = e.timestamp - ts; + if (dt < 50) + pressedKeys.altGr = true; + } + } + } + + if (keyCode in keys.MODIFIER_KEYS) { + keyCode = -1; + } + + if (hashId & 8 && (keyCode === 91 || keyCode === 93)) { + keyCode = -1; + } + + if (!hashId && keyCode === 13) { + var location = "location" in e ? e.location : e.keyLocation; + if (location === 3) { + callback(e, hashId, -keyCode); + if (e.defaultPrevented) + return; + } + } + + if (useragent.isChromeOS && hashId & 8) { + callback(e, hashId, keyCode); + if (e.defaultPrevented) + return; + else + hashId &= ~8; + } + if (!hashId && !(keyCode in keys.FUNCTION_KEYS) && !(keyCode in keys.PRINTABLE_KEYS)) { + return false; + } + + return callback(e, hashId, keyCode); +} + +var pressedKeys = null; +var ts = 0; +exports.addCommandKeyListener = function(el, callback) { + var addListener = exports.addListener; + if (useragent.isOldGecko || (useragent.isOpera && !("KeyboardEvent" in window))) { + var lastKeyDownKeyCode = null; + addListener(el, "keydown", function(e) { + lastKeyDownKeyCode = e.keyCode; + }); + addListener(el, "keypress", function(e) { + return normalizeCommandKeys(callback, e, lastKeyDownKeyCode); + }); + } else { + var lastDefaultPrevented = null; + + addListener(el, "keydown", function(e) { + pressedKeys[e.keyCode] = (pressedKeys[e.keyCode] || 0) + 1; + var result = normalizeCommandKeys(callback, e, e.keyCode); + lastDefaultPrevented = e.defaultPrevented; + return result; + }); + + addListener(el, "keypress", function(e) { + if (lastDefaultPrevented && (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey)) { + exports.stopEvent(e); + lastDefaultPrevented = null; + } + }); + + addListener(el, "keyup", function(e) { + pressedKeys[e.keyCode] = null; + }); + + if (!pressedKeys) { + pressedKeys = Object.create(null); + addListener(window, "focus", function(e) { + pressedKeys = Object.create(null); + }); + } + } +}; + +if (window.postMessage && !useragent.isOldIE) { + var postMessageId = 1; + exports.nextTick = function(callback, win) { + win = win || window; + var messageName = "zero-timeout-message-" + postMessageId; + exports.addListener(win, "message", function listener(e) { + if (e.data == messageName) { + exports.stopPropagation(e); + exports.removeListener(win, "message", listener); + callback(); + } + }); + win.postMessage(messageName, "*"); + }; +} + + +exports.nextFrame = window.requestAnimationFrame || + window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || + window.msRequestAnimationFrame || + window.oRequestAnimationFrame; + +if (exports.nextFrame) + exports.nextFrame = exports.nextFrame.bind(window); +else + exports.nextFrame = function(callback) { + setTimeout(callback, 17); + }; +}); + +define("ace/lib/lang",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.last = function(a) { + return a[a.length - 1]; +}; + +exports.stringReverse = function(string) { + return string.split("").reverse().join(""); +}; + +exports.stringRepeat = function (string, count) { + var result = ''; + while (count > 0) { + if (count & 1) + result += string; + + if (count >>= 1) + string += string; + } + return result; +}; + +var trimBeginRegexp = /^\s\s*/; +var trimEndRegexp = /\s\s*$/; + +exports.stringTrimLeft = function (string) { + return string.replace(trimBeginRegexp, ''); +}; + +exports.stringTrimRight = function (string) { + return string.replace(trimEndRegexp, ''); +}; + +exports.copyObject = function(obj) { + var copy = {}; + for (var key in obj) { + copy[key] = obj[key]; + } + return copy; +}; + +exports.copyArray = function(array){ + var copy = []; + for (var i=0, l=array.length; i 1); + return ev.preventDefault(); + }; + + this.startSelect = function(pos, waitForClickSelection) { + pos = pos || this.editor.renderer.screenToTextCoordinates(this.x, this.y); + var editor = this.editor; + editor.$blockScrolling++; + if (this.mousedownEvent.getShiftKey()) + editor.selection.selectToPosition(pos); + else if (!waitForClickSelection) + editor.selection.moveToPosition(pos); + if (!waitForClickSelection) + this.select(); + if (editor.renderer.scroller.setCapture) { + editor.renderer.scroller.setCapture(); + } + editor.setStyle("ace_selecting"); + this.setState("select"); + editor.$blockScrolling--; + }; + + this.select = function() { + var anchor, editor = this.editor; + var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); + editor.$blockScrolling++; + if (this.$clickSelection) { + var cmp = this.$clickSelection.comparePoint(cursor); + + if (cmp == -1) { + anchor = this.$clickSelection.end; + } else if (cmp == 1) { + anchor = this.$clickSelection.start; + } else { + var orientedRange = calcRangeOrientation(this.$clickSelection, cursor); + cursor = orientedRange.cursor; + anchor = orientedRange.anchor; + } + editor.selection.setSelectionAnchor(anchor.row, anchor.column); + } + editor.selection.selectToPosition(cursor); + editor.$blockScrolling--; + editor.renderer.scrollCursorIntoView(); + }; + + this.extendSelectionBy = function(unitName) { + var anchor, editor = this.editor; + var cursor = editor.renderer.screenToTextCoordinates(this.x, this.y); + var range = editor.selection[unitName](cursor.row, cursor.column); + editor.$blockScrolling++; + if (this.$clickSelection) { + var cmpStart = this.$clickSelection.comparePoint(range.start); + var cmpEnd = this.$clickSelection.comparePoint(range.end); + + if (cmpStart == -1 && cmpEnd <= 0) { + anchor = this.$clickSelection.end; + if (range.end.row != cursor.row || range.end.column != cursor.column) + cursor = range.start; + } else if (cmpEnd == 1 && cmpStart >= 0) { + anchor = this.$clickSelection.start; + if (range.start.row != cursor.row || range.start.column != cursor.column) + cursor = range.end; + } else if (cmpStart == -1 && cmpEnd == 1) { + cursor = range.end; + anchor = range.start; + } else { + var orientedRange = calcRangeOrientation(this.$clickSelection, cursor); + cursor = orientedRange.cursor; + anchor = orientedRange.anchor; + } + editor.selection.setSelectionAnchor(anchor.row, anchor.column); + } + editor.selection.selectToPosition(cursor); + editor.$blockScrolling--; + editor.renderer.scrollCursorIntoView(); + }; + + this.selectEnd = + this.selectAllEnd = + this.selectByWordsEnd = + this.selectByLinesEnd = function() { + this.$clickSelection = null; + this.editor.unsetStyle("ace_selecting"); + if (this.editor.renderer.scroller.releaseCapture) { + this.editor.renderer.scroller.releaseCapture(); + } + }; + + this.focusWait = function() { + var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + var time = Date.now(); + + if (distance > DRAG_OFFSET || time - this.mousedownEvent.time > this.$focusTimout) + this.startSelect(this.mousedownEvent.getDocumentPosition()); + }; + + this.onDoubleClick = function(ev) { + var pos = ev.getDocumentPosition(); + var editor = this.editor; + var session = editor.session; + + var range = session.getBracketRange(pos); + if (range) { + if (range.isEmpty()) { + range.start.column--; + range.end.column++; + } + this.setState("select"); + } else { + range = editor.selection.getWordRange(pos.row, pos.column); + this.setState("selectByWords"); + } + this.$clickSelection = range; + this.select(); + }; + + this.onTripleClick = function(ev) { + var pos = ev.getDocumentPosition(); + var editor = this.editor; + + this.setState("selectByLines"); + var range = editor.getSelectionRange(); + if (range.isMultiLine() && range.contains(pos.row, pos.column)) { + this.$clickSelection = editor.selection.getLineRange(range.start.row); + this.$clickSelection.end = editor.selection.getLineRange(range.end.row).end; + } else { + this.$clickSelection = editor.selection.getLineRange(pos.row); + } + this.select(); + }; + + this.onQuadClick = function(ev) { + var editor = this.editor; + + editor.selectAll(); + this.$clickSelection = editor.getSelectionRange(); + this.setState("selectAll"); + }; + + this.onMouseWheel = function(ev) { + if (ev.getAccelKey()) + return; + if (ev.getShiftKey() && ev.wheelY && !ev.wheelX) { + ev.wheelX = ev.wheelY; + ev.wheelY = 0; + } + + var t = ev.domEvent.timeStamp; + var dt = t - (this.$lastScrollTime||0); + + var editor = this.editor; + var isScrolable = editor.renderer.isScrollableBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); + if (isScrolable || dt < 200) { + this.$lastScrollTime = t; + editor.renderer.scrollBy(ev.wheelX * ev.speed, ev.wheelY * ev.speed); + return ev.stop(); + } + }; + +}).call(DefaultHandlers.prototype); + +exports.DefaultHandlers = DefaultHandlers; + +function calcDistance(ax, ay, bx, by) { + return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); +} + +function calcRangeOrientation(range, cursor) { + if (range.start.row == range.end.row) + var cmp = 2 * cursor.column - range.start.column - range.end.column; + else if (range.start.row == range.end.row - 1 && !range.start.column && !range.end.column) + var cmp = cursor.column - 4; + else + var cmp = 2 * cursor.row - range.start.row - range.end.row; + + if (cmp < 0) + return {cursor: range.start, anchor: range.end}; + else + return {cursor: range.end, anchor: range.start}; +} + +}); + +define("ace/tooltip",["require","exports","module","ace/lib/oop","ace/lib/dom"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var dom = require("./lib/dom"); +function Tooltip (parentNode) { + this.isOpen = false; + this.$element = null; + this.$parentNode = parentNode; +} + +(function() { + this.$init = function() { + this.$element = dom.createElement("div"); + this.$element.className = "ace_tooltip"; + this.$element.style.display = "none"; + this.$parentNode.appendChild(this.$element); + return this.$element; + }; + this.getElement = function() { + return this.$element || this.$init(); + }; + this.setText = function(text) { + dom.setInnerText(this.getElement(), text); + }; + this.setHtml = function(html) { + this.getElement().innerHTML = html; + }; + this.setPosition = function(x, y) { + this.getElement().style.left = x + "px"; + this.getElement().style.top = y + "px"; + }; + this.setClassName = function(className) { + dom.addCssClass(this.getElement(), className); + }; + this.show = function(text, x, y) { + if (text != null) + this.setText(text); + if (x != null && y != null) + this.setPosition(x, y); + if (!this.isOpen) { + this.getElement().style.display = "block"; + this.isOpen = true; + } + }; + + this.hide = function() { + if (this.isOpen) { + this.getElement().style.display = "none"; + this.isOpen = false; + } + }; + this.getHeight = function() { + return this.getElement().offsetHeight; + }; + this.getWidth = function() { + return this.getElement().offsetWidth; + }; + +}).call(Tooltip.prototype); + +exports.Tooltip = Tooltip; +}); + +define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/event","ace/tooltip"], function(require, exports, module) { +"use strict"; +var dom = require("../lib/dom"); +var oop = require("../lib/oop"); +var event = require("../lib/event"); +var Tooltip = require("../tooltip").Tooltip; + +function GutterHandler(mouseHandler) { + var editor = mouseHandler.editor; + var gutter = editor.renderer.$gutterLayer; + var tooltip = new GutterTooltip(editor.container); + + mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) { + if (!editor.isFocused() || e.getButton() != 0) + return; + var gutterRegion = gutter.getRegion(e); + + if (gutterRegion == "foldWidgets") + return; + + var row = e.getDocumentPosition().row; + var selection = editor.session.selection; + + if (e.getShiftKey()) + selection.selectTo(row, 0); + else { + if (e.domEvent.detail == 2) { + editor.selectAll(); + return e.preventDefault(); + } + mouseHandler.$clickSelection = editor.selection.getLineRange(row); + } + mouseHandler.setState("selectByLines"); + mouseHandler.captureMouse(e); + return e.preventDefault(); + }); + + + var tooltipTimeout, mouseEvent, tooltipAnnotation; + + function showTooltip() { + var row = mouseEvent.getDocumentPosition().row; + var annotation = gutter.$annotations[row]; + if (!annotation) + return hideTooltip(); + + var maxRow = editor.session.getLength(); + if (row == maxRow) { + var screenRow = editor.renderer.pixelToScreenCoordinates(0, mouseEvent.y).row; + var pos = mouseEvent.$pos; + if (screenRow > editor.session.documentToScreenRow(pos.row, pos.column)) + return hideTooltip(); + } + + if (tooltipAnnotation == annotation) + return; + tooltipAnnotation = annotation.text.join("
"); + + tooltip.setHtml(tooltipAnnotation); + tooltip.show(); + editor.on("mousewheel", hideTooltip); + + if (mouseHandler.$tooltipFollowsMouse) { + moveTooltip(mouseEvent); + } else { + var gutterElement = gutter.$cells[editor.session.documentToScreenRow(row, 0)].element; + var rect = gutterElement.getBoundingClientRect(); + var style = tooltip.getElement().style; + style.left = rect.right + "px"; + style.top = rect.bottom + "px"; + } + } + + function hideTooltip() { + if (tooltipTimeout) + tooltipTimeout = clearTimeout(tooltipTimeout); + if (tooltipAnnotation) { + tooltip.hide(); + tooltipAnnotation = null; + editor.removeEventListener("mousewheel", hideTooltip); + } + } + + function moveTooltip(e) { + tooltip.setPosition(e.x, e.y); + } + + mouseHandler.editor.setDefaultHandler("guttermousemove", function(e) { + var target = e.domEvent.target || e.domEvent.srcElement; + if (dom.hasCssClass(target, "ace_fold-widget")) + return hideTooltip(); + + if (tooltipAnnotation && mouseHandler.$tooltipFollowsMouse) + moveTooltip(e); + + mouseEvent = e; + if (tooltipTimeout) + return; + tooltipTimeout = setTimeout(function() { + tooltipTimeout = null; + if (mouseEvent && !mouseHandler.isMousePressed) + showTooltip(); + else + hideTooltip(); + }, 50); + }); + + event.addListener(editor.renderer.$gutter, "mouseout", function(e) { + mouseEvent = null; + if (!tooltipAnnotation || tooltipTimeout) + return; + + tooltipTimeout = setTimeout(function() { + tooltipTimeout = null; + hideTooltip(); + }, 50); + }); + + editor.on("changeSession", hideTooltip); +} + +function GutterTooltip(parentNode) { + Tooltip.call(this, parentNode); +} + +oop.inherits(GutterTooltip, Tooltip); + +(function(){ + this.setPosition = function(x, y) { + var windowWidth = window.innerWidth || document.documentElement.clientWidth; + var windowHeight = window.innerHeight || document.documentElement.clientHeight; + var width = this.getWidth(); + var height = this.getHeight(); + x += 15; + y += 15; + if (x + width > windowWidth) { + x -= (x + width) - windowWidth; + } + if (y + height > windowHeight) { + y -= 20 + height; + } + Tooltip.prototype.setPosition.call(this, x, y); + }; + +}).call(GutterTooltip.prototype); + + + +exports.GutterHandler = GutterHandler; + +}); + +define("ace/mouse/mouse_event",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(require, exports, module) { +"use strict"; + +var event = require("../lib/event"); +var useragent = require("../lib/useragent"); +var MouseEvent = exports.MouseEvent = function(domEvent, editor) { + this.domEvent = domEvent; + this.editor = editor; + + this.x = this.clientX = domEvent.clientX; + this.y = this.clientY = domEvent.clientY; + + this.$pos = null; + this.$inSelection = null; + + this.propagationStopped = false; + this.defaultPrevented = false; +}; + +(function() { + + this.stopPropagation = function() { + event.stopPropagation(this.domEvent); + this.propagationStopped = true; + }; + + this.preventDefault = function() { + event.preventDefault(this.domEvent); + this.defaultPrevented = true; + }; + + this.stop = function() { + this.stopPropagation(); + this.preventDefault(); + }; + this.getDocumentPosition = function() { + if (this.$pos) + return this.$pos; + + this.$pos = this.editor.renderer.screenToTextCoordinates(this.clientX, this.clientY); + return this.$pos; + }; + this.inSelection = function() { + if (this.$inSelection !== null) + return this.$inSelection; + + var editor = this.editor; + + + var selectionRange = editor.getSelectionRange(); + if (selectionRange.isEmpty()) + this.$inSelection = false; + else { + var pos = this.getDocumentPosition(); + this.$inSelection = selectionRange.contains(pos.row, pos.column); + } + + return this.$inSelection; + }; + this.getButton = function() { + return event.getButton(this.domEvent); + }; + this.getShiftKey = function() { + return this.domEvent.shiftKey; + }; + + this.getAccelKey = useragent.isMac + ? function() { return this.domEvent.metaKey; } + : function() { return this.domEvent.ctrlKey; }; + +}).call(MouseEvent.prototype); + +}); + +define("ace/mouse/dragdrop_handler",["require","exports","module","ace/lib/dom","ace/lib/event","ace/lib/useragent"], function(require, exports, module) { +"use strict"; + +var dom = require("../lib/dom"); +var event = require("../lib/event"); +var useragent = require("../lib/useragent"); + +var AUTOSCROLL_DELAY = 200; +var SCROLL_CURSOR_DELAY = 200; +var SCROLL_CURSOR_HYSTERESIS = 5; + +function DragdropHandler(mouseHandler) { + + var editor = mouseHandler.editor; + + var blankImage = dom.createElement("img"); + blankImage.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + if (useragent.isOpera) + blankImage.style.cssText = "width:1px;height:1px;position:fixed;top:0;left:0;z-index:2147483647;opacity:0;"; + + var exports = ["dragWait", "dragWaitEnd", "startDrag", "dragReadyEnd", "onMouseDrag"]; + + exports.forEach(function(x) { + mouseHandler[x] = this[x]; + }, this); + editor.addEventListener("mousedown", this.onMouseDown.bind(mouseHandler)); + + + var mouseTarget = editor.container; + var dragSelectionMarker, x, y; + var timerId, range; + var dragCursor, counter = 0; + var dragOperation; + var isInternal; + var autoScrollStartTime; + var cursorMovedTime; + var cursorPointOnCaretMoved; + + this.onDragStart = function(e) { + if (this.cancelDrag || !mouseTarget.draggable) { + var self = this; + setTimeout(function(){ + self.startSelect(); + self.captureMouse(e); + }, 0); + return e.preventDefault(); + } + range = editor.getSelectionRange(); + + var dataTransfer = e.dataTransfer; + dataTransfer.effectAllowed = editor.getReadOnly() ? "copy" : "copyMove"; + if (useragent.isOpera) { + editor.container.appendChild(blankImage); + blankImage.scrollTop = 0; + } + dataTransfer.setDragImage && dataTransfer.setDragImage(blankImage, 0, 0); + if (useragent.isOpera) { + editor.container.removeChild(blankImage); + } + dataTransfer.clearData(); + dataTransfer.setData("Text", editor.session.getTextRange()); + + isInternal = true; + this.setState("drag"); + }; + + this.onDragEnd = function(e) { + mouseTarget.draggable = false; + isInternal = false; + this.setState(null); + if (!editor.getReadOnly()) { + var dropEffect = e.dataTransfer.dropEffect; + if (!dragOperation && dropEffect == "move") + editor.session.remove(editor.getSelectionRange()); + editor.renderer.$cursorLayer.setBlinking(true); + } + this.editor.unsetStyle("ace_dragging"); + this.editor.renderer.setCursorStyle(""); + }; + + this.onDragEnter = function(e) { + if (editor.getReadOnly() || !canAccept(e.dataTransfer)) + return; + x = e.clientX; + y = e.clientY; + if (!dragSelectionMarker) + addDragMarker(); + counter++; + e.dataTransfer.dropEffect = dragOperation = getDropEffect(e); + return event.preventDefault(e); + }; + + this.onDragOver = function(e) { + if (editor.getReadOnly() || !canAccept(e.dataTransfer)) + return; + x = e.clientX; + y = e.clientY; + if (!dragSelectionMarker) { + addDragMarker(); + counter++; + } + if (onMouseMoveTimer !== null) + onMouseMoveTimer = null; + + e.dataTransfer.dropEffect = dragOperation = getDropEffect(e); + return event.preventDefault(e); + }; + + this.onDragLeave = function(e) { + counter--; + if (counter <= 0 && dragSelectionMarker) { + clearDragMarker(); + dragOperation = null; + return event.preventDefault(e); + } + }; + + this.onDrop = function(e) { + if (!dragCursor) + return; + var dataTransfer = e.dataTransfer; + if (isInternal) { + switch (dragOperation) { + case "move": + if (range.contains(dragCursor.row, dragCursor.column)) { + range = { + start: dragCursor, + end: dragCursor + }; + } else { + range = editor.moveText(range, dragCursor); + } + break; + case "copy": + range = editor.moveText(range, dragCursor, true); + break; + } + } else { + var dropData = dataTransfer.getData('Text'); + range = { + start: dragCursor, + end: editor.session.insert(dragCursor, dropData) + }; + editor.focus(); + dragOperation = null; + } + clearDragMarker(); + return event.preventDefault(e); + }; + + event.addListener(mouseTarget, "dragstart", this.onDragStart.bind(mouseHandler)); + event.addListener(mouseTarget, "dragend", this.onDragEnd.bind(mouseHandler)); + event.addListener(mouseTarget, "dragenter", this.onDragEnter.bind(mouseHandler)); + event.addListener(mouseTarget, "dragover", this.onDragOver.bind(mouseHandler)); + event.addListener(mouseTarget, "dragleave", this.onDragLeave.bind(mouseHandler)); + event.addListener(mouseTarget, "drop", this.onDrop.bind(mouseHandler)); + + function scrollCursorIntoView(cursor, prevCursor) { + var now = Date.now(); + var vMovement = !prevCursor || cursor.row != prevCursor.row; + var hMovement = !prevCursor || cursor.column != prevCursor.column; + if (!cursorMovedTime || vMovement || hMovement) { + editor.$blockScrolling += 1; + editor.moveCursorToPosition(cursor); + editor.$blockScrolling -= 1; + cursorMovedTime = now; + cursorPointOnCaretMoved = {x: x, y: y}; + } else { + var distance = calcDistance(cursorPointOnCaretMoved.x, cursorPointOnCaretMoved.y, x, y); + if (distance > SCROLL_CURSOR_HYSTERESIS) { + cursorMovedTime = null; + } else if (now - cursorMovedTime >= SCROLL_CURSOR_DELAY) { + editor.renderer.scrollCursorIntoView(); + cursorMovedTime = null; + } + } + } + + function autoScroll(cursor, prevCursor) { + var now = Date.now(); + var lineHeight = editor.renderer.layerConfig.lineHeight; + var characterWidth = editor.renderer.layerConfig.characterWidth; + var editorRect = editor.renderer.scroller.getBoundingClientRect(); + var offsets = { + x: { + left: x - editorRect.left, + right: editorRect.right - x + }, + y: { + top: y - editorRect.top, + bottom: editorRect.bottom - y + } + }; + var nearestXOffset = Math.min(offsets.x.left, offsets.x.right); + var nearestYOffset = Math.min(offsets.y.top, offsets.y.bottom); + var scrollCursor = {row: cursor.row, column: cursor.column}; + if (nearestXOffset / characterWidth <= 2) { + scrollCursor.column += (offsets.x.left < offsets.x.right ? -3 : +2); + } + if (nearestYOffset / lineHeight <= 1) { + scrollCursor.row += (offsets.y.top < offsets.y.bottom ? -1 : +1); + } + var vScroll = cursor.row != scrollCursor.row; + var hScroll = cursor.column != scrollCursor.column; + var vMovement = !prevCursor || cursor.row != prevCursor.row; + if (vScroll || (hScroll && !vMovement)) { + if (!autoScrollStartTime) + autoScrollStartTime = now; + else if (now - autoScrollStartTime >= AUTOSCROLL_DELAY) + editor.renderer.scrollCursorIntoView(scrollCursor); + } else { + autoScrollStartTime = null; + } + } + + function onDragInterval() { + var prevCursor = dragCursor; + dragCursor = editor.renderer.screenToTextCoordinates(x, y); + scrollCursorIntoView(dragCursor, prevCursor); + autoScroll(dragCursor, prevCursor); + } + + function addDragMarker() { + range = editor.selection.toOrientedRange(); + dragSelectionMarker = editor.session.addMarker(range, "ace_selection", editor.getSelectionStyle()); + editor.clearSelection(); + if (editor.isFocused()) + editor.renderer.$cursorLayer.setBlinking(false); + clearInterval(timerId); + onDragInterval(); + timerId = setInterval(onDragInterval, 20); + counter = 0; + event.addListener(document, "mousemove", onMouseMove); + } + + function clearDragMarker() { + clearInterval(timerId); + editor.session.removeMarker(dragSelectionMarker); + dragSelectionMarker = null; + editor.$blockScrolling += 1; + editor.selection.fromOrientedRange(range); + editor.$blockScrolling -= 1; + if (editor.isFocused() && !isInternal) + editor.renderer.$cursorLayer.setBlinking(!editor.getReadOnly()); + range = null; + dragCursor = null; + counter = 0; + autoScrollStartTime = null; + cursorMovedTime = null; + event.removeListener(document, "mousemove", onMouseMove); + } + var onMouseMoveTimer = null; + function onMouseMove() { + if (onMouseMoveTimer == null) { + onMouseMoveTimer = setTimeout(function() { + if (onMouseMoveTimer != null && dragSelectionMarker) + clearDragMarker(); + }, 20); + } + } + + function canAccept(dataTransfer) { + var types = dataTransfer.types; + return !types || Array.prototype.some.call(types, function(type) { + return type == 'text/plain' || type == 'Text'; + }); + } + + function getDropEffect(e) { + var copyAllowed = ['copy', 'copymove', 'all', 'uninitialized']; + var moveAllowed = ['move', 'copymove', 'linkmove', 'all', 'uninitialized']; + + var copyModifierState = useragent.isMac ? e.altKey : e.ctrlKey; + var effectAllowed = "uninitialized"; + try { + effectAllowed = e.dataTransfer.effectAllowed.toLowerCase(); + } catch (e) {} + var dropEffect = "none"; + + if (copyModifierState && copyAllowed.indexOf(effectAllowed) >= 0) + dropEffect = "copy"; + else if (moveAllowed.indexOf(effectAllowed) >= 0) + dropEffect = "move"; + else if (copyAllowed.indexOf(effectAllowed) >= 0) + dropEffect = "copy"; + + return dropEffect; + } +} + +(function() { + + this.dragWait = function() { + var interval = Date.now() - this.mousedownEvent.time; + if (interval > this.editor.getDragDelay()) + this.startDrag(); + }; + + this.dragWaitEnd = function() { + var target = this.editor.container; + target.draggable = false; + this.startSelect(this.mousedownEvent.getDocumentPosition()); + this.selectEnd(); + }; + + this.dragReadyEnd = function(e) { + this.editor.renderer.$cursorLayer.setBlinking(!this.editor.getReadOnly()); + this.editor.unsetStyle("ace_dragging"); + this.editor.renderer.setCursorStyle(""); + this.dragWaitEnd(); + }; + + this.startDrag = function(){ + this.cancelDrag = false; + var editor = this.editor; + var target = editor.container; + target.draggable = true; + editor.renderer.$cursorLayer.setBlinking(false); + editor.setStyle("ace_dragging"); + var cursorStyle = useragent.isWin ? "default" : "move"; + editor.renderer.setCursorStyle(cursorStyle); + this.setState("dragReady"); + }; + + this.onMouseDrag = function(e) { + var target = this.editor.container; + if (useragent.isIE && this.state == "dragReady") { + var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + if (distance > 3) + target.dragDrop(); + } + if (this.state === "dragWait") { + var distance = calcDistance(this.mousedownEvent.x, this.mousedownEvent.y, this.x, this.y); + if (distance > 0) { + target.draggable = false; + this.startSelect(this.mousedownEvent.getDocumentPosition()); + } + } + }; + + this.onMouseDown = function(e) { + if (!this.$dragEnabled) + return; + this.mousedownEvent = e; + var editor = this.editor; + + var inSelection = e.inSelection(); + var button = e.getButton(); + var clickCount = e.domEvent.detail || 1; + if (clickCount === 1 && button === 0 && inSelection) { + if (e.editor.inMultiSelectMode && (e.getAccelKey() || e.getShiftKey())) + return; + this.mousedownEvent.time = Date.now(); + var eventTarget = e.domEvent.target || e.domEvent.srcElement; + if ("unselectable" in eventTarget) + eventTarget.unselectable = "on"; + if (editor.getDragDelay()) { + if (useragent.isWebKit) { + this.cancelDrag = true; + var mouseTarget = editor.container; + mouseTarget.draggable = true; + } + this.setState("dragWait"); + } else { + this.startDrag(); + } + this.captureMouse(e, this.onMouseDrag.bind(this)); + e.defaultPrevented = true; + } + }; + +}).call(DragdropHandler.prototype); + + +function calcDistance(ax, ay, bx, by) { + return Math.sqrt(Math.pow(bx - ax, 2) + Math.pow(by - ay, 2)); +} + +exports.DragdropHandler = DragdropHandler; + +}); + +define("ace/lib/net",["require","exports","module","ace/lib/dom"], function(require, exports, module) { +"use strict"; +var dom = require("./dom"); + +exports.get = function (url, callback) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + callback(xhr.responseText); + } + }; + xhr.send(null); +}; + +exports.loadScript = function(path, callback) { + var head = dom.getDocumentHead(); + var s = document.createElement('script'); + + s.src = path; + head.appendChild(s); + + s.onload = s.onreadystatechange = function(_, isAbort) { + if (isAbort || !s.readyState || s.readyState == "loaded" || s.readyState == "complete") { + s = s.onload = s.onreadystatechange = null; + if (!isAbort) + callback(); + } + }; +}; +exports.qualifyURL = function(url) { + var a = document.createElement('a'); + a.href = url; + return a.href; +} + +}); + +define("ace/lib/event_emitter",["require","exports","module"], function(require, exports, module) { +"use strict"; + +var EventEmitter = {}; +var stopPropagation = function() { this.propagationStopped = true; }; +var preventDefault = function() { this.defaultPrevented = true; }; + +EventEmitter._emit = +EventEmitter._dispatchEvent = function(eventName, e) { + this._eventRegistry || (this._eventRegistry = {}); + this._defaultHandlers || (this._defaultHandlers = {}); + + var listeners = this._eventRegistry[eventName] || []; + var defaultHandler = this._defaultHandlers[eventName]; + if (!listeners.length && !defaultHandler) + return; + + if (typeof e != "object" || !e) + e = {}; + + if (!e.type) + e.type = eventName; + if (!e.stopPropagation) + e.stopPropagation = stopPropagation; + if (!e.preventDefault) + e.preventDefault = preventDefault; + + listeners = listeners.slice(); + for (var i=0; i 1) + base = parts[parts.length - 2]; + var path = options[component + "Path"]; + if (path == null) { + path = options.basePath; + } else if (sep == "/") { + component = sep = ""; + } + if (path && path.slice(-1) != "/") + path += "/"; + return path + component + sep + base + this.get("suffix"); +}; + +exports.setModuleUrl = function(name, subst) { + return options.$moduleUrls[name] = subst; +}; + +exports.$loading = {}; +exports.loadModule = function(moduleName, onLoad) { + var module, moduleType; + if (Array.isArray(moduleName)) { + moduleType = moduleName[0]; + moduleName = moduleName[1]; + } + + try { + module = require(moduleName); + } catch (e) {} + if (module && !exports.$loading[moduleName]) + return onLoad && onLoad(module); + + if (!exports.$loading[moduleName]) + exports.$loading[moduleName] = []; + + exports.$loading[moduleName].push(onLoad); + + if (exports.$loading[moduleName].length > 1) + return; + + var afterLoad = function() { + require([moduleName], function(module) { + exports._emit("load.module", {name: moduleName, module: module}); + var listeners = exports.$loading[moduleName]; + exports.$loading[moduleName] = null; + listeners.forEach(function(onLoad) { + onLoad && onLoad(module); + }); + }); + }; + + if (!exports.get("packaged")) + return afterLoad(); + net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad); +}; +init(true);function init(packaged) { + + options.packaged = packaged || require.packaged || module.packaged || (global.define && define.packaged); + + if (!global.document) + return ""; + + var scriptOptions = {}; + var scriptUrl = ""; + var currentScript = (document.currentScript || document._currentScript ); // native or polyfill + var currentDocument = currentScript && currentScript.ownerDocument || document; + + var scripts = currentDocument.getElementsByTagName("script"); + for (var i=0; i [" + this.end.row + "/" + this.end.column + "]"); + }; + + this.contains = function(row, column) { + return this.compare(row, column) == 0; + }; + this.compareRange = function(range) { + var cmp, + end = range.end, + start = range.start; + + cmp = this.compare(end.row, end.column); + if (cmp == 1) { + cmp = this.compare(start.row, start.column); + if (cmp == 1) { + return 2; + } else if (cmp == 0) { + return 1; + } else { + return 0; + } + } else if (cmp == -1) { + return -2; + } else { + cmp = this.compare(start.row, start.column); + if (cmp == -1) { + return -1; + } else if (cmp == 1) { + return 42; + } else { + return 0; + } + } + }; + this.comparePoint = function(p) { + return this.compare(p.row, p.column); + }; + this.containsRange = function(range) { + return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; + }; + this.intersects = function(range) { + var cmp = this.compareRange(range); + return (cmp == -1 || cmp == 0 || cmp == 1); + }; + this.isEnd = function(row, column) { + return this.end.row == row && this.end.column == column; + }; + this.isStart = function(row, column) { + return this.start.row == row && this.start.column == column; + }; + this.setStart = function(row, column) { + if (typeof row == "object") { + this.start.column = row.column; + this.start.row = row.row; + } else { + this.start.row = row; + this.start.column = column; + } + }; + this.setEnd = function(row, column) { + if (typeof row == "object") { + this.end.column = row.column; + this.end.row = row.row; + } else { + this.end.row = row; + this.end.column = column; + } + }; + this.inside = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column) || this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideStart = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideEnd = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.compare = function(row, column) { + if (!this.isMultiLine()) { + if (row === this.start.row) { + return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); + }; + } + + if (row < this.start.row) + return -1; + + if (row > this.end.row) + return 1; + + if (this.start.row === row) + return column >= this.start.column ? 0 : -1; + + if (this.end.row === row) + return column <= this.end.column ? 0 : 1; + + return 0; + }; + this.compareStart = function(row, column) { + if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.compareEnd = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else { + return this.compare(row, column); + } + }; + this.compareInside = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.clipRows = function(firstRow, lastRow) { + if (this.end.row > lastRow) + var end = {row: lastRow + 1, column: 0}; + else if (this.end.row < firstRow) + var end = {row: firstRow, column: 0}; + + if (this.start.row > lastRow) + var start = {row: lastRow + 1, column: 0}; + else if (this.start.row < firstRow) + var start = {row: firstRow, column: 0}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + this.extend = function(row, column) { + var cmp = this.compare(row, column); + + if (cmp == 0) + return this; + else if (cmp == -1) + var start = {row: row, column: column}; + else + var end = {row: row, column: column}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + + this.isEmpty = function() { + return (this.start.row === this.end.row && this.start.column === this.end.column); + }; + this.isMultiLine = function() { + return (this.start.row !== this.end.row); + }; + this.clone = function() { + return Range.fromPoints(this.start, this.end); + }; + this.collapseRows = function() { + if (this.end.column == 0) + return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) + else + return new Range(this.start.row, 0, this.end.row, 0) + }; + this.toScreenRange = function(session) { + var screenPosStart = session.documentToScreenPosition(this.start); + var screenPosEnd = session.documentToScreenPosition(this.end); + + return new Range( + screenPosStart.row, screenPosStart.column, + screenPosEnd.row, screenPosEnd.column + ); + }; + this.moveBy = function(row, column) { + this.start.row += row; + this.start.column += column; + this.end.row += row; + this.end.column += column; + }; + +}).call(Range.prototype); +Range.fromPoints = function(start, end) { + return new Range(start.row, start.column, end.row, end.column); +}; +Range.comparePoints = comparePoints; + +Range.comparePoints = function(p1, p2) { + return p1.row - p2.row || p1.column - p2.column; +}; + + +exports.Range = Range; +}); + +define("ace/selection",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/range"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var lang = require("./lib/lang"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var Range = require("./range").Range; +var Selection = function(session) { + this.session = session; + this.doc = session.getDocument(); + + this.clearSelection(); + this.lead = this.selectionLead = this.doc.createAnchor(0, 0); + this.anchor = this.selectionAnchor = this.doc.createAnchor(0, 0); + + var self = this; + this.lead.on("change", function(e) { + self._emit("changeCursor"); + if (!self.$isEmpty) + self._emit("changeSelection"); + if (!self.$keepDesiredColumnOnChange && e.old.column != e.value.column) + self.$desiredColumn = null; + }); + + this.selectionAnchor.on("change", function() { + if (!self.$isEmpty) + self._emit("changeSelection"); + }); +}; + +(function() { + + oop.implement(this, EventEmitter); + this.isEmpty = function() { + return (this.$isEmpty || ( + this.anchor.row == this.lead.row && + this.anchor.column == this.lead.column + )); + }; + this.isMultiLine = function() { + if (this.isEmpty()) { + return false; + } + + return this.getRange().isMultiLine(); + }; + this.getCursor = function() { + return this.lead.getPosition(); + }; + this.setSelectionAnchor = function(row, column) { + this.anchor.setPosition(row, column); + + if (this.$isEmpty) { + this.$isEmpty = false; + this._emit("changeSelection"); + } + }; + this.getSelectionAnchor = function() { + if (this.$isEmpty) + return this.getSelectionLead(); + else + return this.anchor.getPosition(); + }; + this.getSelectionLead = function() { + return this.lead.getPosition(); + }; + this.shiftSelection = function(columns) { + if (this.$isEmpty) { + this.moveCursorTo(this.lead.row, this.lead.column + columns); + return; + } + + var anchor = this.getSelectionAnchor(); + var lead = this.getSelectionLead(); + + var isBackwards = this.isBackwards(); + + if (!isBackwards || anchor.column !== 0) + this.setSelectionAnchor(anchor.row, anchor.column + columns); + + if (isBackwards || lead.column !== 0) { + this.$moveSelection(function() { + this.moveCursorTo(lead.row, lead.column + columns); + }); + } + }; + this.isBackwards = function() { + var anchor = this.anchor; + var lead = this.lead; + return (anchor.row > lead.row || (anchor.row == lead.row && anchor.column > lead.column)); + }; + this.getRange = function() { + var anchor = this.anchor; + var lead = this.lead; + + if (this.isEmpty()) + return Range.fromPoints(lead, lead); + + if (this.isBackwards()) { + return Range.fromPoints(lead, anchor); + } + else { + return Range.fromPoints(anchor, lead); + } + }; + this.clearSelection = function() { + if (!this.$isEmpty) { + this.$isEmpty = true; + this._emit("changeSelection"); + } + }; + this.selectAll = function() { + var lastRow = this.doc.getLength() - 1; + this.setSelectionAnchor(0, 0); + this.moveCursorTo(lastRow, this.doc.getLine(lastRow).length); + }; + this.setRange = + this.setSelectionRange = function(range, reverse) { + if (reverse) { + this.setSelectionAnchor(range.end.row, range.end.column); + this.selectTo(range.start.row, range.start.column); + } else { + this.setSelectionAnchor(range.start.row, range.start.column); + this.selectTo(range.end.row, range.end.column); + } + if (this.getRange().isEmpty()) + this.$isEmpty = true; + this.$desiredColumn = null; + }; + + this.$moveSelection = function(mover) { + var lead = this.lead; + if (this.$isEmpty) + this.setSelectionAnchor(lead.row, lead.column); + + mover.call(this); + }; + this.selectTo = function(row, column) { + this.$moveSelection(function() { + this.moveCursorTo(row, column); + }); + }; + this.selectToPosition = function(pos) { + this.$moveSelection(function() { + this.moveCursorToPosition(pos); + }); + }; + this.moveTo = function(row, column) { + this.clearSelection(); + this.moveCursorTo(row, column); + }; + this.moveToPosition = function(pos) { + this.clearSelection(); + this.moveCursorToPosition(pos); + }; + this.selectUp = function() { + this.$moveSelection(this.moveCursorUp); + }; + this.selectDown = function() { + this.$moveSelection(this.moveCursorDown); + }; + this.selectRight = function() { + this.$moveSelection(this.moveCursorRight); + }; + this.selectLeft = function() { + this.$moveSelection(this.moveCursorLeft); + }; + this.selectLineStart = function() { + this.$moveSelection(this.moveCursorLineStart); + }; + this.selectLineEnd = function() { + this.$moveSelection(this.moveCursorLineEnd); + }; + this.selectFileEnd = function() { + this.$moveSelection(this.moveCursorFileEnd); + }; + this.selectFileStart = function() { + this.$moveSelection(this.moveCursorFileStart); + }; + this.selectWordRight = function() { + this.$moveSelection(this.moveCursorWordRight); + }; + this.selectWordLeft = function() { + this.$moveSelection(this.moveCursorWordLeft); + }; + this.getWordRange = function(row, column) { + if (typeof column == "undefined") { + var cursor = row || this.lead; + row = cursor.row; + column = cursor.column; + } + return this.session.getWordRange(row, column); + }; + this.selectWord = function() { + this.setSelectionRange(this.getWordRange()); + }; + this.selectAWord = function() { + var cursor = this.getCursor(); + var range = this.session.getAWordRange(cursor.row, cursor.column); + this.setSelectionRange(range); + }; + + this.getLineRange = function(row, excludeLastChar) { + var rowStart = typeof row == "number" ? row : this.lead.row; + var rowEnd; + + var foldLine = this.session.getFoldLine(rowStart); + if (foldLine) { + rowStart = foldLine.start.row; + rowEnd = foldLine.end.row; + } else { + rowEnd = rowStart; + } + if (excludeLastChar === true) + return new Range(rowStart, 0, rowEnd, this.session.getLine(rowEnd).length); + else + return new Range(rowStart, 0, rowEnd + 1, 0); + }; + this.selectLine = function() { + this.setSelectionRange(this.getLineRange()); + }; + this.moveCursorUp = function() { + this.moveCursorBy(-1, 0); + }; + this.moveCursorDown = function() { + this.moveCursorBy(1, 0); + }; + this.moveCursorLeft = function() { + var cursor = this.lead.getPosition(), + fold; + + if (fold = this.session.getFoldAt(cursor.row, cursor.column, -1)) { + this.moveCursorTo(fold.start.row, fold.start.column); + } else if (cursor.column === 0) { + if (cursor.row > 0) { + this.moveCursorTo(cursor.row - 1, this.doc.getLine(cursor.row - 1).length); + } + } + else { + var tabSize = this.session.getTabSize(); + if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column-tabSize, cursor.column).split(" ").length-1 == tabSize) + this.moveCursorBy(0, -tabSize); + else + this.moveCursorBy(0, -1); + } + }; + this.moveCursorRight = function() { + var cursor = this.lead.getPosition(), + fold; + if (fold = this.session.getFoldAt(cursor.row, cursor.column, 1)) { + this.moveCursorTo(fold.end.row, fold.end.column); + } + else if (this.lead.column == this.doc.getLine(this.lead.row).length) { + if (this.lead.row < this.doc.getLength() - 1) { + this.moveCursorTo(this.lead.row + 1, 0); + } + } + else { + var tabSize = this.session.getTabSize(); + var cursor = this.lead; + if (this.session.isTabStop(cursor) && this.doc.getLine(cursor.row).slice(cursor.column, cursor.column+tabSize).split(" ").length-1 == tabSize) + this.moveCursorBy(0, tabSize); + else + this.moveCursorBy(0, 1); + } + }; + this.moveCursorLineStart = function() { + var row = this.lead.row; + var column = this.lead.column; + var screenRow = this.session.documentToScreenRow(row, column); + var firstColumnPosition = this.session.screenToDocumentPosition(screenRow, 0); + var beforeCursor = this.session.getDisplayLine( + row, null, firstColumnPosition.row, + firstColumnPosition.column + ); + + var leadingSpace = beforeCursor.match(/^\s*/); + if (leadingSpace[0].length != column && !this.session.$useEmacsStyleLineStart) + firstColumnPosition.column += leadingSpace[0].length; + this.moveCursorToPosition(firstColumnPosition); + }; + this.moveCursorLineEnd = function() { + var lead = this.lead; + var lineEnd = this.session.getDocumentLastRowColumnPosition(lead.row, lead.column); + if (this.lead.column == lineEnd.column) { + var line = this.session.getLine(lineEnd.row); + if (lineEnd.column == line.length) { + var textEnd = line.search(/\s+$/); + if (textEnd > 0) + lineEnd.column = textEnd; + } + } + + this.moveCursorTo(lineEnd.row, lineEnd.column); + }; + this.moveCursorFileEnd = function() { + var row = this.doc.getLength() - 1; + var column = this.doc.getLine(row).length; + this.moveCursorTo(row, column); + }; + this.moveCursorFileStart = function() { + this.moveCursorTo(0, 0); + }; + this.moveCursorLongWordRight = function() { + var row = this.lead.row; + var column = this.lead.column; + var line = this.doc.getLine(row); + var rightOfCursor = line.substring(column); + + var match; + this.session.nonTokenRe.lastIndex = 0; + this.session.tokenRe.lastIndex = 0; + var fold = this.session.getFoldAt(row, column, 1); + if (fold) { + this.moveCursorTo(fold.end.row, fold.end.column); + return; + } + if (match = this.session.nonTokenRe.exec(rightOfCursor)) { + column += this.session.nonTokenRe.lastIndex; + this.session.nonTokenRe.lastIndex = 0; + rightOfCursor = line.substring(column); + } + if (column >= line.length) { + this.moveCursorTo(row, line.length); + this.moveCursorRight(); + if (row < this.doc.getLength() - 1) + this.moveCursorWordRight(); + return; + } + if (match = this.session.tokenRe.exec(rightOfCursor)) { + column += this.session.tokenRe.lastIndex; + this.session.tokenRe.lastIndex = 0; + } + + this.moveCursorTo(row, column); + }; + this.moveCursorLongWordLeft = function() { + var row = this.lead.row; + var column = this.lead.column; + var fold; + if (fold = this.session.getFoldAt(row, column, -1)) { + this.moveCursorTo(fold.start.row, fold.start.column); + return; + } + + var str = this.session.getFoldStringAt(row, column, -1); + if (str == null) { + str = this.doc.getLine(row).substring(0, column); + } + + var leftOfCursor = lang.stringReverse(str); + var match; + this.session.nonTokenRe.lastIndex = 0; + this.session.tokenRe.lastIndex = 0; + if (match = this.session.nonTokenRe.exec(leftOfCursor)) { + column -= this.session.nonTokenRe.lastIndex; + leftOfCursor = leftOfCursor.slice(this.session.nonTokenRe.lastIndex); + this.session.nonTokenRe.lastIndex = 0; + } + if (column <= 0) { + this.moveCursorTo(row, 0); + this.moveCursorLeft(); + if (row > 0) + this.moveCursorWordLeft(); + return; + } + if (match = this.session.tokenRe.exec(leftOfCursor)) { + column -= this.session.tokenRe.lastIndex; + this.session.tokenRe.lastIndex = 0; + } + + this.moveCursorTo(row, column); + }; + + this.$shortWordEndIndex = function(rightOfCursor) { + var match, index = 0, ch; + var whitespaceRe = /\s/; + var tokenRe = this.session.tokenRe; + + tokenRe.lastIndex = 0; + if (match = this.session.tokenRe.exec(rightOfCursor)) { + index = this.session.tokenRe.lastIndex; + } else { + while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch)) + index ++; + + if (index < 1) { + tokenRe.lastIndex = 0; + while ((ch = rightOfCursor[index]) && !tokenRe.test(ch)) { + tokenRe.lastIndex = 0; + index ++; + if (whitespaceRe.test(ch)) { + if (index > 2) { + index--; + break; + } else { + while ((ch = rightOfCursor[index]) && whitespaceRe.test(ch)) + index ++; + if (index > 2) + break; + } + } + } + } + } + tokenRe.lastIndex = 0; + + return index; + }; + + this.moveCursorShortWordRight = function() { + var row = this.lead.row; + var column = this.lead.column; + var line = this.doc.getLine(row); + var rightOfCursor = line.substring(column); + + var fold = this.session.getFoldAt(row, column, 1); + if (fold) + return this.moveCursorTo(fold.end.row, fold.end.column); + + if (column == line.length) { + var l = this.doc.getLength(); + do { + row++; + rightOfCursor = this.doc.getLine(row); + } while (row < l && /^\s*$/.test(rightOfCursor)); + + if (!/^\s+/.test(rightOfCursor)) + rightOfCursor = ""; + column = 0; + } + + var index = this.$shortWordEndIndex(rightOfCursor); + + this.moveCursorTo(row, column + index); + }; + + this.moveCursorShortWordLeft = function() { + var row = this.lead.row; + var column = this.lead.column; + + var fold; + if (fold = this.session.getFoldAt(row, column, -1)) + return this.moveCursorTo(fold.start.row, fold.start.column); + + var line = this.session.getLine(row).substring(0, column); + if (column === 0) { + do { + row--; + line = this.doc.getLine(row); + } while (row > 0 && /^\s*$/.test(line)); + + column = line.length; + if (!/\s+$/.test(line)) + line = ""; + } + + var leftOfCursor = lang.stringReverse(line); + var index = this.$shortWordEndIndex(leftOfCursor); + + return this.moveCursorTo(row, column - index); + }; + + this.moveCursorWordRight = function() { + if (this.session.$selectLongWords) + this.moveCursorLongWordRight(); + else + this.moveCursorShortWordRight(); + }; + + this.moveCursorWordLeft = function() { + if (this.session.$selectLongWords) + this.moveCursorLongWordLeft(); + else + this.moveCursorShortWordLeft(); + }; + this.moveCursorBy = function(rows, chars) { + var screenPos = this.session.documentToScreenPosition( + this.lead.row, + this.lead.column + ); + + if (chars === 0) { + if (this.$desiredColumn) + screenPos.column = this.$desiredColumn; + else + this.$desiredColumn = screenPos.column; + } + + var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenPos.column); + + if (rows !== 0 && chars === 0 && docPos.row === this.lead.row && docPos.column === this.lead.column) { + if (this.session.lineWidgets && this.session.lineWidgets[docPos.row]) + docPos.row++; + } + this.moveCursorTo(docPos.row, docPos.column + chars, chars === 0); + }; + this.moveCursorToPosition = function(position) { + this.moveCursorTo(position.row, position.column); + }; + this.moveCursorTo = function(row, column, keepDesiredColumn) { + var fold = this.session.getFoldAt(row, column, 1); + if (fold) { + row = fold.start.row; + column = fold.start.column; + } + + this.$keepDesiredColumnOnChange = true; + this.lead.setPosition(row, column); + this.$keepDesiredColumnOnChange = false; + + if (!keepDesiredColumn) + this.$desiredColumn = null; + }; + this.moveCursorToScreen = function(row, column, keepDesiredColumn) { + var pos = this.session.screenToDocumentPosition(row, column); + this.moveCursorTo(pos.row, pos.column, keepDesiredColumn); + }; + this.detach = function() { + this.lead.detach(); + this.anchor.detach(); + this.session = this.doc = null; + }; + + this.fromOrientedRange = function(range) { + this.setSelectionRange(range, range.cursor == range.start); + this.$desiredColumn = range.desiredColumn || this.$desiredColumn; + }; + + this.toOrientedRange = function(range) { + var r = this.getRange(); + if (range) { + range.start.column = r.start.column; + range.start.row = r.start.row; + range.end.column = r.end.column; + range.end.row = r.end.row; + } else { + range = r; + } + + range.cursor = this.isBackwards() ? range.start : range.end; + range.desiredColumn = this.$desiredColumn; + return range; + }; + this.getRangeOfMovements = function(func) { + var start = this.getCursor(); + try { + func.call(null, this); + var end = this.getCursor(); + return Range.fromPoints(start,end); + } catch(e) { + return Range.fromPoints(start,start); + } finally { + this.moveCursorToPosition(start); + } + }; + + this.toJSON = function() { + if (this.rangeCount) { + var data = this.ranges.map(function(r) { + var r1 = r.clone(); + r1.isBackwards = r.cursor == r.start; + return r1; + }); + } else { + var data = this.getRange(); + data.isBackwards = this.isBackwards(); + } + return data; + }; + + this.fromJSON = function(data) { + if (data.start == undefined) { + if (this.rangeList) { + this.toSingleRange(data[0]); + for (var i = data.length; i--; ) { + var r = Range.fromPoints(data[i].start, data[i].end); + if (data.isBackwards) + r.cursor = r.start; + this.addRange(r, true); + } + return; + } else + data = data[0]; + } + if (this.rangeList) + this.toSingleRange(data); + this.setSelectionRange(data, data.isBackwards); + }; + + this.isEqual = function(data) { + if ((data.length || this.rangeCount) && data.length != this.rangeCount) + return false; + if (!data.length || !this.ranges) + return this.getRange().isEqual(data); + + for (var i = this.ranges.length; i--; ) { + if (!this.ranges[i].isEqual(data[i])) + return false; + } + return true; + }; + +}).call(Selection.prototype); + +exports.Selection = Selection; +}); + +define("ace/tokenizer",["require","exports","module","ace/config"], function(require, exports, module) { +"use strict"; + +var config = require("./config"); +var MAX_TOKEN_COUNT = 2000; +var Tokenizer = function(rules) { + this.states = rules; + + this.regExps = {}; + this.matchMappings = {}; + for (var key in this.states) { + var state = this.states[key]; + var ruleRegExps = []; + var matchTotal = 0; + var mapping = this.matchMappings[key] = {defaultToken: "text"}; + var flag = "g"; + + var splitterRurles = []; + for (var i = 0; i < state.length; i++) { + var rule = state[i]; + if (rule.defaultToken) + mapping.defaultToken = rule.defaultToken; + if (rule.caseInsensitive) + flag = "gi"; + if (rule.regex == null) + continue; + + if (rule.regex instanceof RegExp) + rule.regex = rule.regex.toString().slice(1, -1); + var adjustedregex = rule.regex; + var matchcount = new RegExp("(?:(" + adjustedregex + ")|(.))").exec("a").length - 2; + if (Array.isArray(rule.token)) { + if (rule.token.length == 1 || matchcount == 1) { + rule.token = rule.token[0]; + } else if (matchcount - 1 != rule.token.length) { + this.reportError("number of classes and regexp groups doesn't match", { + rule: rule, + groupCount: matchcount - 1 + }); + rule.token = rule.token[0]; + } else { + rule.tokenArray = rule.token; + rule.token = null; + rule.onMatch = this.$arrayTokens; + } + } else if (typeof rule.token == "function" && !rule.onMatch) { + if (matchcount > 1) + rule.onMatch = this.$applyToken; + else + rule.onMatch = rule.token; + } + + if (matchcount > 1) { + if (/\\\d/.test(rule.regex)) { + adjustedregex = rule.regex.replace(/\\([0-9]+)/g, function(match, digit) { + return "\\" + (parseInt(digit, 10) + matchTotal + 1); + }); + } else { + matchcount = 1; + adjustedregex = this.removeCapturingGroups(rule.regex); + } + if (!rule.splitRegex && typeof rule.token != "string") + splitterRurles.push(rule); // flag will be known only at the very end + } + + mapping[matchTotal] = i; + matchTotal += matchcount; + + ruleRegExps.push(adjustedregex); + if (!rule.onMatch) + rule.onMatch = null; + } + + if (!ruleRegExps.length) { + mapping[0] = 0; + ruleRegExps.push("$"); + } + + splitterRurles.forEach(function(rule) { + rule.splitRegex = this.createSplitterRegexp(rule.regex, flag); + }, this); + + this.regExps[key] = new RegExp("(" + ruleRegExps.join(")|(") + ")|($)", flag); + } +}; + +(function() { + this.$setMaxTokenCount = function(m) { + MAX_TOKEN_COUNT = m | 0; + }; + + this.$applyToken = function(str) { + var values = this.splitRegex.exec(str).slice(1); + var types = this.token.apply(this, values); + if (typeof types === "string") + return [{type: types, value: str}]; + + var tokens = []; + for (var i = 0, l = types.length; i < l; i++) { + if (values[i]) + tokens[tokens.length] = { + type: types[i], + value: values[i] + }; + } + return tokens; + }, + + this.$arrayTokens = function(str) { + if (!str) + return []; + var values = this.splitRegex.exec(str); + if (!values) + return "text"; + var tokens = []; + var types = this.tokenArray; + for (var i = 0, l = types.length; i < l; i++) { + if (values[i + 1]) + tokens[tokens.length] = { + type: types[i], + value: values[i + 1] + }; + } + return tokens; + }; + + this.removeCapturingGroups = function(src) { + var r = src.replace( + /\[(?:\\.|[^\]])*?\]|\\.|\(\?[:=!]|(\()/g, + function(x, y) {return y ? "(?:" : x;} + ); + return r; + }; + + this.createSplitterRegexp = function(src, flag) { + if (src.indexOf("(?=") != -1) { + var stack = 0; + var inChClass = false; + var lastCapture = {}; + src.replace(/(\\.)|(\((?:\?[=!])?)|(\))|([\[\]])/g, function( + m, esc, parenOpen, parenClose, square, index + ) { + if (inChClass) { + inChClass = square != "]"; + } else if (square) { + inChClass = true; + } else if (parenClose) { + if (stack == lastCapture.stack) { + lastCapture.end = index+1; + lastCapture.stack = -1; + } + stack--; + } else if (parenOpen) { + stack++; + if (parenOpen.length != 1) { + lastCapture.stack = stack + lastCapture.start = index; + } + } + return m; + }); + + if (lastCapture.end != null && /^\)*$/.test(src.substr(lastCapture.end))) + src = src.substring(0, lastCapture.start) + src.substr(lastCapture.end); + } + return new RegExp(src, (flag||"").replace("g", "")); + }; + this.getLineTokens = function(line, startState) { + if (startState && typeof startState != "string") { + var stack = startState.slice(0); + startState = stack[0]; + if (startState === "#tmp") { + stack.shift() + startState = stack.shift() + } + } else + var stack = []; + + var currentState = startState || "start"; + var state = this.states[currentState]; + if (!state) { + currentState = "start"; + state = this.states[currentState]; + } + var mapping = this.matchMappings[currentState]; + var re = this.regExps[currentState]; + re.lastIndex = 0; + + var match, tokens = []; + var lastIndex = 0; + var matchAttempts = 0; + + var token = {type: null, value: ""}; + + while (match = re.exec(line)) { + var type = mapping.defaultToken; + var rule = null; + var value = match[0]; + var index = re.lastIndex; + + if (index - value.length > lastIndex) { + var skipped = line.substring(lastIndex, index - value.length); + if (token.type == type) { + token.value += skipped; + } else { + if (token.type) + tokens.push(token); + token = {type: type, value: skipped}; + } + } + + for (var i = 0; i < match.length-2; i++) { + if (match[i + 1] === undefined) + continue; + + rule = state[mapping[i]]; + + if (rule.onMatch) + type = rule.onMatch(value, currentState, stack); + else + type = rule.token; + + if (rule.next) { + if (typeof rule.next == "string") { + currentState = rule.next; + } else { + currentState = rule.next(currentState, stack); + } + + state = this.states[currentState]; + if (!state) { + this.reportError("state doesn't exist", currentState); + currentState = "start"; + state = this.states[currentState]; + } + mapping = this.matchMappings[currentState]; + lastIndex = index; + re = this.regExps[currentState]; + re.lastIndex = index; + } + break; + } + + if (value) { + if (typeof type === "string") { + if ((!rule || rule.merge !== false) && token.type === type) { + token.value += value; + } else { + if (token.type) + tokens.push(token); + token = {type: type, value: value}; + } + } else if (type) { + if (token.type) + tokens.push(token); + token = {type: null, value: ""}; + for (var i = 0; i < type.length; i++) + tokens.push(type[i]); + } + } + + if (lastIndex == line.length) + break; + + lastIndex = index; + + if (matchAttempts++ > MAX_TOKEN_COUNT) { + if (matchAttempts > 2 * line.length) { + this.reportError("infinite loop with in ace tokenizer", { + startState: startState, + line: line + }); + } + while (lastIndex < line.length) { + if (token.type) + tokens.push(token); + token = { + value: line.substring(lastIndex, lastIndex += 2000), + type: "overflow" + }; + } + currentState = "start"; + stack = []; + break; + } + } + + if (token.type) + tokens.push(token); + + if (stack.length > 1) { + if (stack[0] !== currentState) + stack.unshift("#tmp", currentState); + } + return { + tokens : tokens, + state : stack.length ? stack : currentState + }; + }; + + this.reportError = config.reportError; + +}).call(Tokenizer.prototype); + +exports.Tokenizer = Tokenizer; +}); + +define("ace/mode/text_highlight_rules",["require","exports","module","ace/lib/lang"], function(require, exports, module) { +"use strict"; + +var lang = require("../lib/lang"); + +var TextHighlightRules = function() { + + this.$rules = { + "start" : [{ + token : "empty_line", + regex : '^$' + }, { + defaultToken : "text" + }] + }; +}; + +(function() { + + this.addRules = function(rules, prefix) { + if (!prefix) { + for (var key in rules) + this.$rules[key] = rules[key]; + return; + } + for (var key in rules) { + var state = rules[key]; + for (var i = 0; i < state.length; i++) { + var rule = state[i]; + if (rule.next || rule.onMatch) { + if (typeof rule.next != "string") { + if (rule.nextState && rule.nextState.indexOf(prefix) !== 0) + rule.nextState = prefix + rule.nextState; + } else { + if (rule.next.indexOf(prefix) !== 0) + rule.next = prefix + rule.next; + } + } + } + this.$rules[prefix + key] = state; + } + }; + + this.getRules = function() { + return this.$rules; + }; + + this.embedRules = function (HighlightRules, prefix, escapeRules, states, append) { + var embedRules = typeof HighlightRules == "function" + ? new HighlightRules().getRules() + : HighlightRules; + if (states) { + for (var i = 0; i < states.length; i++) + states[i] = prefix + states[i]; + } else { + states = []; + for (var key in embedRules) + states.push(prefix + key); + } + + this.addRules(embedRules, prefix); + + if (escapeRules) { + var addRules = Array.prototype[append ? "push" : "unshift"]; + for (var i = 0; i < states.length; i++) + addRules.apply(this.$rules[states[i]], lang.deepCopy(escapeRules)); + } + + if (!this.$embeds) + this.$embeds = []; + this.$embeds.push(prefix); + }; + + this.getEmbeds = function() { + return this.$embeds; + }; + + var pushState = function(currentState, stack) { + if (currentState != "start" || stack.length) + stack.unshift(this.nextState, currentState); + return this.nextState; + }; + var popState = function(currentState, stack) { + stack.shift(); + return stack.shift() || "start"; + }; + + this.normalizeRules = function() { + var id = 0; + var rules = this.$rules; + function processState(key) { + var state = rules[key]; + state.processed = true; + for (var i = 0; i < state.length; i++) { + var rule = state[i]; + if (!rule.regex && rule.start) { + rule.regex = rule.start; + if (!rule.next) + rule.next = []; + rule.next.push({ + defaultToken: rule.token + }, { + token: rule.token + ".end", + regex: rule.end || rule.start, + next: "pop" + }); + rule.token = rule.token + ".start"; + rule.push = true; + } + var next = rule.next || rule.push; + if (next && Array.isArray(next)) { + var stateName = rule.stateName; + if (!stateName) { + stateName = rule.token; + if (typeof stateName != "string") + stateName = stateName[0] || ""; + if (rules[stateName]) + stateName += id++; + } + rules[stateName] = next; + rule.next = stateName; + processState(stateName); + } else if (next == "pop") { + rule.next = popState; + } + + if (rule.push) { + rule.nextState = rule.next || rule.push; + rule.next = pushState; + delete rule.push; + } + + if (rule.rules) { + for (var r in rule.rules) { + if (rules[r]) { + if (rules[r].push) + rules[r].push.apply(rules[r], rule.rules[r]); + } else { + rules[r] = rule.rules[r]; + } + } + } + if (rule.include || typeof rule == "string") { + var includeName = rule.include || rule; + var toInsert = rules[includeName]; + } else if (Array.isArray(rule)) + toInsert = rule; + + if (toInsert) { + var args = [i, 1].concat(toInsert); + if (rule.noEscape) + args = args.filter(function(x) {return !x.next;}); + state.splice.apply(state, args); + i--; + toInsert = null; + } + + if (rule.keywordMap) { + rule.token = this.createKeywordMapper( + rule.keywordMap, rule.defaultToken || "text", rule.caseInsensitive + ); + delete rule.defaultToken; + } + } + } + Object.keys(rules).forEach(processState, this); + }; + + this.createKeywordMapper = function(map, defaultToken, ignoreCase, splitChar) { + var keywords = Object.create(null); + Object.keys(map).forEach(function(className) { + var a = map[className]; + if (ignoreCase) + a = a.toLowerCase(); + var list = a.split(splitChar || "|"); + for (var i = list.length; i--; ) + keywords[list[i]] = className; + }); + if (Object.getPrototypeOf(keywords)) { + keywords.__proto__ = null; + } + this.$keywordList = Object.keys(keywords); + map = null; + return ignoreCase + ? function(value) {return keywords[value.toLowerCase()] || defaultToken } + : function(value) {return keywords[value] || defaultToken }; + }; + + this.getKeywords = function() { + return this.$keywords; + }; + +}).call(TextHighlightRules.prototype); + +exports.TextHighlightRules = TextHighlightRules; +}); + +define("ace/mode/behaviour",["require","exports","module"], function(require, exports, module) { +"use strict"; + +var Behaviour = function() { + this.$behaviours = {}; +}; + +(function () { + + this.add = function (name, action, callback) { + switch (undefined) { + case this.$behaviours: + this.$behaviours = {}; + case this.$behaviours[name]: + this.$behaviours[name] = {}; + } + this.$behaviours[name][action] = callback; + } + + this.addBehaviours = function (behaviours) { + for (var key in behaviours) { + for (var action in behaviours[key]) { + this.add(key, action, behaviours[key][action]); + } + } + } + + this.remove = function (name) { + if (this.$behaviours && this.$behaviours[name]) { + delete this.$behaviours[name]; + } + } + + this.inherit = function (mode, filter) { + if (typeof mode === "function") { + var behaviours = new mode().getBehaviours(filter); + } else { + var behaviours = mode.getBehaviours(filter); + } + this.addBehaviours(behaviours); + } + + this.getBehaviours = function (filter) { + if (!filter) { + return this.$behaviours; + } else { + var ret = {} + for (var i = 0; i < filter.length; i++) { + if (this.$behaviours[filter[i]]) { + ret[filter[i]] = this.$behaviours[filter[i]]; + } + } + return ret; + } + } + +}).call(Behaviour.prototype); + +exports.Behaviour = Behaviour; +}); + +define("ace/unicode",["require","exports","module"], function(require, exports, module) { +"use strict"; +exports.packages = {}; + +addUnicodePackage({ + L: "0041-005A0061-007A00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05250531-055605590561-058705D0-05EA05F0-05F20621-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280904-0939093D09500958-0961097109720979-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-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510D0-10FA10FC1100-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-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209421022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2D00-2D252D30-2D652D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A65FA662-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78BA78CA7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC", + Ll: "0061-007A00AA00B500BA00DF-00F600F8-00FF01010103010501070109010B010D010F01110113011501170119011B011D011F01210123012501270129012B012D012F01310133013501370138013A013C013E014001420144014601480149014B014D014F01510153015501570159015B015D015F01610163016501670169016B016D016F0171017301750177017A017C017E-0180018301850188018C018D019201950199-019B019E01A101A301A501A801AA01AB01AD01B001B401B601B901BA01BD-01BF01C601C901CC01CE01D001D201D401D601D801DA01DC01DD01DF01E101E301E501E701E901EB01ED01EF01F001F301F501F901FB01FD01FF02010203020502070209020B020D020F02110213021502170219021B021D021F02210223022502270229022B022D022F02310233-0239023C023F0240024202470249024B024D024F-02930295-02AF037103730377037B-037D039003AC-03CE03D003D103D5-03D703D903DB03DD03DF03E103E303E503E703E903EB03ED03EF-03F303F503F803FB03FC0430-045F04610463046504670469046B046D046F04710473047504770479047B047D047F0481048B048D048F04910493049504970499049B049D049F04A104A304A504A704A904AB04AD04AF04B104B304B504B704B904BB04BD04BF04C204C404C604C804CA04CC04CE04CF04D104D304D504D704D904DB04DD04DF04E104E304E504E704E904EB04ED04EF04F104F304F504F704F904FB04FD04FF05010503050505070509050B050D050F05110513051505170519051B051D051F0521052305250561-05871D00-1D2B1D62-1D771D79-1D9A1E011E031E051E071E091E0B1E0D1E0F1E111E131E151E171E191E1B1E1D1E1F1E211E231E251E271E291E2B1E2D1E2F1E311E331E351E371E391E3B1E3D1E3F1E411E431E451E471E491E4B1E4D1E4F1E511E531E551E571E591E5B1E5D1E5F1E611E631E651E671E691E6B1E6D1E6F1E711E731E751E771E791E7B1E7D1E7F1E811E831E851E871E891E8B1E8D1E8F1E911E931E95-1E9D1E9F1EA11EA31EA51EA71EA91EAB1EAD1EAF1EB11EB31EB51EB71EB91EBB1EBD1EBF1EC11EC31EC51EC71EC91ECB1ECD1ECF1ED11ED31ED51ED71ED91EDB1EDD1EDF1EE11EE31EE51EE71EE91EEB1EED1EEF1EF11EF31EF51EF71EF91EFB1EFD1EFF-1F071F10-1F151F20-1F271F30-1F371F40-1F451F50-1F571F60-1F671F70-1F7D1F80-1F871F90-1F971FA0-1FA71FB0-1FB41FB61FB71FBE1FC2-1FC41FC61FC71FD0-1FD31FD61FD71FE0-1FE71FF2-1FF41FF61FF7210A210E210F2113212F21342139213C213D2146-2149214E21842C30-2C5E2C612C652C662C682C6A2C6C2C712C732C742C76-2C7C2C812C832C852C872C892C8B2C8D2C8F2C912C932C952C972C992C9B2C9D2C9F2CA12CA32CA52CA72CA92CAB2CAD2CAF2CB12CB32CB52CB72CB92CBB2CBD2CBF2CC12CC32CC52CC72CC92CCB2CCD2CCF2CD12CD32CD52CD72CD92CDB2CDD2CDF2CE12CE32CE42CEC2CEE2D00-2D25A641A643A645A647A649A64BA64DA64FA651A653A655A657A659A65BA65DA65FA663A665A667A669A66BA66DA681A683A685A687A689A68BA68DA68FA691A693A695A697A723A725A727A729A72BA72DA72F-A731A733A735A737A739A73BA73DA73FA741A743A745A747A749A74BA74DA74FA751A753A755A757A759A75BA75DA75FA761A763A765A767A769A76BA76DA76FA771-A778A77AA77CA77FA781A783A785A787A78CFB00-FB06FB13-FB17FF41-FF5A", + Lu: "0041-005A00C0-00D600D8-00DE01000102010401060108010A010C010E01100112011401160118011A011C011E01200122012401260128012A012C012E01300132013401360139013B013D013F0141014301450147014A014C014E01500152015401560158015A015C015E01600162016401660168016A016C016E017001720174017601780179017B017D018101820184018601870189-018B018E-0191019301940196-0198019C019D019F01A001A201A401A601A701A901AC01AE01AF01B1-01B301B501B701B801BC01C401C701CA01CD01CF01D101D301D501D701D901DB01DE01E001E201E401E601E801EA01EC01EE01F101F401F6-01F801FA01FC01FE02000202020402060208020A020C020E02100212021402160218021A021C021E02200222022402260228022A022C022E02300232023A023B023D023E02410243-02460248024A024C024E03700372037603860388-038A038C038E038F0391-03A103A3-03AB03CF03D2-03D403D803DA03DC03DE03E003E203E403E603E803EA03EC03EE03F403F703F903FA03FD-042F04600462046404660468046A046C046E04700472047404760478047A047C047E0480048A048C048E04900492049404960498049A049C049E04A004A204A404A604A804AA04AC04AE04B004B204B404B604B804BA04BC04BE04C004C104C304C504C704C904CB04CD04D004D204D404D604D804DA04DC04DE04E004E204E404E604E804EA04EC04EE04F004F204F404F604F804FA04FC04FE05000502050405060508050A050C050E05100512051405160518051A051C051E0520052205240531-055610A0-10C51E001E021E041E061E081E0A1E0C1E0E1E101E121E141E161E181E1A1E1C1E1E1E201E221E241E261E281E2A1E2C1E2E1E301E321E341E361E381E3A1E3C1E3E1E401E421E441E461E481E4A1E4C1E4E1E501E521E541E561E581E5A1E5C1E5E1E601E621E641E661E681E6A1E6C1E6E1E701E721E741E761E781E7A1E7C1E7E1E801E821E841E861E881E8A1E8C1E8E1E901E921E941E9E1EA01EA21EA41EA61EA81EAA1EAC1EAE1EB01EB21EB41EB61EB81EBA1EBC1EBE1EC01EC21EC41EC61EC81ECA1ECC1ECE1ED01ED21ED41ED61ED81EDA1EDC1EDE1EE01EE21EE41EE61EE81EEA1EEC1EEE1EF01EF21EF41EF61EF81EFA1EFC1EFE1F08-1F0F1F18-1F1D1F28-1F2F1F38-1F3F1F48-1F4D1F591F5B1F5D1F5F1F68-1F6F1FB8-1FBB1FC8-1FCB1FD8-1FDB1FE8-1FEC1FF8-1FFB21022107210B-210D2110-211221152119-211D212421262128212A-212D2130-2133213E213F214521832C00-2C2E2C602C62-2C642C672C692C6B2C6D-2C702C722C752C7E-2C802C822C842C862C882C8A2C8C2C8E2C902C922C942C962C982C9A2C9C2C9E2CA02CA22CA42CA62CA82CAA2CAC2CAE2CB02CB22CB42CB62CB82CBA2CBC2CBE2CC02CC22CC42CC62CC82CCA2CCC2CCE2CD02CD22CD42CD62CD82CDA2CDC2CDE2CE02CE22CEB2CEDA640A642A644A646A648A64AA64CA64EA650A652A654A656A658A65AA65CA65EA662A664A666A668A66AA66CA680A682A684A686A688A68AA68CA68EA690A692A694A696A722A724A726A728A72AA72CA72EA732A734A736A738A73AA73CA73EA740A742A744A746A748A74AA74CA74EA750A752A754A756A758A75AA75CA75EA760A762A764A766A768A76AA76CA76EA779A77BA77DA77EA780A782A784A786A78BFF21-FF3A", + Lt: "01C501C801CB01F21F88-1F8F1F98-1F9F1FA8-1FAF1FBC1FCC1FFC", + Lm: "02B0-02C102C6-02D102E0-02E402EC02EE0374037A0559064006E506E607F407F507FA081A0824082809710E460EC610FC17D718431AA71C78-1C7D1D2C-1D611D781D9B-1DBF2071207F2090-20942C7D2D6F2E2F30053031-3035303B309D309E30FC-30FEA015A4F8-A4FDA60CA67FA717-A71FA770A788A9CFAA70AADDFF70FF9EFF9F", + Lo: "01BB01C0-01C3029405D0-05EA05F0-05F20621-063F0641-064A066E066F0671-06D306D506EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA0800-08150904-0939093D09500958-096109720979-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-0CB90CBD0CDE0CE00CE10D05-0D0C0D0E-0D100D12-0D280D2A-0D390D3D0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E450E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EDC0EDD0F000F40-0F470F49-0F6C0F88-0F8B1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10D0-10FA1100-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-1BA01BAE1BAF1C00-1C231C4D-1C4F1C5A-1C771CE9-1CEC1CEE-1CF12135-21382D30-2D652D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE3006303C3041-3096309F30A1-30FA30FF3105-312D3131-318E31A0-31B731F0-31FF3400-4DB54E00-9FCBA000-A014A016-A48CA4D0-A4F7A500-A60BA610-A61FA62AA62BA66EA6A0-A6E5A7FB-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2AA00-AA28AA40-AA42AA44-AA4BAA60-AA6FAA71-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADBAADCABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA2DFA30-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-065E067006D6-06DC06DE-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0903093C093E-094E0951-0955096209630981-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-0F840F860F870F90-0F970F99-0FBC0FC6102B-103E1056-1059105E-10601062-10641067-106D1071-10741082-108D108F109A-109D135F1712-17141732-1734175217531772177317B6-17D317DD180B-180D18A91920-192B1930-193B19B0-19C019C819C91A17-1A1B1A55-1A5E1A60-1A7C1A7F1B00-1B041B34-1B441B6B-1B731B80-1B821BA1-1BAA1C24-1C371CD0-1CD21CD4-1CE81CED1CF21DC0-1DE61DFD-1DFF20D0-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66F-A672A67CA67DA6F0A6F1A802A806A80BA823-A827A880A881A8B4-A8C4A8E0-A8F1A926-A92DA947-A953A980-A983A9B3-A9C0AA29-AA36AA43AA4CAA4DAA7BAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE3-ABEAABECABEDFB1EFE00-FE0FFE20-FE26", + Mn: "0300-036F0483-04870591-05BD05BF05C105C205C405C505C70610-061A064B-065E067006D6-06DC06DF-06E406E706E806EA-06ED07110730-074A07A6-07B007EB-07F30816-0819081B-08230825-08270829-082D0900-0902093C0941-0948094D0951-095509620963098109BC09C1-09C409CD09E209E30A010A020A3C0A410A420A470A480A4B-0A4D0A510A700A710A750A810A820ABC0AC1-0AC50AC70AC80ACD0AE20AE30B010B3C0B3F0B41-0B440B4D0B560B620B630B820BC00BCD0C3E-0C400C46-0C480C4A-0C4D0C550C560C620C630CBC0CBF0CC60CCC0CCD0CE20CE30D41-0D440D4D0D620D630DCA0DD2-0DD40DD60E310E34-0E3A0E47-0E4E0EB10EB4-0EB90EBB0EBC0EC8-0ECD0F180F190F350F370F390F71-0F7E0F80-0F840F860F870F90-0F970F99-0FBC0FC6102D-10301032-10371039103A103D103E10581059105E-10601071-1074108210851086108D109D135F1712-17141732-1734175217531772177317B7-17BD17C617C9-17D317DD180B-180D18A91920-19221927192819321939-193B1A171A181A561A58-1A5E1A601A621A65-1A6C1A73-1A7C1A7F1B00-1B031B341B36-1B3A1B3C1B421B6B-1B731B801B811BA2-1BA51BA81BA91C2C-1C331C361C371CD0-1CD21CD4-1CE01CE2-1CE81CED1DC0-1DE61DFD-1DFF20D0-20DC20E120E5-20F02CEF-2CF12DE0-2DFF302A-302F3099309AA66FA67CA67DA6F0A6F1A802A806A80BA825A826A8C4A8E0-A8F1A926-A92DA947-A951A980-A982A9B3A9B6-A9B9A9BCAA29-AA2EAA31AA32AA35AA36AA43AA4CAAB0AAB2-AAB4AAB7AAB8AABEAABFAAC1ABE5ABE8ABEDFB1EFE00-FE0FFE20-FE26", + Mc: "0903093E-09400949-094C094E0982098309BE-09C009C709C809CB09CC09D70A030A3E-0A400A830ABE-0AC00AC90ACB0ACC0B020B030B3E0B400B470B480B4B0B4C0B570BBE0BBF0BC10BC20BC6-0BC80BCA-0BCC0BD70C01-0C030C41-0C440C820C830CBE0CC0-0CC40CC70CC80CCA0CCB0CD50CD60D020D030D3E-0D400D46-0D480D4A-0D4C0D570D820D830DCF-0DD10DD8-0DDF0DF20DF30F3E0F3F0F7F102B102C10311038103B103C105610571062-10641067-106D108310841087-108C108F109A-109C17B617BE-17C517C717C81923-19261929-192B193019311933-193819B0-19C019C819C91A19-1A1B1A551A571A611A631A641A6D-1A721B041B351B3B1B3D-1B411B431B441B821BA11BA61BA71BAA1C24-1C2B1C341C351CE11CF2A823A824A827A880A881A8B4-A8C3A952A953A983A9B4A9B5A9BAA9BBA9BD-A9C0AA2FAA30AA33AA34AA4DAA7BABE3ABE4ABE6ABE7ABE9ABEAABEC", + Me: "0488048906DE20DD-20E020E2-20E4A670-A672", + N: "0030-003900B200B300B900BC-00BE0660-066906F0-06F907C0-07C90966-096F09E6-09EF09F4-09F90A66-0A6F0AE6-0AEF0B66-0B6F0BE6-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-32293251-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-19DA1A80-1A891A90-1A991B50-1B591BB0-1BB91C40-1C491C50-1C59A620-A629A8D0-A8D9A900-A909A9D0-A9D9AA50-AA59ABF0-ABF9FF10-FF19", + Nl: "16EE-16F02160-21822185-218830073021-30293038-303AA6E6-A6EF", + No: "00B200B300B900BC-00BE09F4-09F90BF0-0BF20C78-0C7E0D70-0D750F2A-0F331369-137C17F0-17F920702074-20792080-20892150-215F21892460-249B24EA-24FF2776-27932CFD3192-31953220-32293251-325F3280-328932B1-32BFA830-A835", + P: "0021-00230025-002A002C-002F003A003B003F0040005B-005D005F007B007D00A100AB00B700BB00BF037E0387055A-055F0589058A05BE05C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F3A-0F3D0F850FD0-0FD4104A-104F10FB1361-13681400166D166E169B169C16EB-16ED1735173617D4-17D617D8-17DA1800-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD32010-20272030-20432045-20512053-205E207D207E208D208E2329232A2768-277527C527C627E6-27EF2983-299829D8-29DB29FC29FD2CF9-2CFC2CFE2CFF2E00-2E2E2E302E313001-30033008-30113014-301F3030303D30A030FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFD3EFD3FFE10-FE19FE30-FE52FE54-FE61FE63FE68FE6AFE6BFF01-FF03FF05-FF0AFF0C-FF0FFF1AFF1BFF1FFF20FF3B-FF3DFF3FFF5BFF5DFF5F-FF65", + Pd: "002D058A05BE140018062010-20152E172E1A301C303030A0FE31FE32FE58FE63FF0D", + Ps: "0028005B007B0F3A0F3C169B201A201E2045207D208D23292768276A276C276E27702772277427C527E627E827EA27EC27EE2983298529872989298B298D298F299129932995299729D829DA29FC2E222E242E262E283008300A300C300E3010301430163018301A301DFD3EFE17FE35FE37FE39FE3BFE3DFE3FFE41FE43FE47FE59FE5BFE5DFF08FF3BFF5BFF5FFF62", + Pe: "0029005D007D0F3B0F3D169C2046207E208E232A2769276B276D276F27712773277527C627E727E927EB27ED27EF298429862988298A298C298E2990299229942996299829D929DB29FD2E232E252E272E293009300B300D300F3011301530173019301B301E301FFD3FFE18FE36FE38FE3AFE3CFE3EFE40FE42FE44FE48FE5AFE5CFE5EFF09FF3DFF5DFF60FF63", + Pi: "00AB2018201B201C201F20392E022E042E092E0C2E1C2E20", + Pf: "00BB2019201D203A2E032E052E0A2E0D2E1D2E21", + Pc: "005F203F20402054FE33FE34FE4D-FE4FFF3F", + Po: "0021-00230025-0027002A002C002E002F003A003B003F0040005C00A100B700BF037E0387055A-055F058905C005C305C605F305F40609060A060C060D061B061E061F066A-066D06D40700-070D07F7-07F90830-083E0964096509700DF40E4F0E5A0E5B0F04-0F120F850FD0-0FD4104A-104F10FB1361-1368166D166E16EB-16ED1735173617D4-17D617D8-17DA1800-18051807-180A1944194519DE19DF1A1E1A1F1AA0-1AA61AA8-1AAD1B5A-1B601C3B-1C3F1C7E1C7F1CD3201620172020-20272030-2038203B-203E2041-20432047-205120532055-205E2CF9-2CFC2CFE2CFF2E002E012E06-2E082E0B2E0E-2E162E182E192E1B2E1E2E1F2E2A-2E2E2E302E313001-3003303D30FBA4FEA4FFA60D-A60FA673A67EA6F2-A6F7A874-A877A8CEA8CFA8F8-A8FAA92EA92FA95FA9C1-A9CDA9DEA9DFAA5C-AA5FAADEAADFABEBFE10-FE16FE19FE30FE45FE46FE49-FE4CFE50-FE52FE54-FE57FE5F-FE61FE68FE6AFE6BFF01-FF03FF05-FF07FF0AFF0CFF0EFF0FFF1AFF1BFF1FFF20FF3CFF61FF64FF65", + S: "0024002B003C-003E005E0060007C007E00A2-00A900AC00AE-00B100B400B600B800D700F702C2-02C502D2-02DF02E5-02EB02ED02EF-02FF03750384038503F604820606-0608060B060E060F06E906FD06FE07F609F209F309FA09FB0AF10B700BF3-0BFA0C7F0CF10CF20D790E3F0F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-139917DB194019E0-19FF1B61-1B6A1B74-1B7C1FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE20442052207A-207C208A-208C20A0-20B8210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B2140-2144214A-214D214F2190-2328232B-23E82400-24262440-244A249C-24E92500-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE27C0-27C427C7-27CA27CC27D0-27E527F0-29822999-29D729DC-29FB29FE-2B4C2B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F309B309C319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A700-A716A720A721A789A78AA828-A82BA836-A839AA77-AA79FB29FDFCFDFDFE62FE64-FE66FE69FF04FF0BFF1C-FF1EFF3EFF40FF5CFF5EFFE0-FFE6FFE8-FFEEFFFCFFFD", + Sm: "002B003C-003E007C007E00AC00B100D700F703F60606-060820442052207A-207C208A-208C2140-2144214B2190-2194219A219B21A021A321A621AE21CE21CF21D221D421F4-22FF2308-230B23202321237C239B-23B323DC-23E125B725C125F8-25FF266F27C0-27C427C7-27CA27CC27D0-27E527F0-27FF2900-29822999-29D729DC-29FB29FE-2AFF2B30-2B442B47-2B4CFB29FE62FE64-FE66FF0BFF1C-FF1EFF5CFF5EFFE2FFE9-FFEC", + Sc: "002400A2-00A5060B09F209F309FB0AF10BF90E3F17DB20A0-20B8A838FDFCFE69FF04FFE0FFE1FFE5FFE6", + Sk: "005E006000A800AF00B400B802C2-02C502D2-02DF02E5-02EB02ED02EF-02FF0375038403851FBD1FBF-1FC11FCD-1FCF1FDD-1FDF1FED-1FEF1FFD1FFE309B309CA700-A716A720A721A789A78AFF3EFF40FFE3", + So: "00A600A700A900AE00B000B60482060E060F06E906FD06FE07F609FA0B700BF3-0BF80BFA0C7F0CF10CF20D790F01-0F030F13-0F170F1A-0F1F0F340F360F380FBE-0FC50FC7-0FCC0FCE0FCF0FD5-0FD8109E109F13601390-1399194019E0-19FF1B61-1B6A1B74-1B7C210021012103-21062108210921142116-2118211E-2123212521272129212E213A213B214A214C214D214F2195-2199219C-219F21A121A221A421A521A7-21AD21AF-21CD21D021D121D321D5-21F32300-2307230C-231F2322-2328232B-237B237D-239A23B4-23DB23E2-23E82400-24262440-244A249C-24E92500-25B625B8-25C025C2-25F72600-266E2670-26CD26CF-26E126E326E8-26FF2701-27042706-2709270C-27272729-274B274D274F-27522756-275E2761-276727942798-27AF27B1-27BE2800-28FF2B00-2B2F2B452B462B50-2B592CE5-2CEA2E80-2E992E9B-2EF32F00-2FD52FF0-2FFB300430123013302030363037303E303F319031913196-319F31C0-31E33200-321E322A-32503260-327F328A-32B032C0-32FE3300-33FF4DC0-4DFFA490-A4C6A828-A82BA836A837A839AA77-AA79FDFDFFE4FFE8FFEDFFEEFFFCFFFD", + Z: "002000A01680180E2000-200A20282029202F205F3000", + Zs: "002000A01680180E2000-200A202F205F3000", + Zl: "2028", + Zp: "2029", + C: "0000-001F007F-009F00AD03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-0605061C061D0620065F06DD070E070F074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-137F139A-139F13F5-13FF169D-169F16F1-16FF170D1715-171F1737-173F1754-175F176D17711774-177F17B417B517DE17DF17EA-17EF17FA-17FF180F181A-181F1878-187F18AB-18AF18F6-18FF191D-191F192C-192F193C-193F1941-1943196E196F1975-197F19AC-19AF19CA-19CF19DB-19DD1A1C1A1D1A5F1A7D1A7E1A8A-1A8F1A9A-1A9F1AAE-1AFF1B4C-1B4F1B7D-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF200B-200F202A-202E2060-206F20722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-F8FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFD-FF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFFBFFFEFFFF", + Cc: "0000-001F007F-009F", + Cf: "00AD0600-060306DD070F17B417B5200B-200F202A-202E2060-2064206A-206FFEFFFFF9-FFFB", + Co: "E000-F8FF", + Cs: "D800-DFFF", + Cn: "03780379037F-0383038B038D03A20526-05300557055805600588058B-059005C8-05CF05EB-05EF05F5-05FF06040605061C061D0620065F070E074B074C07B2-07BF07FB-07FF082E082F083F-08FF093A093B094F095609570973-097809800984098D098E0991099209A909B109B3-09B509BA09BB09C509C609C909CA09CF-09D609D8-09DB09DE09E409E509FC-0A000A040A0B-0A0E0A110A120A290A310A340A370A3A0A3B0A3D0A43-0A460A490A4A0A4E-0A500A52-0A580A5D0A5F-0A650A76-0A800A840A8E0A920AA90AB10AB40ABA0ABB0AC60ACA0ACE0ACF0AD1-0ADF0AE40AE50AF00AF2-0B000B040B0D0B0E0B110B120B290B310B340B3A0B3B0B450B460B490B4A0B4E-0B550B58-0B5B0B5E0B640B650B72-0B810B840B8B-0B8D0B910B96-0B980B9B0B9D0BA0-0BA20BA5-0BA70BAB-0BAD0BBA-0BBD0BC3-0BC50BC90BCE0BCF0BD1-0BD60BD8-0BE50BFB-0C000C040C0D0C110C290C340C3A-0C3C0C450C490C4E-0C540C570C5A-0C5F0C640C650C70-0C770C800C810C840C8D0C910CA90CB40CBA0CBB0CC50CC90CCE-0CD40CD7-0CDD0CDF0CE40CE50CF00CF3-0D010D040D0D0D110D290D3A-0D3C0D450D490D4E-0D560D58-0D5F0D640D650D76-0D780D800D810D840D97-0D990DB20DBC0DBE0DBF0DC7-0DC90DCB-0DCE0DD50DD70DE0-0DF10DF5-0E000E3B-0E3E0E5C-0E800E830E850E860E890E8B0E8C0E8E-0E930E980EA00EA40EA60EA80EA90EAC0EBA0EBE0EBF0EC50EC70ECE0ECF0EDA0EDB0EDE-0EFF0F480F6D-0F700F8C-0F8F0F980FBD0FCD0FD9-0FFF10C6-10CF10FD-10FF1249124E124F12571259125E125F1289128E128F12B112B612B712BF12C112C612C712D7131113161317135B-135E137D-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-1B7F1BAB-1BAD1BBA-1BFF1C38-1C3A1C4A-1C4C1C80-1CCF1CF3-1CFF1DE7-1DFC1F161F171F1E1F1F1F461F471F4E1F4F1F581F5A1F5C1F5E1F7E1F7F1FB51FC51FD41FD51FDC1FF01FF11FF51FFF2065-206920722073208F2095-209F20B9-20CF20F1-20FF218A-218F23E9-23FF2427-243F244B-245F26CE26E226E4-26E727002705270A270B2728274C274E2753-2755275F27602795-279727B027BF27CB27CD-27CF2B4D-2B4F2B5A-2BFF2C2F2C5F2CF2-2CF82D26-2D2F2D66-2D6E2D70-2D7F2D97-2D9F2DA72DAF2DB72DBF2DC72DCF2DD72DDF2E32-2E7F2E9A2EF4-2EFF2FD6-2FEF2FFC-2FFF3040309730983100-3104312E-3130318F31B8-31BF31E4-31EF321F32FF4DB6-4DBF9FCC-9FFFA48D-A48FA4C7-A4CFA62C-A63FA660A661A674-A67BA698-A69FA6F8-A6FFA78D-A7FAA82C-A82FA83A-A83FA878-A87FA8C5-A8CDA8DA-A8DFA8FC-A8FFA954-A95EA97D-A97FA9CEA9DA-A9DDA9E0-A9FFAA37-AA3FAA4EAA4FAA5AAA5BAA7C-AA7FAAC3-AADAAAE0-ABBFABEEABEFABFA-ABFFD7A4-D7AFD7C7-D7CAD7FC-D7FFFA2EFA2FFA6EFA6FFADA-FAFFFB07-FB12FB18-FB1CFB37FB3DFB3FFB42FB45FBB2-FBD2FD40-FD4FFD90FD91FDC8-FDEFFDFEFDFFFE1A-FE1FFE27-FE2FFE53FE67FE6C-FE6FFE75FEFDFEFEFF00FFBF-FFC1FFC8FFC9FFD0FFD1FFD8FFD9FFDD-FFDFFFE7FFEF-FFF8FFFEFFFF" +}); + +function addUnicodePackage (pack) { + var codePoint = /\w{4}/g; + for (var name in pack) + exports.packages[name] = pack[name].replace(codePoint, "\\u$&"); +}; + +}); + +define("ace/token_iterator",["require","exports","module"], function(require, exports, module) { +"use strict"; +var TokenIterator = function(session, initialRow, initialColumn) { + this.$session = session; + this.$row = initialRow; + this.$rowTokens = session.getTokens(initialRow); + + var token = session.getTokenAt(initialRow, initialColumn); + this.$tokenIndex = token ? token.index : -1; +}; + +(function() { + this.stepBackward = function() { + this.$tokenIndex -= 1; + + while (this.$tokenIndex < 0) { + this.$row -= 1; + if (this.$row < 0) { + this.$row = 0; + return null; + } + + this.$rowTokens = this.$session.getTokens(this.$row); + this.$tokenIndex = this.$rowTokens.length - 1; + } + + return this.$rowTokens[this.$tokenIndex]; + }; + this.stepForward = function() { + this.$tokenIndex += 1; + var rowCount; + while (this.$tokenIndex >= this.$rowTokens.length) { + this.$row += 1; + if (!rowCount) + rowCount = this.$session.getLength(); + if (this.$row >= rowCount) { + this.$row = rowCount - 1; + return null; + } + + this.$rowTokens = this.$session.getTokens(this.$row); + this.$tokenIndex = 0; + } + + return this.$rowTokens[this.$tokenIndex]; + }; + this.getCurrentToken = function () { + return this.$rowTokens[this.$tokenIndex]; + }; + this.getCurrentTokenRow = function () { + return this.$row; + }; + this.getCurrentTokenColumn = function() { + var rowTokens = this.$rowTokens; + var tokenIndex = this.$tokenIndex; + var column = rowTokens[tokenIndex].start; + if (column !== undefined) + return column; + + column = 0; + while (tokenIndex > 0) { + tokenIndex -= 1; + column += rowTokens[tokenIndex].value.length; + } + + return column; + }; + +}).call(TokenIterator.prototype); + +exports.TokenIterator = TokenIterator; +}); + +define("ace/mode/text",["require","exports","module","ace/tokenizer","ace/mode/text_highlight_rules","ace/mode/behaviour","ace/unicode","ace/lib/lang","ace/token_iterator","ace/range"], function(require, exports, module) { +"use strict"; + +var Tokenizer = require("../tokenizer").Tokenizer; +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; +var Behaviour = require("./behaviour").Behaviour; +var unicode = require("../unicode"); +var lang = require("../lib/lang"); +var TokenIterator = require("../token_iterator").TokenIterator; +var Range = require("../range").Range; + +var Mode = function() { + this.HighlightRules = TextHighlightRules; + this.$behaviour = new Behaviour(); +}; + +(function() { + + this.tokenRe = new RegExp("^[" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\\$_]+", "g" + ); + + this.nonTokenRe = new RegExp("^(?:[^" + + unicode.packages.L + + unicode.packages.Mn + unicode.packages.Mc + + unicode.packages.Nd + + unicode.packages.Pc + "\\$_]|\\s])+", "g" + ); + + this.getTokenizer = function() { + if (!this.$tokenizer) { + this.$highlightRules = this.$highlightRules || new this.HighlightRules(); + this.$tokenizer = new Tokenizer(this.$highlightRules.getRules()); + } + return this.$tokenizer; + }; + + this.lineCommentStart = ""; + this.blockComment = ""; + + this.toggleCommentLines = function(state, session, startRow, endRow) { + var doc = session.doc; + + var ignoreBlankLines = true; + var shouldRemove = true; + var minIndent = Infinity; + var tabSize = session.getTabSize(); + var insertAtTabStop = false; + + if (!this.lineCommentStart) { + if (!this.blockComment) + return false; + var lineCommentStart = this.blockComment.start; + var lineCommentEnd = this.blockComment.end; + var regexpStart = new RegExp("^(\\s*)(?:" + lang.escapeRegExp(lineCommentStart) + ")"); + var regexpEnd = new RegExp("(?:" + lang.escapeRegExp(lineCommentEnd) + ")\\s*$"); + + var comment = function(line, i) { + if (testRemove(line, i)) + return; + if (!ignoreBlankLines || /\S/.test(line)) { + doc.insertInLine({row: i, column: line.length}, lineCommentEnd); + doc.insertInLine({row: i, column: minIndent}, lineCommentStart); + } + }; + + var uncomment = function(line, i) { + var m; + if (m = line.match(regexpEnd)) + doc.removeInLine(i, line.length - m[0].length, line.length); + if (m = line.match(regexpStart)) + doc.removeInLine(i, m[1].length, m[0].length); + }; + + var testRemove = function(line, row) { + if (regexpStart.test(line)) + return true; + var tokens = session.getTokens(row); + for (var i = 0; i < tokens.length; i++) { + if (tokens[i].type === 'comment') + return true; + } + }; + } else { + if (Array.isArray(this.lineCommentStart)) { + var regexpStart = this.lineCommentStart.map(lang.escapeRegExp).join("|"); + var lineCommentStart = this.lineCommentStart[0]; + } else { + var regexpStart = lang.escapeRegExp(this.lineCommentStart); + var lineCommentStart = this.lineCommentStart; + } + regexpStart = new RegExp("^(\\s*)(?:" + regexpStart + ") ?"); + + insertAtTabStop = session.getUseSoftTabs(); + + var uncomment = function(line, i) { + var m = line.match(regexpStart); + if (!m) return; + var start = m[1].length, end = m[0].length; + if (!shouldInsertSpace(line, start, end) && m[0][end - 1] == " ") + end--; + doc.removeInLine(i, start, end); + }; + var commentWithSpace = lineCommentStart + " "; + var comment = function(line, i) { + if (!ignoreBlankLines || /\S/.test(line)) { + if (shouldInsertSpace(line, minIndent, minIndent)) + doc.insertInLine({row: i, column: minIndent}, commentWithSpace); + else + doc.insertInLine({row: i, column: minIndent}, lineCommentStart); + } + }; + var testRemove = function(line, i) { + return regexpStart.test(line); + }; + + var shouldInsertSpace = function(line, before, after) { + var spaces = 0; + while (before-- && line.charAt(before) == " ") + spaces++; + if (spaces % tabSize != 0) + return false; + var spaces = 0; + while (line.charAt(after++) == " ") + spaces++; + if (tabSize > 2) + return spaces % tabSize != tabSize - 1; + else + return spaces % tabSize == 0; + return true; + }; + } + + function iter(fun) { + for (var i = startRow; i <= endRow; i++) + fun(doc.getLine(i), i); + } + + + var minEmptyLength = Infinity; + iter(function(line, i) { + var indent = line.search(/\S/); + if (indent !== -1) { + if (indent < minIndent) + minIndent = indent; + if (shouldRemove && !testRemove(line, i)) + shouldRemove = false; + } else if (minEmptyLength > line.length) { + minEmptyLength = line.length; + } + }); + + if (minIndent == Infinity) { + minIndent = minEmptyLength; + ignoreBlankLines = false; + shouldRemove = false; + } + + if (insertAtTabStop && minIndent % tabSize != 0) + minIndent = Math.floor(minIndent / tabSize) * tabSize; + + iter(shouldRemove ? uncomment : comment); + }; + + this.toggleBlockComment = function(state, session, range, cursor) { + var comment = this.blockComment; + if (!comment) + return; + if (!comment.start && comment[0]) + comment = comment[0]; + + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + + var sel = session.selection; + var initialRange = session.selection.toOrientedRange(); + var startRow, colDiff; + + if (token && /comment/.test(token.type)) { + var startRange, endRange; + while (token && /comment/.test(token.type)) { + var i = token.value.indexOf(comment.start); + if (i != -1) { + var row = iterator.getCurrentTokenRow(); + var column = iterator.getCurrentTokenColumn() + i; + startRange = new Range(row, column, row, column + comment.start.length); + break; + } + token = iterator.stepBackward(); + } + + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + while (token && /comment/.test(token.type)) { + var i = token.value.indexOf(comment.end); + if (i != -1) { + var row = iterator.getCurrentTokenRow(); + var column = iterator.getCurrentTokenColumn() + i; + endRange = new Range(row, column, row, column + comment.end.length); + break; + } + token = iterator.stepForward(); + } + if (endRange) + session.remove(endRange); + if (startRange) { + session.remove(startRange); + startRow = startRange.start.row; + colDiff = -comment.start.length; + } + } else { + colDiff = comment.start.length; + startRow = range.start.row; + session.insert(range.end, comment.end); + session.insert(range.start, comment.start); + } + if (initialRange.start.row == startRow) + initialRange.start.column += colDiff; + if (initialRange.end.row == startRow) + initialRange.end.column += colDiff; + session.selection.fromOrientedRange(initialRange); + }; + + this.getNextLineIndent = function(state, line, tab) { + return this.$getIndent(line); + }; + + this.checkOutdent = function(state, line, input) { + return false; + }; + + this.autoOutdent = function(state, doc, row) { + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + + this.createWorker = function(session) { + return null; + }; + + this.createModeDelegates = function (mapping) { + this.$embeds = []; + this.$modes = {}; + for (var i in mapping) { + if (mapping[i]) { + this.$embeds.push(i); + this.$modes[i] = new mapping[i](); + } + } + + var delegations = ['toggleBlockComment', 'toggleCommentLines', 'getNextLineIndent', + 'checkOutdent', 'autoOutdent', 'transformAction', 'getCompletions']; + + for (var i = 0; i < delegations.length; i++) { + (function(scope) { + var functionName = delegations[i]; + var defaultHandler = scope[functionName]; + scope[delegations[i]] = function() { + return this.$delegator(functionName, arguments, defaultHandler); + }; + } (this)); + } + }; + + this.$delegator = function(method, args, defaultHandler) { + var state = args[0]; + if (typeof state != "string") + state = state[0]; + for (var i = 0; i < this.$embeds.length; i++) { + if (!this.$modes[this.$embeds[i]]) continue; + + var split = state.split(this.$embeds[i]); + if (!split[0] && split[1]) { + args[0] = split[1]; + var mode = this.$modes[this.$embeds[i]]; + return mode[method].apply(mode, args); + } + } + var ret = defaultHandler.apply(this, args); + return defaultHandler ? ret : undefined; + }; + + this.transformAction = function(state, action, editor, session, param) { + if (this.$behaviour) { + var behaviours = this.$behaviour.getBehaviours(); + for (var key in behaviours) { + if (behaviours[key][action]) { + var ret = behaviours[key][action].apply(this, arguments); + if (ret) { + return ret; + } + } + } + } + }; + + this.getKeywords = function(append) { + if (!this.completionKeywords) { + var rules = this.$tokenizer.rules; + var completionKeywords = []; + for (var rule in rules) { + var ruleItr = rules[rule]; + for (var r = 0, l = ruleItr.length; r < l; r++) { + if (typeof ruleItr[r].token === "string") { + if (/keyword|support|storage/.test(ruleItr[r].token)) + completionKeywords.push(ruleItr[r].regex); + } + else if (typeof ruleItr[r].token === "object") { + for (var a = 0, aLength = ruleItr[r].token.length; a < aLength; a++) { + if (/keyword|support|storage/.test(ruleItr[r].token[a])) { + var rule = ruleItr[r].regex.match(/\(.+?\)/g)[a]; + completionKeywords.push(rule.substr(1, rule.length - 2)); + } + } + } + } + } + this.completionKeywords = completionKeywords; + } + if (!append) + return this.$keywordList; + return completionKeywords.concat(this.$keywordList || []); + }; + + this.$createKeywordList = function() { + if (!this.$highlightRules) + this.getTokenizer(); + return this.$keywordList = this.$highlightRules.$keywordList || []; + }; + + this.getCompletions = function(state, session, pos, prefix) { + var keywords = this.$keywordList || this.$createKeywordList(); + return keywords.map(function(word) { + return { + name: word, + value: word, + score: 0, + meta: "keyword" + }; + }); + }; + + this.$id = "ace/mode/text"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); + +define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; + +var Anchor = exports.Anchor = function(doc, row, column) { + this.$onChange = this.onChange.bind(this); + this.attach(doc); + + if (typeof column == "undefined") + this.setPosition(row.row, row.column); + else + this.setPosition(row, column); +}; + +(function() { + + oop.implement(this, EventEmitter); + this.getPosition = function() { + return this.$clipPositionToDocument(this.row, this.column); + }; + this.getDocument = function() { + return this.document; + }; + this.$insertRight = false; + this.onChange = function(e) { + var delta = e.data; + var range = delta.range; + + if (range.start.row == range.end.row && range.start.row != this.row) + return; + + if (range.start.row > this.row) + return; + + if (range.start.row == this.row && range.start.column > this.column) + return; + + var row = this.row; + var column = this.column; + var start = range.start; + var end = range.end; + + if (delta.action === "insertText") { + if (start.row === row && start.column <= column) { + if (start.column === column && this.$insertRight) { + } else if (start.row === end.row) { + column += end.column - start.column; + } else { + column -= start.column; + row += end.row - start.row; + } + } else if (start.row !== end.row && start.row < row) { + row += end.row - start.row; + } + } else if (delta.action === "insertLines") { + if (start.row === row && column === 0 && this.$insertRight) { + } + else if (start.row <= row) { + row += end.row - start.row; + } + } else if (delta.action === "removeText") { + if (start.row === row && start.column < column) { + if (end.column >= column) + column = start.column; + else + column = Math.max(0, column - (end.column - start.column)); + + } else if (start.row !== end.row && start.row < row) { + if (end.row === row) + column = Math.max(0, column - end.column) + start.column; + row -= (end.row - start.row); + } else if (end.row === row) { + row -= end.row - start.row; + column = Math.max(0, column - end.column) + start.column; + } + } else if (delta.action == "removeLines") { + if (start.row <= row) { + if (end.row <= row) + row -= end.row - start.row; + else { + row = start.row; + column = 0; + } + } + } + + this.setPosition(row, column, true); + }; + this.setPosition = function(row, column, noClip) { + var pos; + if (noClip) { + pos = { + row: row, + column: column + }; + } else { + pos = this.$clipPositionToDocument(row, column); + } + + if (this.row == pos.row && this.column == pos.column) + return; + + var old = { + row: this.row, + column: this.column + }; + + this.row = pos.row; + this.column = pos.column; + this._signal("change", { + old: old, + value: pos + }); + }; + this.detach = function() { + this.document.removeEventListener("change", this.$onChange); + }; + this.attach = function(doc) { + this.document = doc || this.document; + this.document.on("change", this.$onChange); + }; + this.$clipPositionToDocument = function(row, column) { + var pos = {}; + + if (row >= this.document.getLength()) { + pos.row = Math.max(0, this.document.getLength() - 1); + pos.column = this.document.getLine(pos.row).length; + } + else if (row < 0) { + pos.row = 0; + pos.column = 0; + } + else { + pos.row = row; + pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); + } + + if (column < 0) + pos.column = 0; + + return pos; + }; + +}).call(Anchor.prototype); + +}); + +define("ace/document",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/range","ace/anchor"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var Range = require("./range").Range; +var Anchor = require("./anchor").Anchor; + +var Document = function(text) { + this.$lines = []; + if (text.length === 0) { + this.$lines = [""]; + } else if (Array.isArray(text)) { + this._insertLines(0, text); + } else { + this.insert({row: 0, column:0}, text); + } +}; + +(function() { + + oop.implement(this, EventEmitter); + this.setValue = function(text) { + var len = this.getLength(); + this.remove(new Range(0, 0, len, this.getLine(len-1).length)); + this.insert({row: 0, column:0}, text); + }; + this.getValue = function() { + return this.getAllLines().join(this.getNewLineCharacter()); + }; + this.createAnchor = function(row, column) { + return new Anchor(this, row, column); + }; + if ("aaa".split(/a/).length === 0) + this.$split = function(text) { + return text.replace(/\r\n|\r/g, "\n").split("\n"); + }; + else + this.$split = function(text) { + return text.split(/\r\n|\r|\n/); + }; + + + this.$detectNewLine = function(text) { + var match = text.match(/^.*?(\r\n|\r|\n)/m); + this.$autoNewLine = match ? match[1] : "\n"; + this._signal("changeNewLineMode"); + }; + this.getNewLineCharacter = function() { + switch (this.$newLineMode) { + case "windows": + return "\r\n"; + case "unix": + return "\n"; + default: + return this.$autoNewLine || "\n"; + } + }; + + this.$autoNewLine = ""; + this.$newLineMode = "auto"; + this.setNewLineMode = function(newLineMode) { + if (this.$newLineMode === newLineMode) + return; + + this.$newLineMode = newLineMode; + this._signal("changeNewLineMode"); + }; + this.getNewLineMode = function() { + return this.$newLineMode; + }; + this.isNewLine = function(text) { + return (text == "\r\n" || text == "\r" || text == "\n"); + }; + this.getLine = function(row) { + return this.$lines[row] || ""; + }; + this.getLines = function(firstRow, lastRow) { + return this.$lines.slice(firstRow, lastRow + 1); + }; + this.getAllLines = function() { + return this.getLines(0, this.getLength()); + }; + this.getLength = function() { + return this.$lines.length; + }; + this.getTextRange = function(range) { + if (range.start.row == range.end.row) { + return this.getLine(range.start.row) + .substring(range.start.column, range.end.column); + } + var lines = this.getLines(range.start.row, range.end.row); + lines[0] = (lines[0] || "").substring(range.start.column); + var l = lines.length - 1; + if (range.end.row - range.start.row == l) + lines[l] = lines[l].substring(0, range.end.column); + return lines.join(this.getNewLineCharacter()); + }; + + this.$clipPosition = function(position) { + var length = this.getLength(); + if (position.row >= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length-1).length; + } else if (position.row < 0) + position.row = 0; + return position; + }; + this.insert = function(position, text) { + if (!text || text.length === 0) + return position; + + position = this.$clipPosition(position); + if (this.getLength() <= 1) + this.$detectNewLine(text); + + var lines = this.$split(text); + var firstLine = lines.splice(0, 1)[0]; + var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0]; + + position = this.insertInLine(position, firstLine); + if (lastLine !== null) { + position = this.insertNewLine(position); // terminate first line + position = this._insertLines(position.row, lines); + position = this.insertInLine(position, lastLine || ""); + } + return position; + }; + this.insertLines = function(row, lines) { + if (row >= this.getLength()) + return this.insert({row: row, column: 0}, "\n" + lines.join("\n")); + return this._insertLines(Math.max(row, 0), lines); + }; + this._insertLines = function(row, lines) { + if (lines.length == 0) + return {row: row, column: 0}; + while (lines.length > 20000) { + var end = this._insertLines(row, lines.slice(0, 20000)); + lines = lines.slice(20000); + row = end.row; + } + + var args = [row, 0]; + args.push.apply(args, lines); + this.$lines.splice.apply(this.$lines, args); + + var range = new Range(row, 0, row + lines.length, 0); + var delta = { + action: "insertLines", + range: range, + lines: lines + }; + this._signal("change", { data: delta }); + return range.end; + }; + this.insertNewLine = function(position) { + position = this.$clipPosition(position); + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column); + this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length)); + + var end = { + row : position.row + 1, + column : 0 + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: this.getNewLineCharacter() + }; + this._signal("change", { data: delta }); + + return end; + }; + this.insertInLine = function(position, text) { + if (text.length == 0) + return position; + + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column) + text + + line.substring(position.column); + + var end = { + row : position.row, + column : position.column + text.length + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: text + }; + this._signal("change", { data: delta }); + + return end; + }; + this.remove = function(range) { + if (!(range instanceof Range)) + range = Range.fromPoints(range.start, range.end); + range.start = this.$clipPosition(range.start); + range.end = this.$clipPosition(range.end); + + if (range.isEmpty()) + return range.start; + + var firstRow = range.start.row; + var lastRow = range.end.row; + + if (range.isMultiLine()) { + var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1; + var lastFullRow = lastRow - 1; + + if (range.end.column > 0) + this.removeInLine(lastRow, 0, range.end.column); + + if (lastFullRow >= firstFullRow) + this._removeLines(firstFullRow, lastFullRow); + + if (firstFullRow != firstRow) { + this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length); + this.removeNewLine(range.start.row); + } + } + else { + this.removeInLine(firstRow, range.start.column, range.end.column); + } + return range.start; + }; + this.removeInLine = function(row, startColumn, endColumn) { + if (startColumn == endColumn) + return; + + var range = new Range(row, startColumn, row, endColumn); + var line = this.getLine(row); + var removed = line.substring(startColumn, endColumn); + var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length); + this.$lines.splice(row, 1, newLine); + + var delta = { + action: "removeText", + range: range, + text: removed + }; + this._signal("change", { data: delta }); + return range.start; + }; + this.removeLines = function(firstRow, lastRow) { + if (firstRow < 0 || lastRow >= this.getLength()) + return this.remove(new Range(firstRow, 0, lastRow + 1, 0)); + return this._removeLines(firstRow, lastRow); + }; + + this._removeLines = function(firstRow, lastRow) { + var range = new Range(firstRow, 0, lastRow + 1, 0); + var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1); + + var delta = { + action: "removeLines", + range: range, + nl: this.getNewLineCharacter(), + lines: removed + }; + this._signal("change", { data: delta }); + return removed; + }; + this.removeNewLine = function(row) { + var firstLine = this.getLine(row); + var secondLine = this.getLine(row+1); + + var range = new Range(row, firstLine.length, row+1, 0); + var line = firstLine + secondLine; + + this.$lines.splice(row, 2, line); + + var delta = { + action: "removeText", + range: range, + text: this.getNewLineCharacter() + }; + this._signal("change", { data: delta }); + }; + this.replace = function(range, text) { + if (!(range instanceof Range)) + range = Range.fromPoints(range.start, range.end); + if (text.length == 0 && range.isEmpty()) + return range.start; + if (text == this.getTextRange(range)) + return range.end; + + this.remove(range); + if (text) { + var end = this.insert(range.start, text); + } + else { + end = range.start; + } + + return end; + }; + this.applyDeltas = function(deltas) { + for (var i=0; i=0; i--) { + var delta = deltas[i]; + + var range = Range.fromPoints(delta.range.start, delta.range.end); + + if (delta.action == "insertLines") + this._removeLines(range.start.row, range.end.row - 1); + else if (delta.action == "insertText") + this.remove(range); + else if (delta.action == "removeLines") + this._insertLines(range.start.row, delta.lines); + else if (delta.action == "removeText") + this.insert(range.start, delta.text); + } + }; + this.indexToPosition = function(index, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + for (var i = startRow || 0, l = lines.length; i < l; i++) { + index -= lines[i].length + newlineLength; + if (index < 0) + return {row: i, column: index + lines[i].length + newlineLength}; + } + return {row: l-1, column: lines[l-1].length}; + }; + this.positionToIndex = function(pos, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + var index = 0; + var row = Math.min(pos.row, lines.length); + for (var i = startRow || 0; i < row; ++i) + index += lines[i].length + newlineLength; + + return index + pos.column; + }; + +}).call(Document.prototype); + +exports.Document = Document; +}); + +define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; + +var BackgroundTokenizer = function(tokenizer, editor) { + this.running = false; + this.lines = []; + this.states = []; + this.currentLine = 0; + this.tokenizer = tokenizer; + + var self = this; + + this.$worker = function() { + if (!self.running) { return; } + + var workerStart = new Date(); + var currentLine = self.currentLine; + var endLine = -1; + var doc = self.doc; + + while (self.lines[currentLine]) + currentLine++; + + var startLine = currentLine; + + var len = doc.getLength(); + var processedLines = 0; + self.running = false; + while (currentLine < len) { + self.$tokenizeRow(currentLine); + endLine = currentLine; + do { + currentLine++; + } while (self.lines[currentLine]); + processedLines ++; + if ((processedLines % 5 === 0) && (new Date() - workerStart) > 20) { + self.running = setTimeout(self.$worker, 20); + break; + } + } + self.currentLine = currentLine; + + if (startLine <= endLine) + self.fireUpdateEvent(startLine, endLine); + }; +}; + +(function(){ + + oop.implement(this, EventEmitter); + this.setTokenizer = function(tokenizer) { + this.tokenizer = tokenizer; + this.lines = []; + this.states = []; + + this.start(0); + }; + this.setDocument = function(doc) { + this.doc = doc; + this.lines = []; + this.states = []; + + this.stop(); + }; + this.fireUpdateEvent = function(firstRow, lastRow) { + var data = { + first: firstRow, + last: lastRow + }; + this._signal("update", {data: data}); + }; + this.start = function(startRow) { + this.currentLine = Math.min(startRow || 0, this.currentLine, this.doc.getLength()); + this.lines.splice(this.currentLine, this.lines.length); + this.states.splice(this.currentLine, this.states.length); + + this.stop(); + this.running = setTimeout(this.$worker, 700); + }; + + this.scheduleStart = function() { + if (!this.running) + this.running = setTimeout(this.$worker, 700); + } + + this.$updateOnChange = function(delta) { + var range = delta.range; + var startRow = range.start.row; + var len = range.end.row - startRow; + + if (len === 0) { + this.lines[startRow] = null; + } else if (delta.action == "removeText" || delta.action == "removeLines") { + this.lines.splice(startRow, len + 1, null); + this.states.splice(startRow, len + 1, null); + } else { + var args = Array(len + 1); + args.unshift(startRow, 1); + this.lines.splice.apply(this.lines, args); + this.states.splice.apply(this.states, args); + } + + this.currentLine = Math.min(startRow, this.currentLine, this.doc.getLength()); + + this.stop(); + }; + this.stop = function() { + if (this.running) + clearTimeout(this.running); + this.running = false; + }; + this.getTokens = function(row) { + return this.lines[row] || this.$tokenizeRow(row); + }; + this.getState = function(row) { + if (this.currentLine == row) + this.$tokenizeRow(row); + return this.states[row] || "start"; + }; + + this.$tokenizeRow = function(row) { + var line = this.doc.getLine(row); + var state = this.states[row - 1]; + + var data = this.tokenizer.getLineTokens(line, state, row); + + if (this.states[row] + "" !== data.state + "") { + this.states[row] = data.state; + this.lines[row + 1] = null; + if (this.currentLine > row + 1) + this.currentLine = row + 1; + } else if (this.currentLine == row) { + this.currentLine = row + 1; + } + + return this.lines[row] = data.tokens; + }; + +}).call(BackgroundTokenizer.prototype); + +exports.BackgroundTokenizer = BackgroundTokenizer; +}); + +define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(require, exports, module) { +"use strict"; + +var lang = require("./lib/lang"); +var oop = require("./lib/oop"); +var Range = require("./range").Range; + +var SearchHighlight = function(regExp, clazz, type) { + this.setRegexp(regExp); + this.clazz = clazz; + this.type = type || "text"; +}; + +(function() { + this.MAX_RANGES = 500; + + this.setRegexp = function(regExp) { + if (this.regExp+"" == regExp+"") + return; + this.regExp = regExp; + this.cache = []; + }; + + this.update = function(html, markerLayer, session, config) { + if (!this.regExp) + return; + var start = config.firstRow, end = config.lastRow; + + for (var i = start; i <= end; i++) { + var ranges = this.cache[i]; + if (ranges == null) { + ranges = lang.getMatchOffsets(session.getLine(i), this.regExp); + if (ranges.length > this.MAX_RANGES) + ranges = ranges.slice(0, this.MAX_RANGES); + ranges = ranges.map(function(match) { + return new Range(i, match.offset, i, match.offset + match.length); + }); + this.cache[i] = ranges.length ? ranges : ""; + } + + for (var j = ranges.length; j --; ) { + markerLayer.drawSingleLineMarker( + html, ranges[j].toScreenRange(session), this.clazz, config); + } + } + }; + +}).call(SearchHighlight.prototype); + +exports.SearchHighlight = SearchHighlight; +}); + +define("ace/edit_session/fold_line",["require","exports","module","ace/range"], function(require, exports, module) { +"use strict"; + +var Range = require("../range").Range; +function FoldLine(foldData, folds) { + this.foldData = foldData; + if (Array.isArray(folds)) { + this.folds = folds; + } else { + folds = this.folds = [ folds ]; + } + + var last = folds[folds.length - 1]; + this.range = new Range(folds[0].start.row, folds[0].start.column, + last.end.row, last.end.column); + this.start = this.range.start; + this.end = this.range.end; + + this.folds.forEach(function(fold) { + fold.setFoldLine(this); + }, this); +} + +(function() { + this.shiftRow = function(shift) { + this.start.row += shift; + this.end.row += shift; + this.folds.forEach(function(fold) { + fold.start.row += shift; + fold.end.row += shift; + }); + }; + + this.addFold = function(fold) { + if (fold.sameRow) { + if (fold.start.row < this.startRow || fold.endRow > this.endRow) { + throw new Error("Can't add a fold to this FoldLine as it has no connection"); + } + this.folds.push(fold); + this.folds.sort(function(a, b) { + return -a.range.compareEnd(b.start.row, b.start.column); + }); + if (this.range.compareEnd(fold.start.row, fold.start.column) > 0) { + this.end.row = fold.end.row; + this.end.column = fold.end.column; + } else if (this.range.compareStart(fold.end.row, fold.end.column) < 0) { + this.start.row = fold.start.row; + this.start.column = fold.start.column; + } + } else if (fold.start.row == this.end.row) { + this.folds.push(fold); + this.end.row = fold.end.row; + this.end.column = fold.end.column; + } else if (fold.end.row == this.start.row) { + this.folds.unshift(fold); + this.start.row = fold.start.row; + this.start.column = fold.start.column; + } else { + throw new Error("Trying to add fold to FoldRow that doesn't have a matching row"); + } + fold.foldLine = this; + }; + + this.containsRow = function(row) { + return row >= this.start.row && row <= this.end.row; + }; + + this.walk = function(callback, endRow, endColumn) { + var lastEnd = 0, + folds = this.folds, + fold, + cmp, stop, isNewRow = true; + + if (endRow == null) { + endRow = this.end.row; + endColumn = this.end.column; + } + + for (var i = 0; i < folds.length; i++) { + fold = folds[i]; + + cmp = fold.range.compareStart(endRow, endColumn); + if (cmp == -1) { + callback(null, endRow, endColumn, lastEnd, isNewRow); + return; + } + + stop = callback(null, fold.start.row, fold.start.column, lastEnd, isNewRow); + stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd); + if (stop || cmp === 0) { + return; + } + isNewRow = !fold.sameRow; + lastEnd = fold.end.column; + } + callback(null, endRow, endColumn, lastEnd, isNewRow); + }; + + this.getNextFoldTo = function(row, column) { + var fold, cmp; + for (var i = 0; i < this.folds.length; i++) { + fold = this.folds[i]; + cmp = fold.range.compareEnd(row, column); + if (cmp == -1) { + return { + fold: fold, + kind: "after" + }; + } else if (cmp === 0) { + return { + fold: fold, + kind: "inside" + }; + } + } + return null; + }; + + this.addRemoveChars = function(row, column, len) { + var ret = this.getNextFoldTo(row, column), + fold, folds; + if (ret) { + fold = ret.fold; + if (ret.kind == "inside" + && fold.start.column != column + && fold.start.row != row) + { + window.console && window.console.log(row, column, fold); + } else if (fold.start.row == row) { + folds = this.folds; + var i = folds.indexOf(fold); + if (i === 0) { + this.start.column += len; + } + for (i; i < folds.length; i++) { + fold = folds[i]; + fold.start.column += len; + if (!fold.sameRow) { + return; + } + fold.end.column += len; + } + this.end.column += len; + } + } + }; + + this.split = function(row, column) { + var pos = this.getNextFoldTo(row, column); + + if (!pos || pos.kind == "inside") + return null; + + var fold = pos.fold; + var folds = this.folds; + var foldData = this.foldData; + + var i = folds.indexOf(fold); + var foldBefore = folds[i - 1]; + this.end.row = foldBefore.end.row; + this.end.column = foldBefore.end.column; + folds = folds.splice(i, folds.length - i); + + var newFoldLine = new FoldLine(foldData, folds); + foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine); + return newFoldLine; + }; + + this.merge = function(foldLineNext) { + var folds = foldLineNext.folds; + for (var i = 0; i < folds.length; i++) { + this.addFold(folds[i]); + } + var foldData = this.foldData; + foldData.splice(foldData.indexOf(foldLineNext), 1); + }; + + this.toString = function() { + var ret = [this.range.toString() + ": [" ]; + + this.folds.forEach(function(fold) { + ret.push(" " + fold.toString()); + }); + ret.push("]"); + return ret.join("\n"); + }; + + this.idxToPosition = function(idx) { + var lastFoldEndColumn = 0; + + for (var i = 0; i < this.folds.length; i++) { + var fold = this.folds[i]; + + idx -= fold.start.column - lastFoldEndColumn; + if (idx < 0) { + return { + row: fold.start.row, + column: fold.start.column + idx + }; + } + + idx -= fold.placeholder.length; + if (idx < 0) { + return fold.start; + } + + lastFoldEndColumn = fold.end.column; + } + + return { + row: this.end.row, + column: this.end.column + idx + }; + }; +}).call(FoldLine.prototype); + +exports.FoldLine = FoldLine; +}); + +define("ace/range_list",["require","exports","module","ace/range"], function(require, exports, module) { +"use strict"; +var Range = require("./range").Range; +var comparePoints = Range.comparePoints; + +var RangeList = function() { + this.ranges = []; +}; + +(function() { + this.comparePoints = comparePoints; + + this.pointIndex = function(pos, excludeEdges, startIndex) { + var list = this.ranges; + + for (var i = startIndex || 0; i < list.length; i++) { + var range = list[i]; + var cmpEnd = comparePoints(pos, range.end); + if (cmpEnd > 0) + continue; + var cmpStart = comparePoints(pos, range.start); + if (cmpEnd === 0) + return excludeEdges && cmpStart !== 0 ? -i-2 : i; + if (cmpStart > 0 || (cmpStart === 0 && !excludeEdges)) + return i; + + return -i-1; + } + return -i - 1; + }; + + this.add = function(range) { + var excludeEdges = !range.isEmpty(); + var startIndex = this.pointIndex(range.start, excludeEdges); + if (startIndex < 0) + startIndex = -startIndex - 1; + + var endIndex = this.pointIndex(range.end, excludeEdges, startIndex); + + if (endIndex < 0) + endIndex = -endIndex - 1; + else + endIndex++; + return this.ranges.splice(startIndex, endIndex - startIndex, range); + }; + + this.addList = function(list) { + var removed = []; + for (var i = list.length; i--; ) { + removed.push.call(removed, this.add(list[i])); + } + return removed; + }; + + this.substractPoint = function(pos) { + var i = this.pointIndex(pos); + + if (i >= 0) + return this.ranges.splice(i, 1); + }; + this.merge = function() { + var removed = []; + var list = this.ranges; + + list = list.sort(function(a, b) { + return comparePoints(a.start, b.start); + }); + + var next = list[0], range; + for (var i = 1; i < list.length; i++) { + range = next; + next = list[i]; + var cmp = comparePoints(range.end, next.start); + if (cmp < 0) + continue; + + if (cmp == 0 && !range.isEmpty() && !next.isEmpty()) + continue; + + if (comparePoints(range.end, next.end) < 0) { + range.end.row = next.end.row; + range.end.column = next.end.column; + } + + list.splice(i, 1); + removed.push(next); + next = range; + i--; + } + + this.ranges = list; + + return removed; + }; + + this.contains = function(row, column) { + return this.pointIndex({row: row, column: column}) >= 0; + }; + + this.containsPoint = function(pos) { + return this.pointIndex(pos) >= 0; + }; + + this.rangeAtPoint = function(pos) { + var i = this.pointIndex(pos); + if (i >= 0) + return this.ranges[i]; + }; + + + this.clipRows = function(startRow, endRow) { + var list = this.ranges; + if (list[0].start.row > endRow || list[list.length - 1].start.row < startRow) + return []; + + var startIndex = this.pointIndex({row: startRow, column: 0}); + if (startIndex < 0) + startIndex = -startIndex - 1; + var endIndex = this.pointIndex({row: endRow, column: 0}, startIndex); + if (endIndex < 0) + endIndex = -endIndex - 1; + + var clipped = []; + for (var i = startIndex; i < endIndex; i++) { + clipped.push(list[i]); + } + return clipped; + }; + + this.removeAll = function() { + return this.ranges.splice(0, this.ranges.length); + }; + + this.attach = function(session) { + if (this.session) + this.detach(); + + this.session = session; + this.onChange = this.$onChange.bind(this); + + this.session.on('change', this.onChange); + }; + + this.detach = function() { + if (!this.session) + return; + this.session.removeListener('change', this.onChange); + this.session = null; + }; + + this.$onChange = function(e) { + var changeRange = e.data.range; + if (e.data.action[0] == "i"){ + var start = changeRange.start; + var end = changeRange.end; + } else { + var end = changeRange.start; + var start = changeRange.end; + } + var startRow = start.row; + var endRow = end.row; + var lineDif = endRow - startRow; + + var colDiff = -start.column + end.column; + var ranges = this.ranges; + + for (var i = 0, n = ranges.length; i < n; i++) { + var r = ranges[i]; + if (r.end.row < startRow) + continue; + if (r.start.row > startRow) + break; + + if (r.start.row == startRow && r.start.column >= start.column ) { + if (r.start.column == start.column && this.$insertRight) { + } else { + r.start.column += colDiff; + r.start.row += lineDif; + } + } + if (r.end.row == startRow && r.end.column >= start.column) { + if (r.end.column == start.column && this.$insertRight) { + continue; + } + if (r.end.column == start.column && colDiff > 0 && i < n - 1) { + if (r.end.column > r.start.column && r.end.column == ranges[i+1].start.column) + r.end.column -= colDiff; + } + r.end.column += colDiff; + r.end.row += lineDif; + } + } + + if (lineDif != 0 && i < n) { + for (; i < n; i++) { + var r = ranges[i]; + r.start.row += lineDif; + r.end.row += lineDif; + } + } + }; + +}).call(RangeList.prototype); + +exports.RangeList = RangeList; +}); + +define("ace/edit_session/fold",["require","exports","module","ace/range","ace/range_list","ace/lib/oop"], function(require, exports, module) { +"use strict"; + +var Range = require("../range").Range; +var RangeList = require("../range_list").RangeList; +var oop = require("../lib/oop") +var Fold = exports.Fold = function(range, placeholder) { + this.foldLine = null; + this.placeholder = placeholder; + this.range = range; + this.start = range.start; + this.end = range.end; + + this.sameRow = range.start.row == range.end.row; + this.subFolds = this.ranges = []; +}; + +oop.inherits(Fold, RangeList); + +(function() { + + this.toString = function() { + return '"' + this.placeholder + '" ' + this.range.toString(); + }; + + this.setFoldLine = function(foldLine) { + this.foldLine = foldLine; + this.subFolds.forEach(function(fold) { + fold.setFoldLine(foldLine); + }); + }; + + this.clone = function() { + var range = this.range.clone(); + var fold = new Fold(range, this.placeholder); + this.subFolds.forEach(function(subFold) { + fold.subFolds.push(subFold.clone()); + }); + fold.collapseChildren = this.collapseChildren; + return fold; + }; + + this.addSubFold = function(fold) { + if (this.range.isEqual(fold)) + return; + + if (!this.range.containsRange(fold)) + throw new Error("A fold can't intersect already existing fold" + fold.range + this.range); + consumeRange(fold, this.start); + + var row = fold.start.row, column = fold.start.column; + for (var i = 0, cmp = -1; i < this.subFolds.length; i++) { + cmp = this.subFolds[i].range.compare(row, column); + if (cmp != 1) + break; + } + var afterStart = this.subFolds[i]; + + if (cmp == 0) + return afterStart.addSubFold(fold); + var row = fold.range.end.row, column = fold.range.end.column; + for (var j = i, cmp = -1; j < this.subFolds.length; j++) { + cmp = this.subFolds[j].range.compare(row, column); + if (cmp != 1) + break; + } + var afterEnd = this.subFolds[j]; + + if (cmp == 0) + throw new Error("A fold can't intersect already existing fold" + fold.range + this.range); + + var consumedFolds = this.subFolds.splice(i, j - i, fold); + fold.setFoldLine(this.foldLine); + + return fold; + }; + + this.restoreRange = function(range) { + return restoreRange(range, this.start); + }; + +}).call(Fold.prototype); + +function consumePoint(point, anchor) { + point.row -= anchor.row; + if (point.row == 0) + point.column -= anchor.column; +} +function consumeRange(range, anchor) { + consumePoint(range.start, anchor); + consumePoint(range.end, anchor); +} +function restorePoint(point, anchor) { + if (point.row == 0) + point.column += anchor.column; + point.row += anchor.row; +} +function restoreRange(range, anchor) { + restorePoint(range.start, anchor); + restorePoint(range.end, anchor); +} + +}); + +define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"], function(require, exports, module) { +"use strict"; + +var Range = require("../range").Range; +var FoldLine = require("./fold_line").FoldLine; +var Fold = require("./fold").Fold; +var TokenIterator = require("../token_iterator").TokenIterator; + +function Folding() { + this.getFoldAt = function(row, column, side) { + var foldLine = this.getFoldLine(row); + if (!foldLine) + return null; + + var folds = foldLine.folds; + for (var i = 0; i < folds.length; i++) { + var fold = folds[i]; + if (fold.range.contains(row, column)) { + if (side == 1 && fold.range.isEnd(row, column)) { + continue; + } else if (side == -1 && fold.range.isStart(row, column)) { + continue; + } + return fold; + } + } + }; + this.getFoldsInRange = function(range) { + var start = range.start; + var end = range.end; + var foldLines = this.$foldData; + var foundFolds = []; + + start.column += 1; + end.column -= 1; + + for (var i = 0; i < foldLines.length; i++) { + var cmp = foldLines[i].range.compareRange(range); + if (cmp == 2) { + continue; + } + else if (cmp == -2) { + break; + } + + var folds = foldLines[i].folds; + for (var j = 0; j < folds.length; j++) { + var fold = folds[j]; + cmp = fold.range.compareRange(range); + if (cmp == -2) { + break; + } else if (cmp == 2) { + continue; + } else + if (cmp == 42) { + break; + } + foundFolds.push(fold); + } + } + start.column -= 1; + end.column += 1; + + return foundFolds; + }; + + this.getFoldsInRangeList = function(ranges) { + if (Array.isArray(ranges)) { + var folds = []; + ranges.forEach(function(range) { + folds = folds.concat(this.getFoldsInRange(range)); + }, this); + } else { + var folds = this.getFoldsInRange(ranges); + } + return folds; + } + this.getAllFolds = function() { + var folds = []; + var foldLines = this.$foldData; + + for (var i = 0; i < foldLines.length; i++) + for (var j = 0; j < foldLines[i].folds.length; j++) + folds.push(foldLines[i].folds[j]); + + return folds; + }; + this.getFoldStringAt = function(row, column, trim, foldLine) { + foldLine = foldLine || this.getFoldLine(row); + if (!foldLine) + return null; + + var lastFold = { + end: { column: 0 } + }; + var str, fold; + for (var i = 0; i < foldLine.folds.length; i++) { + fold = foldLine.folds[i]; + var cmp = fold.range.compareEnd(row, column); + if (cmp == -1) { + str = this + .getLine(fold.start.row) + .substring(lastFold.end.column, fold.start.column); + break; + } + else if (cmp === 0) { + return null; + } + lastFold = fold; + } + if (!str) + str = this.getLine(fold.start.row).substring(lastFold.end.column); + + if (trim == -1) + return str.substring(0, column - lastFold.end.column); + else if (trim == 1) + return str.substring(column - lastFold.end.column); + else + return str; + }; + + this.getFoldLine = function(docRow, startFoldLine) { + var foldData = this.$foldData; + var i = 0; + if (startFoldLine) + i = foldData.indexOf(startFoldLine); + if (i == -1) + i = 0; + for (i; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (foldLine.start.row <= docRow && foldLine.end.row >= docRow) { + return foldLine; + } else if (foldLine.end.row > docRow) { + return null; + } + } + return null; + }; + this.getNextFoldLine = function(docRow, startFoldLine) { + var foldData = this.$foldData; + var i = 0; + if (startFoldLine) + i = foldData.indexOf(startFoldLine); + if (i == -1) + i = 0; + for (i; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (foldLine.end.row >= docRow) { + return foldLine; + } + } + return null; + }; + + this.getFoldedRowCount = function(first, last) { + var foldData = this.$foldData, rowCount = last-first+1; + for (var i = 0; i < foldData.length; i++) { + var foldLine = foldData[i], + end = foldLine.end.row, + start = foldLine.start.row; + if (end >= last) { + if(start < last) { + if(start >= first) + rowCount -= last-start; + else + rowCount = 0;//in one fold + } + break; + } else if(end >= first){ + if (start >= first) //fold inside range + rowCount -= end-start; + else + rowCount -= end-first+1; + } + } + return rowCount; + }; + + this.$addFoldLine = function(foldLine) { + this.$foldData.push(foldLine); + this.$foldData.sort(function(a, b) { + return a.start.row - b.start.row; + }); + return foldLine; + }; + this.addFold = function(placeholder, range) { + var foldData = this.$foldData; + var added = false; + var fold; + + if (placeholder instanceof Fold) + fold = placeholder; + else { + fold = new Fold(range, placeholder); + fold.collapseChildren = range.collapseChildren; + } + this.$clipRangeToDocument(fold.range); + + var startRow = fold.start.row; + var startColumn = fold.start.column; + var endRow = fold.end.row; + var endColumn = fold.end.column; + if (!(startRow < endRow || + startRow == endRow && startColumn <= endColumn - 2)) + throw new Error("The range has to be at least 2 characters width"); + + var startFold = this.getFoldAt(startRow, startColumn, 1); + var endFold = this.getFoldAt(endRow, endColumn, -1); + if (startFold && endFold == startFold) + return startFold.addSubFold(fold); + + if (startFold && !startFold.range.isStart(startRow, startColumn)) + this.removeFold(startFold); + + if (endFold && !endFold.range.isEnd(endRow, endColumn)) + this.removeFold(endFold); + var folds = this.getFoldsInRange(fold.range); + if (folds.length > 0) { + this.removeFolds(folds); + folds.forEach(function(subFold) { + fold.addSubFold(subFold); + }); + } + + for (var i = 0; i < foldData.length; i++) { + var foldLine = foldData[i]; + if (endRow == foldLine.start.row) { + foldLine.addFold(fold); + added = true; + break; + } else if (startRow == foldLine.end.row) { + foldLine.addFold(fold); + added = true; + if (!fold.sameRow) { + var foldLineNext = foldData[i + 1]; + if (foldLineNext && foldLineNext.start.row == endRow) { + foldLine.merge(foldLineNext); + break; + } + } + break; + } else if (endRow <= foldLine.start.row) { + break; + } + } + + if (!added) + foldLine = this.$addFoldLine(new FoldLine(this.$foldData, fold)); + + if (this.$useWrapMode) + this.$updateWrapData(foldLine.start.row, foldLine.start.row); + else + this.$updateRowLengthCache(foldLine.start.row, foldLine.start.row); + this.$modified = true; + this._emit("changeFold", { data: fold, action: "add" }); + + return fold; + }; + + this.addFolds = function(folds) { + folds.forEach(function(fold) { + this.addFold(fold); + }, this); + }; + + this.removeFold = function(fold) { + var foldLine = fold.foldLine; + var startRow = foldLine.start.row; + var endRow = foldLine.end.row; + + var foldLines = this.$foldData; + var folds = foldLine.folds; + if (folds.length == 1) { + foldLines.splice(foldLines.indexOf(foldLine), 1); + } else + if (foldLine.range.isEnd(fold.end.row, fold.end.column)) { + folds.pop(); + foldLine.end.row = folds[folds.length - 1].end.row; + foldLine.end.column = folds[folds.length - 1].end.column; + } else + if (foldLine.range.isStart(fold.start.row, fold.start.column)) { + folds.shift(); + foldLine.start.row = folds[0].start.row; + foldLine.start.column = folds[0].start.column; + } else + if (fold.sameRow) { + folds.splice(folds.indexOf(fold), 1); + } else + { + var newFoldLine = foldLine.split(fold.start.row, fold.start.column); + folds = newFoldLine.folds; + folds.shift(); + newFoldLine.start.row = folds[0].start.row; + newFoldLine.start.column = folds[0].start.column; + } + + if (!this.$updating) { + if (this.$useWrapMode) + this.$updateWrapData(startRow, endRow); + else + this.$updateRowLengthCache(startRow, endRow); + } + this.$modified = true; + this._emit("changeFold", { data: fold, action: "remove" }); + }; + + this.removeFolds = function(folds) { + var cloneFolds = []; + for (var i = 0; i < folds.length; i++) { + cloneFolds.push(folds[i]); + } + + cloneFolds.forEach(function(fold) { + this.removeFold(fold); + }, this); + this.$modified = true; + }; + + this.expandFold = function(fold) { + this.removeFold(fold); + fold.subFolds.forEach(function(subFold) { + fold.restoreRange(subFold); + this.addFold(subFold); + }, this); + if (fold.collapseChildren > 0) { + this.foldAll(fold.start.row+1, fold.end.row, fold.collapseChildren-1); + } + fold.subFolds = []; + }; + + this.expandFolds = function(folds) { + folds.forEach(function(fold) { + this.expandFold(fold); + }, this); + }; + + this.unfold = function(location, expandInner) { + var range, folds; + if (location == null) { + range = new Range(0, 0, this.getLength(), 0); + expandInner = true; + } else if (typeof location == "number") + range = new Range(location, 0, location, this.getLine(location).length); + else if ("row" in location) + range = Range.fromPoints(location, location); + else + range = location; + + folds = this.getFoldsInRangeList(range); + if (expandInner) { + this.removeFolds(folds); + } else { + var subFolds = folds; + while (subFolds.length) { + this.expandFolds(subFolds); + subFolds = this.getFoldsInRangeList(range); + } + } + if (folds.length) + return folds; + }; + this.isRowFolded = function(docRow, startFoldRow) { + return !!this.getFoldLine(docRow, startFoldRow); + }; + + this.getRowFoldEnd = function(docRow, startFoldRow) { + var foldLine = this.getFoldLine(docRow, startFoldRow); + return foldLine ? foldLine.end.row : docRow; + }; + + this.getRowFoldStart = function(docRow, startFoldRow) { + var foldLine = this.getFoldLine(docRow, startFoldRow); + return foldLine ? foldLine.start.row : docRow; + }; + + this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) { + if (startRow == null) + startRow = foldLine.start.row; + if (startColumn == null) + startColumn = 0; + if (endRow == null) + endRow = foldLine.end.row; + if (endColumn == null) + endColumn = this.getLine(endRow).length; + var doc = this.doc; + var textLine = ""; + + foldLine.walk(function(placeholder, row, column, lastColumn) { + if (row < startRow) + return; + if (row == startRow) { + if (column < startColumn) + return; + lastColumn = Math.max(startColumn, lastColumn); + } + + if (placeholder != null) { + textLine += placeholder; + } else { + textLine += doc.getLine(row).substring(lastColumn, column); + } + }, endRow, endColumn); + return textLine; + }; + + this.getDisplayLine = function(row, endColumn, startRow, startColumn) { + var foldLine = this.getFoldLine(row); + + if (!foldLine) { + var line; + line = this.doc.getLine(row); + return line.substring(startColumn || 0, endColumn || line.length); + } else { + return this.getFoldDisplayLine( + foldLine, row, endColumn, startRow, startColumn); + } + }; + + this.$cloneFoldData = function() { + var fd = []; + fd = this.$foldData.map(function(foldLine) { + var folds = foldLine.folds.map(function(fold) { + return fold.clone(); + }); + return new FoldLine(fd, folds); + }); + + return fd; + }; + + this.toggleFold = function(tryToUnfold) { + var selection = this.selection; + var range = selection.getRange(); + var fold; + var bracketPos; + + if (range.isEmpty()) { + var cursor = range.start; + fold = this.getFoldAt(cursor.row, cursor.column); + + if (fold) { + this.expandFold(fold); + return; + } else if (bracketPos = this.findMatchingBracket(cursor)) { + if (range.comparePoint(bracketPos) == 1) { + range.end = bracketPos; + } else { + range.start = bracketPos; + range.start.column++; + range.end.column--; + } + } else if (bracketPos = this.findMatchingBracket({row: cursor.row, column: cursor.column + 1})) { + if (range.comparePoint(bracketPos) == 1) + range.end = bracketPos; + else + range.start = bracketPos; + + range.start.column++; + } else { + range = this.getCommentFoldRange(cursor.row, cursor.column) || range; + } + } else { + var folds = this.getFoldsInRange(range); + if (tryToUnfold && folds.length) { + this.expandFolds(folds); + return; + } else if (folds.length == 1 ) { + fold = folds[0]; + } + } + + if (!fold) + fold = this.getFoldAt(range.start.row, range.start.column); + + if (fold && fold.range.toString() == range.toString()) { + this.expandFold(fold); + return; + } + + var placeholder = "..."; + if (!range.isMultiLine()) { + placeholder = this.getTextRange(range); + if(placeholder.length < 4) + return; + placeholder = placeholder.trim().substring(0, 2) + ".."; + } + + this.addFold(placeholder, range); + }; + + this.getCommentFoldRange = function(row, column, dir) { + var iterator = new TokenIterator(this, row, column); + var token = iterator.getCurrentToken(); + if (token && /^comment|string/.test(token.type)) { + var range = new Range(); + var re = new RegExp(token.type.replace(/\..*/, "\\.")); + if (dir != 1) { + do { + token = iterator.stepBackward(); + } while(token && re.test(token.type)); + iterator.stepForward(); + } + + range.start.row = iterator.getCurrentTokenRow(); + range.start.column = iterator.getCurrentTokenColumn() + 2; + + iterator = new TokenIterator(this, row, column); + + if (dir != -1) { + do { + token = iterator.stepForward(); + } while(token && re.test(token.type)); + token = iterator.stepBackward(); + } else + token = iterator.getCurrentToken(); + + range.end.row = iterator.getCurrentTokenRow(); + range.end.column = iterator.getCurrentTokenColumn() + token.value.length - 2; + return range; + } + }; + + this.foldAll = function(startRow, endRow, depth) { + if (depth == undefined) + depth = 100000; // JSON.stringify doesn't hanle Infinity + var foldWidgets = this.foldWidgets; + if (!foldWidgets) + return; // mode doesn't support folding + endRow = endRow || this.getLength(); + startRow = startRow || 0; + for (var row = startRow; row < endRow; row++) { + if (foldWidgets[row] == null) + foldWidgets[row] = this.getFoldWidget(row); + if (foldWidgets[row] != "start") + continue; + + var range = this.getFoldWidgetRange(row); + if (range && range.isMultiLine() + && range.end.row <= endRow + && range.start.row >= startRow + ) { + row = range.end.row; + try { + var fold = this.addFold("...", range); + if (fold) + fold.collapseChildren = depth; + } catch(e) {} + } + } + }; + this.$foldStyles = { + "manual": 1, + "markbegin": 1, + "markbeginend": 1 + }; + this.$foldStyle = "markbegin"; + this.setFoldStyle = function(style) { + if (!this.$foldStyles[style]) + throw new Error("invalid fold style: " + style + "[" + Object.keys(this.$foldStyles).join(", ") + "]"); + + if (this.$foldStyle == style) + return; + + this.$foldStyle = style; + + if (style == "manual") + this.unfold(); + var mode = this.$foldMode; + this.$setFolding(null); + this.$setFolding(mode); + }; + + this.$setFolding = function(foldMode) { + if (this.$foldMode == foldMode) + return; + + this.$foldMode = foldMode; + + this.off('change', this.$updateFoldWidgets); + this.off('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets); + this._emit("changeAnnotation"); + + if (!foldMode || this.$foldStyle == "manual") { + this.foldWidgets = null; + return; + } + + this.foldWidgets = []; + this.getFoldWidget = foldMode.getFoldWidget.bind(foldMode, this, this.$foldStyle); + this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle); + + this.$updateFoldWidgets = this.updateFoldWidgets.bind(this); + this.$tokenizerUpdateFoldWidgets = this.tokenizerUpdateFoldWidgets.bind(this); + this.on('change', this.$updateFoldWidgets); + this.on('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets); + }; + + this.getParentFoldRangeData = function (row, ignoreCurrent) { + var fw = this.foldWidgets; + if (!fw || (ignoreCurrent && fw[row])) + return {}; + + var i = row - 1, firstRange; + while (i >= 0) { + var c = fw[i]; + if (c == null) + c = fw[i] = this.getFoldWidget(i); + + if (c == "start") { + var range = this.getFoldWidgetRange(i); + if (!firstRange) + firstRange = range; + if (range && range.end.row >= row) + break; + } + i--; + } + + return { + range: i !== -1 && range, + firstRange: firstRange + }; + } + + this.onFoldWidgetClick = function(row, e) { + e = e.domEvent; + var options = { + children: e.shiftKey, + all: e.ctrlKey || e.metaKey, + siblings: e.altKey + }; + + var range = this.$toggleFoldWidget(row, options); + if (!range) { + var el = (e.target || e.srcElement) + if (el && /ace_fold-widget/.test(el.className)) + el.className += " ace_invalid"; + } + }; + + this.$toggleFoldWidget = function(row, options) { + if (!this.getFoldWidget) + return; + var type = this.getFoldWidget(row); + var line = this.getLine(row); + + var dir = type === "end" ? -1 : 1; + var fold = this.getFoldAt(row, dir === -1 ? 0 : line.length, dir); + + if (fold) { + if (options.children || options.all) + this.removeFold(fold); + else + this.expandFold(fold); + return; + } + + var range = this.getFoldWidgetRange(row, true); + if (range && !range.isMultiLine()) { + fold = this.getFoldAt(range.start.row, range.start.column, 1); + if (fold && range.isEqual(fold.range)) { + this.removeFold(fold); + return; + } + } + + if (options.siblings) { + var data = this.getParentFoldRangeData(row); + if (data.range) { + var startRow = data.range.start.row + 1; + var endRow = data.range.end.row; + } + this.foldAll(startRow, endRow, options.all ? 10000 : 0); + } else if (options.children) { + endRow = range ? range.end.row : this.getLength(); + this.foldAll(row + 1, endRow, options.all ? 10000 : 0); + } else if (range) { + if (options.all) + range.collapseChildren = 10000; + this.addFold("...", range); + } + + return range; + }; + + + + this.toggleFoldWidget = function(toggleParent) { + var row = this.selection.getCursor().row; + row = this.getRowFoldStart(row); + var range = this.$toggleFoldWidget(row, {}); + + if (range) + return; + var data = this.getParentFoldRangeData(row, true); + range = data.range || data.firstRange; + + if (range) { + row = range.start.row; + var fold = this.getFoldAt(row, this.getLine(row).length, 1); + + if (fold) { + this.removeFold(fold); + } else { + this.addFold("...", range); + } + } + }; + + this.updateFoldWidgets = function(e) { + var delta = e.data; + var range = delta.range; + var firstRow = range.start.row; + var len = range.end.row - firstRow; + + if (len === 0) { + this.foldWidgets[firstRow] = null; + } else if (delta.action == "removeText" || delta.action == "removeLines") { + this.foldWidgets.splice(firstRow, len + 1, null); + } else { + var args = Array(len + 1); + args.unshift(firstRow, 1); + this.foldWidgets.splice.apply(this.foldWidgets, args); + } + }; + this.tokenizerUpdateFoldWidgets = function(e) { + var rows = e.data; + if (rows.first != rows.last) { + if (this.foldWidgets.length > rows.first) + this.foldWidgets.splice(rows.first, this.foldWidgets.length); + } + } +} + +exports.Folding = Folding; + +}); + +define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"], function(require, exports, module) { +"use strict"; + +var TokenIterator = require("../token_iterator").TokenIterator; +var Range = require("../range").Range; + + +function BracketMatch() { + + this.findMatchingBracket = function(position, chr) { + if (position.column == 0) return null; + + var charBeforeCursor = chr || this.getLine(position.row).charAt(position.column-1); + if (charBeforeCursor == "") return null; + + var match = charBeforeCursor.match(/([\(\[\{])|([\)\]\}])/); + if (!match) + return null; + + if (match[1]) + return this.$findClosingBracket(match[1], position); + else + return this.$findOpeningBracket(match[2], position); + }; + + this.getBracketRange = function(pos) { + var line = this.getLine(pos.row); + var before = true, range; + + var chr = line.charAt(pos.column-1); + var match = chr && chr.match(/([\(\[\{])|([\)\]\}])/); + if (!match) { + chr = line.charAt(pos.column); + pos = {row: pos.row, column: pos.column + 1}; + match = chr && chr.match(/([\(\[\{])|([\)\]\}])/); + before = false; + } + if (!match) + return null; + + if (match[1]) { + var bracketPos = this.$findClosingBracket(match[1], pos); + if (!bracketPos) + return null; + range = Range.fromPoints(pos, bracketPos); + if (!before) { + range.end.column++; + range.start.column--; + } + range.cursor = range.end; + } else { + var bracketPos = this.$findOpeningBracket(match[2], pos); + if (!bracketPos) + return null; + range = Range.fromPoints(bracketPos, pos); + if (!before) { + range.start.column++; + range.end.column--; + } + range.cursor = range.start; + } + + return range; + }; + + this.$brackets = { + ")": "(", + "(": ")", + "]": "[", + "[": "]", + "{": "}", + "}": "{" + }; + + this.$findOpeningBracket = function(bracket, position, typeRe) { + var openBracket = this.$brackets[bracket]; + var depth = 1; + + var iterator = new TokenIterator(this, position.row, position.column); + var token = iterator.getCurrentToken(); + if (!token) + token = iterator.stepForward(); + if (!token) + return; + + if (!typeRe){ + typeRe = new RegExp( + "(\\.?" + + token.type.replace(".", "\\.").replace("rparen", ".paren") + .replace(/\b(?:end|start|begin)\b/, "") + + ")+" + ); + } + var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2; + var value = token.value; + + while (true) { + + while (valueIndex >= 0) { + var chr = value.charAt(valueIndex); + if (chr == openBracket) { + depth -= 1; + if (depth == 0) { + return {row: iterator.getCurrentTokenRow(), + column: valueIndex + iterator.getCurrentTokenColumn()}; + } + } + else if (chr == bracket) { + depth += 1; + } + valueIndex -= 1; + } + do { + token = iterator.stepBackward(); + } while (token && !typeRe.test(token.type)); + + if (token == null) + break; + + value = token.value; + valueIndex = value.length - 1; + } + + return null; + }; + + this.$findClosingBracket = function(bracket, position, typeRe) { + var closingBracket = this.$brackets[bracket]; + var depth = 1; + + var iterator = new TokenIterator(this, position.row, position.column); + var token = iterator.getCurrentToken(); + if (!token) + token = iterator.stepForward(); + if (!token) + return; + + if (!typeRe){ + typeRe = new RegExp( + "(\\.?" + + token.type.replace(".", "\\.").replace("lparen", ".paren") + .replace(/\b(?:end|start|begin)\b/, "") + + ")+" + ); + } + var valueIndex = position.column - iterator.getCurrentTokenColumn(); + + while (true) { + + var value = token.value; + var valueLength = value.length; + while (valueIndex < valueLength) { + var chr = value.charAt(valueIndex); + if (chr == closingBracket) { + depth -= 1; + if (depth == 0) { + return {row: iterator.getCurrentTokenRow(), + column: valueIndex + iterator.getCurrentTokenColumn()}; + } + } + else if (chr == bracket) { + depth += 1; + } + valueIndex += 1; + } + do { + token = iterator.stepForward(); + } while (token && !typeRe.test(token.type)); + + if (token == null) + break; + + valueIndex = 0; + } + + return null; + }; +} +exports.BracketMatch = BracketMatch; + +}); + +define("ace/edit_session",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/config","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/search_highlight","ace/edit_session/folding","ace/edit_session/bracket_match"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var lang = require("./lib/lang"); +var config = require("./config"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var Selection = require("./selection").Selection; +var TextMode = require("./mode/text").Mode; +var Range = require("./range").Range; +var Document = require("./document").Document; +var BackgroundTokenizer = require("./background_tokenizer").BackgroundTokenizer; +var SearchHighlight = require("./search_highlight").SearchHighlight; + +var EditSession = function(text, mode) { + this.$breakpoints = []; + this.$decorations = []; + this.$frontMarkers = {}; + this.$backMarkers = {}; + this.$markerId = 1; + this.$undoSelect = true; + + this.$foldData = []; + this.$foldData.toString = function() { + return this.join("\n"); + } + this.on("changeFold", this.onChangeFold.bind(this)); + this.$onChange = this.onChange.bind(this); + + if (typeof text != "object" || !text.getLine) + text = new Document(text); + + this.setDocument(text); + this.selection = new Selection(this); + + config.resetOptions(this); + this.setMode(mode); + config._signal("session", this); +}; + + +(function() { + + oop.implement(this, EventEmitter); + this.setDocument = function(doc) { + if (this.doc) + this.doc.removeListener("change", this.$onChange); + + this.doc = doc; + doc.on("change", this.$onChange); + + if (this.bgTokenizer) + this.bgTokenizer.setDocument(this.getDocument()); + + this.resetCaches(); + }; + this.getDocument = function() { + return this.doc; + }; + this.$resetRowCache = function(docRow) { + if (!docRow) { + this.$docRowCache = []; + this.$screenRowCache = []; + return; + } + var l = this.$docRowCache.length; + var i = this.$getRowCacheIndex(this.$docRowCache, docRow) + 1; + if (l > i) { + this.$docRowCache.splice(i, l); + this.$screenRowCache.splice(i, l); + } + }; + + this.$getRowCacheIndex = function(cacheArray, val) { + var low = 0; + var hi = cacheArray.length - 1; + + while (low <= hi) { + var mid = (low + hi) >> 1; + var c = cacheArray[mid]; + + if (val > c) + low = mid + 1; + else if (val < c) + hi = mid - 1; + else + return mid; + } + + return low -1; + }; + + this.resetCaches = function() { + this.$modified = true; + this.$wrapData = []; + this.$rowLengthCache = []; + this.$resetRowCache(0); + if (this.bgTokenizer) + this.bgTokenizer.start(0); + }; + + this.onChangeFold = function(e) { + var fold = e.data; + this.$resetRowCache(fold.start.row); + }; + + this.onChange = function(e) { + var delta = e.data; + this.$modified = true; + + this.$resetRowCache(delta.range.start.row); + + var removedFolds = this.$updateInternalDataOnChange(e); + if (!this.$fromUndo && this.$undoManager && !delta.ignore) { + this.$deltasDoc.push(delta); + if (removedFolds && removedFolds.length != 0) { + this.$deltasFold.push({ + action: "removeFolds", + folds: removedFolds + }); + } + + this.$informUndoManager.schedule(); + } + + this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta); + this._signal("change", e); + }; + this.setValue = function(text) { + this.doc.setValue(text); + this.selection.moveTo(0, 0); + + this.$resetRowCache(0); + this.$deltas = []; + this.$deltasDoc = []; + this.$deltasFold = []; + this.setUndoManager(this.$undoManager); + this.getUndoManager().reset(); + }; + this.getValue = + this.toString = function() { + return this.doc.getValue(); + }; + this.getSelection = function() { + return this.selection; + }; + this.getState = function(row) { + return this.bgTokenizer.getState(row); + }; + this.getTokens = function(row) { + return this.bgTokenizer.getTokens(row); + }; + this.getTokenAt = function(row, column) { + var tokens = this.bgTokenizer.getTokens(row); + var token, c = 0; + if (column == null) { + i = tokens.length - 1; + c = this.getLine(row).length; + } else { + for (var i = 0; i < tokens.length; i++) { + c += tokens[i].value.length; + if (c >= column) + break; + } + } + token = tokens[i]; + if (!token) + return null; + token.index = i; + token.start = c - token.value.length; + return token; + }; + this.setUndoManager = function(undoManager) { + this.$undoManager = undoManager; + this.$deltas = []; + this.$deltasDoc = []; + this.$deltasFold = []; + + if (this.$informUndoManager) + this.$informUndoManager.cancel(); + + if (undoManager) { + var self = this; + + this.$syncInformUndoManager = function() { + self.$informUndoManager.cancel(); + + if (self.$deltasFold.length) { + self.$deltas.push({ + group: "fold", + deltas: self.$deltasFold + }); + self.$deltasFold = []; + } + + if (self.$deltasDoc.length) { + self.$deltas.push({ + group: "doc", + deltas: self.$deltasDoc + }); + self.$deltasDoc = []; + } + + if (self.$deltas.length > 0) { + undoManager.execute({ + action: "aceupdate", + args: [self.$deltas, self], + merge: self.mergeUndoDeltas + }); + } + self.mergeUndoDeltas = false; + self.$deltas = []; + }; + this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager); + } + }; + this.markUndoGroup = function() { + if (this.$syncInformUndoManager) + this.$syncInformUndoManager(); + }; + + this.$defaultUndoManager = { + undo: function() {}, + redo: function() {}, + reset: function() {} + }; + this.getUndoManager = function() { + return this.$undoManager || this.$defaultUndoManager; + }; + this.getTabString = function() { + if (this.getUseSoftTabs()) { + return lang.stringRepeat(" ", this.getTabSize()); + } else { + return "\t"; + } + }; + this.setUseSoftTabs = function(val) { + this.setOption("useSoftTabs", val); + }; + this.getUseSoftTabs = function() { + return this.$useSoftTabs && !this.$mode.$indentWithTabs; + }; + this.setTabSize = function(tabSize) { + this.setOption("tabSize", tabSize); + }; + this.getTabSize = function() { + return this.$tabSize; + }; + this.isTabStop = function(position) { + return this.$useSoftTabs && (position.column % this.$tabSize === 0); + }; + + this.$overwrite = false; + this.setOverwrite = function(overwrite) { + this.setOption("overwrite", overwrite); + }; + this.getOverwrite = function() { + return this.$overwrite; + }; + this.toggleOverwrite = function() { + this.setOverwrite(!this.$overwrite); + }; + this.addGutterDecoration = function(row, className) { + if (!this.$decorations[row]) + this.$decorations[row] = ""; + this.$decorations[row] += " " + className; + this._signal("changeBreakpoint", {}); + }; + this.removeGutterDecoration = function(row, className) { + this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, ""); + this._signal("changeBreakpoint", {}); + }; + this.getBreakpoints = function() { + return this.$breakpoints; + }; + this.setBreakpoints = function(rows) { + this.$breakpoints = []; + for (var i=0; i 0) + inToken = !!line.charAt(column - 1).match(this.tokenRe); + + if (!inToken) + inToken = !!line.charAt(column).match(this.tokenRe); + + if (inToken) + var re = this.tokenRe; + else if (/^\s+$/.test(line.slice(column-1, column+1))) + var re = /\s/; + else + var re = this.nonTokenRe; + + var start = column; + if (start > 0) { + do { + start--; + } + while (start >= 0 && line.charAt(start).match(re)); + start++; + } + + var end = column; + while (end < line.length && line.charAt(end).match(re)) { + end++; + } + + return new Range(row, start, row, end); + }; + this.getAWordRange = function(row, column) { + var wordRange = this.getWordRange(row, column); + var line = this.getLine(wordRange.end.row); + + while (line.charAt(wordRange.end.column).match(/[ \t]/)) { + wordRange.end.column += 1; + } + return wordRange; + }; + this.setNewLineMode = function(newLineMode) { + this.doc.setNewLineMode(newLineMode); + }; + this.getNewLineMode = function() { + return this.doc.getNewLineMode(); + }; + this.setUseWorker = function(useWorker) { this.setOption("useWorker", useWorker); }; + this.getUseWorker = function() { return this.$useWorker; }; + this.onReloadTokenizer = function(e) { + var rows = e.data; + this.bgTokenizer.start(rows.first); + this._signal("tokenizerUpdate", e); + }; + + this.$modes = {}; + this.$mode = null; + this.$modeId = null; + this.setMode = function(mode, cb) { + if (mode && typeof mode === "object") { + if (mode.getTokenizer) + return this.$onChangeMode(mode); + var options = mode; + var path = options.path; + } else { + path = mode || "ace/mode/text"; + } + if (!this.$modes["ace/mode/text"]) + this.$modes["ace/mode/text"] = new TextMode(); + + if (this.$modes[path] && !options) { + this.$onChangeMode(this.$modes[path]); + cb && cb(); + return; + } + this.$modeId = path; + config.loadModule(["mode", path], function(m) { + if (this.$modeId !== path) + return cb && cb(); + if (this.$modes[path] && !options) { + this.$onChangeMode(this.$modes[path]); + } else if (m && m.Mode) { + m = new m.Mode(options); + if (!options) { + this.$modes[path] = m; + m.$id = path; + } + this.$onChangeMode(m); + } + cb && cb(); + }.bind(this)); + if (!this.$mode) + this.$onChangeMode(this.$modes["ace/mode/text"], true); + }; + + this.$onChangeMode = function(mode, $isPlaceholder) { + if (!$isPlaceholder) + this.$modeId = mode.$id; + if (this.$mode === mode) + return; + + this.$mode = mode; + + this.$stopWorker(); + + if (this.$useWorker) + this.$startWorker(); + + var tokenizer = mode.getTokenizer(); + + if(tokenizer.addEventListener !== undefined) { + var onReloadTokenizer = this.onReloadTokenizer.bind(this); + tokenizer.addEventListener("update", onReloadTokenizer); + } + + if (!this.bgTokenizer) { + this.bgTokenizer = new BackgroundTokenizer(tokenizer); + var _self = this; + this.bgTokenizer.addEventListener("update", function(e) { + _self._signal("tokenizerUpdate", e); + }); + } else { + this.bgTokenizer.setTokenizer(tokenizer); + } + + this.bgTokenizer.setDocument(this.getDocument()); + + this.tokenRe = mode.tokenRe; + this.nonTokenRe = mode.nonTokenRe; + + + if (!$isPlaceholder) { + if (mode.attachToSession) + mode.attachToSession(this); + this.$options.wrapMethod.set.call(this, this.$wrapMethod); + this.$setFolding(mode.foldingRules); + this.bgTokenizer.start(0); + this._emit("changeMode"); + } + }; + + this.$stopWorker = function() { + if (this.$worker) { + this.$worker.terminate(); + this.$worker = null; + } + }; + + this.$startWorker = function() { + try { + this.$worker = this.$mode.createWorker(this); + } catch (e) { + config.warn("Could not load worker", e); + this.$worker = null; + } + }; + this.getMode = function() { + return this.$mode; + }; + + this.$scrollTop = 0; + this.setScrollTop = function(scrollTop) { + if (this.$scrollTop === scrollTop || isNaN(scrollTop)) + return; + + this.$scrollTop = scrollTop; + this._signal("changeScrollTop", scrollTop); + }; + this.getScrollTop = function() { + return this.$scrollTop; + }; + + this.$scrollLeft = 0; + this.setScrollLeft = function(scrollLeft) { + if (this.$scrollLeft === scrollLeft || isNaN(scrollLeft)) + return; + + this.$scrollLeft = scrollLeft; + this._signal("changeScrollLeft", scrollLeft); + }; + this.getScrollLeft = function() { + return this.$scrollLeft; + }; + this.getScreenWidth = function() { + this.$computeWidth(); + if (this.lineWidgets) + return Math.max(this.getLineWidgetMaxWidth(), this.screenWidth); + return this.screenWidth; + }; + + this.getLineWidgetMaxWidth = function() { + if (this.lineWidgetsWidth != null) return this.lineWidgetsWidth; + var width = 0; + this.lineWidgets.forEach(function(w) { + if (w && w.screenWidth > width) + width = w.screenWidth; + }); + return this.lineWidgetWidth = width; + }; + + this.$computeWidth = function(force) { + if (this.$modified || force) { + this.$modified = false; + + if (this.$useWrapMode) + return this.screenWidth = this.$wrapLimit; + + var lines = this.doc.getAllLines(); + var cache = this.$rowLengthCache; + var longestScreenLine = 0; + var foldIndex = 0; + var foldLine = this.$foldData[foldIndex]; + var foldStart = foldLine ? foldLine.start.row : Infinity; + var len = lines.length; + + for (var i = 0; i < len; i++) { + if (i > foldStart) { + i = foldLine.end.row + 1; + if (i >= len) + break; + foldLine = this.$foldData[foldIndex++]; + foldStart = foldLine ? foldLine.start.row : Infinity; + } + + if (cache[i] == null) + cache[i] = this.$getStringScreenWidth(lines[i])[0]; + + if (cache[i] > longestScreenLine) + longestScreenLine = cache[i]; + } + this.screenWidth = longestScreenLine; + } + }; + this.getLine = function(row) { + return this.doc.getLine(row); + }; + this.getLines = function(firstRow, lastRow) { + return this.doc.getLines(firstRow, lastRow); + }; + this.getLength = function() { + return this.doc.getLength(); + }; + this.getTextRange = function(range) { + return this.doc.getTextRange(range || this.selection.getRange()); + }; + this.insert = function(position, text) { + return this.doc.insert(position, text); + }; + this.remove = function(range) { + return this.doc.remove(range); + }; + this.undoChanges = function(deltas, dontSelect) { + if (!deltas.length) + return; + + this.$fromUndo = true; + var lastUndoRange = null; + for (var i = deltas.length - 1; i != -1; i--) { + var delta = deltas[i]; + if (delta.group == "doc") { + this.doc.revertDeltas(delta.deltas); + lastUndoRange = + this.$getUndoSelection(delta.deltas, true, lastUndoRange); + } else { + delta.deltas.forEach(function(foldDelta) { + this.addFolds(foldDelta.folds); + }, this); + } + } + this.$fromUndo = false; + lastUndoRange && + this.$undoSelect && + !dontSelect && + this.selection.setSelectionRange(lastUndoRange); + return lastUndoRange; + }; + this.redoChanges = function(deltas, dontSelect) { + if (!deltas.length) + return; + + this.$fromUndo = true; + var lastUndoRange = null; + for (var i = 0; i < deltas.length; i++) { + var delta = deltas[i]; + if (delta.group == "doc") { + this.doc.applyDeltas(delta.deltas); + lastUndoRange = + this.$getUndoSelection(delta.deltas, false, lastUndoRange); + } + } + this.$fromUndo = false; + lastUndoRange && + this.$undoSelect && + !dontSelect && + this.selection.setSelectionRange(lastUndoRange); + return lastUndoRange; + }; + this.setUndoSelect = function(enable) { + this.$undoSelect = enable; + }; + + this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) { + function isInsert(delta) { + var insert = + delta.action === "insertText" || delta.action === "insertLines"; + return isUndo ? !insert : insert; + } + + var delta = deltas[0]; + var range, point; + var lastDeltaIsInsert = false; + if (isInsert(delta)) { + range = Range.fromPoints(delta.range.start, delta.range.end); + lastDeltaIsInsert = true; + } else { + range = Range.fromPoints(delta.range.start, delta.range.start); + lastDeltaIsInsert = false; + } + + for (var i = 1; i < deltas.length; i++) { + delta = deltas[i]; + if (isInsert(delta)) { + point = delta.range.start; + if (range.compare(point.row, point.column) == -1) { + range.setStart(delta.range.start); + } + point = delta.range.end; + if (range.compare(point.row, point.column) == 1) { + range.setEnd(delta.range.end); + } + lastDeltaIsInsert = true; + } else { + point = delta.range.start; + if (range.compare(point.row, point.column) == -1) { + range = + Range.fromPoints(delta.range.start, delta.range.start); + } + lastDeltaIsInsert = false; + } + } + if (lastUndoRange != null) { + if (Range.comparePoints(lastUndoRange.start, range.start) === 0) { + lastUndoRange.start.column += range.end.column - range.start.column; + lastUndoRange.end.column += range.end.column - range.start.column; + } + + var cmp = lastUndoRange.compareRange(range); + if (cmp == 1) { + range.setStart(lastUndoRange.start); + } else if (cmp == -1) { + range.setEnd(lastUndoRange.end); + } + } + + return range; + }; + this.replace = function(range, text) { + return this.doc.replace(range, text); + }; + this.moveText = function(fromRange, toPosition, copy) { + var text = this.getTextRange(fromRange); + var folds = this.getFoldsInRange(fromRange); + + var toRange = Range.fromPoints(toPosition, toPosition); + if (!copy) { + this.remove(fromRange); + var rowDiff = fromRange.start.row - fromRange.end.row; + var collDiff = rowDiff ? -fromRange.end.column : fromRange.start.column - fromRange.end.column; + if (collDiff) { + if (toRange.start.row == fromRange.end.row && toRange.start.column > fromRange.end.column) + toRange.start.column += collDiff; + if (toRange.end.row == fromRange.end.row && toRange.end.column > fromRange.end.column) + toRange.end.column += collDiff; + } + if (rowDiff && toRange.start.row >= fromRange.end.row) { + toRange.start.row += rowDiff; + toRange.end.row += rowDiff; + } + } + + toRange.end = this.insert(toRange.start, text); + if (folds.length) { + var oldStart = fromRange.start; + var newStart = toRange.start; + var rowDiff = newStart.row - oldStart.row; + var collDiff = newStart.column - oldStart.column; + this.addFolds(folds.map(function(x) { + x = x.clone(); + if (x.start.row == oldStart.row) + x.start.column += collDiff; + if (x.end.row == oldStart.row) + x.end.column += collDiff; + x.start.row += rowDiff; + x.end.row += rowDiff; + return x; + })); + } + + return toRange; + }; + this.indentRows = function(startRow, endRow, indentString) { + indentString = indentString.replace(/\t/g, this.getTabString()); + for (var row=startRow; row<=endRow; row++) + this.insert({row: row, column:0}, indentString); + }; + this.outdentRows = function (range) { + var rowRange = range.collapseRows(); + var deleteRange = new Range(0, 0, 0, 0); + var size = this.getTabSize(); + + for (var i = rowRange.start.row; i <= rowRange.end.row; ++i) { + var line = this.getLine(i); + + deleteRange.start.row = i; + deleteRange.end.row = i; + for (var j = 0; j < size; ++j) + if (line.charAt(j) != ' ') + break; + if (j < size && line.charAt(j) == '\t') { + deleteRange.start.column = j; + deleteRange.end.column = j + 1; + } else { + deleteRange.start.column = 0; + deleteRange.end.column = j; + } + this.remove(deleteRange); + } + }; + + this.$moveLines = function(firstRow, lastRow, dir) { + firstRow = this.getRowFoldStart(firstRow); + lastRow = this.getRowFoldEnd(lastRow); + if (dir < 0) { + var row = this.getRowFoldStart(firstRow + dir); + if (row < 0) return 0; + var diff = row-firstRow; + } else if (dir > 0) { + var row = this.getRowFoldEnd(lastRow + dir); + if (row > this.doc.getLength()-1) return 0; + var diff = row-lastRow; + } else { + firstRow = this.$clipRowToDocument(firstRow); + lastRow = this.$clipRowToDocument(lastRow); + var diff = lastRow - firstRow + 1; + } + + var range = new Range(firstRow, 0, lastRow, Number.MAX_VALUE); + var folds = this.getFoldsInRange(range).map(function(x){ + x = x.clone(); + x.start.row += diff; + x.end.row += diff; + return x; + }); + + var lines = dir == 0 + ? this.doc.getLines(firstRow, lastRow) + : this.doc.removeLines(firstRow, lastRow); + this.doc.insertLines(firstRow+diff, lines); + folds.length && this.addFolds(folds); + return diff; + }; + this.moveLinesUp = function(firstRow, lastRow) { + return this.$moveLines(firstRow, lastRow, -1); + }; + this.moveLinesDown = function(firstRow, lastRow) { + return this.$moveLines(firstRow, lastRow, 1); + }; + this.duplicateLines = function(firstRow, lastRow) { + return this.$moveLines(firstRow, lastRow, 0); + }; + + + this.$clipRowToDocument = function(row) { + return Math.max(0, Math.min(row, this.doc.getLength()-1)); + }; + + this.$clipColumnToRow = function(row, column) { + if (column < 0) + return 0; + return Math.min(this.doc.getLine(row).length, column); + }; + + + this.$clipPositionToDocument = function(row, column) { + column = Math.max(0, column); + + if (row < 0) { + row = 0; + column = 0; + } else { + var len = this.doc.getLength(); + if (row >= len) { + row = len - 1; + column = this.doc.getLine(len-1).length; + } else { + column = Math.min(this.doc.getLine(row).length, column); + } + } + + return { + row: row, + column: column + }; + }; + + this.$clipRangeToDocument = function(range) { + if (range.start.row < 0) { + range.start.row = 0; + range.start.column = 0; + } else { + range.start.column = this.$clipColumnToRow( + range.start.row, + range.start.column + ); + } + + var len = this.doc.getLength() - 1; + if (range.end.row > len) { + range.end.row = len; + range.end.column = this.doc.getLine(len).length; + } else { + range.end.column = this.$clipColumnToRow( + range.end.row, + range.end.column + ); + } + return range; + }; + this.$wrapLimit = 80; + this.$useWrapMode = false; + this.$wrapLimitRange = { + min : null, + max : null + }; + this.setUseWrapMode = function(useWrapMode) { + if (useWrapMode != this.$useWrapMode) { + this.$useWrapMode = useWrapMode; + this.$modified = true; + this.$resetRowCache(0); + if (useWrapMode) { + var len = this.getLength(); + this.$wrapData = Array(len); + this.$updateWrapData(0, len - 1); + } + + this._signal("changeWrapMode"); + } + }; + this.getUseWrapMode = function() { + return this.$useWrapMode; + }; + this.setWrapLimitRange = function(min, max) { + if (this.$wrapLimitRange.min !== min || this.$wrapLimitRange.max !== max) { + this.$wrapLimitRange = { min: min, max: max }; + this.$modified = true; + if (this.$useWrapMode) + this._signal("changeWrapMode"); + } + }; + this.adjustWrapLimit = function(desiredLimit, $printMargin) { + var limits = this.$wrapLimitRange; + if (limits.max < 0) + limits = {min: $printMargin, max: $printMargin}; + var wrapLimit = this.$constrainWrapLimit(desiredLimit, limits.min, limits.max); + if (wrapLimit != this.$wrapLimit && wrapLimit > 1) { + this.$wrapLimit = wrapLimit; + this.$modified = true; + if (this.$useWrapMode) { + this.$updateWrapData(0, this.getLength() - 1); + this.$resetRowCache(0); + this._signal("changeWrapLimit"); + } + return true; + } + return false; + }; + + this.$constrainWrapLimit = function(wrapLimit, min, max) { + if (min) + wrapLimit = Math.max(min, wrapLimit); + + if (max) + wrapLimit = Math.min(max, wrapLimit); + + return wrapLimit; + }; + this.getWrapLimit = function() { + return this.$wrapLimit; + }; + this.setWrapLimit = function (limit) { + this.setWrapLimitRange(limit, limit); + }; + this.getWrapLimitRange = function() { + return { + min : this.$wrapLimitRange.min, + max : this.$wrapLimitRange.max + }; + }; + + this.$updateInternalDataOnChange = function(e) { + var useWrapMode = this.$useWrapMode; + var len; + var action = e.data.action; + var firstRow = e.data.range.start.row; + var lastRow = e.data.range.end.row; + var start = e.data.range.start; + var end = e.data.range.end; + var removedFolds = null; + + if (action.indexOf("Lines") != -1) { + if (action == "insertLines") { + lastRow = firstRow + (e.data.lines.length); + } else { + lastRow = firstRow; + } + len = e.data.lines ? e.data.lines.length : lastRow - firstRow; + } else { + len = lastRow - firstRow; + } + + this.$updating = true; + if (len != 0) { + if (action.indexOf("remove") != -1) { + this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); + + var foldLines = this.$foldData; + removedFolds = this.getFoldsInRange(e.data.range); + this.removeFolds(removedFolds); + + var foldLine = this.getFoldLine(end.row); + var idx = 0; + if (foldLine) { + foldLine.addRemoveChars(end.row, end.column, start.column - end.column); + foldLine.shiftRow(-len); + + var foldLineBefore = this.getFoldLine(firstRow); + if (foldLineBefore && foldLineBefore !== foldLine) { + foldLineBefore.merge(foldLine); + foldLine = foldLineBefore; + } + idx = foldLines.indexOf(foldLine) + 1; + } + + for (idx; idx < foldLines.length; idx++) { + var foldLine = foldLines[idx]; + if (foldLine.start.row >= end.row) { + foldLine.shiftRow(-len); + } + } + + lastRow = firstRow; + } else { + var args = Array(len); + args.unshift(firstRow, 0); + var arr = useWrapMode ? this.$wrapData : this.$rowLengthCache + arr.splice.apply(arr, args); + var foldLines = this.$foldData; + var foldLine = this.getFoldLine(firstRow); + var idx = 0; + if (foldLine) { + var cmp = foldLine.range.compareInside(start.row, start.column); + if (cmp == 0) { + foldLine = foldLine.split(start.row, start.column); + if (foldLine) { + foldLine.shiftRow(len); + foldLine.addRemoveChars(lastRow, 0, end.column - start.column); + } + } else + if (cmp == -1) { + foldLine.addRemoveChars(firstRow, 0, end.column - start.column); + foldLine.shiftRow(len); + } + idx = foldLines.indexOf(foldLine) + 1; + } + + for (idx; idx < foldLines.length; idx++) { + var foldLine = foldLines[idx]; + if (foldLine.start.row >= firstRow) { + foldLine.shiftRow(len); + } + } + } + } else { + len = Math.abs(e.data.range.start.column - e.data.range.end.column); + if (action.indexOf("remove") != -1) { + removedFolds = this.getFoldsInRange(e.data.range); + this.removeFolds(removedFolds); + + len = -len; + } + var foldLine = this.getFoldLine(firstRow); + if (foldLine) { + foldLine.addRemoveChars(firstRow, start.column, len); + } + } + + if (useWrapMode && this.$wrapData.length != this.doc.getLength()) { + console.error("doc.getLength() and $wrapData.length have to be the same!"); + } + this.$updating = false; + + if (useWrapMode) + this.$updateWrapData(firstRow, lastRow); + else + this.$updateRowLengthCache(firstRow, lastRow); + + return removedFolds; + }; + + this.$updateRowLengthCache = function(firstRow, lastRow, b) { + this.$rowLengthCache[firstRow] = null; + this.$rowLengthCache[lastRow] = null; + }; + + this.$updateWrapData = function(firstRow, lastRow) { + var lines = this.doc.getAllLines(); + var tabSize = this.getTabSize(); + var wrapData = this.$wrapData; + var wrapLimit = this.$wrapLimit; + var tokens; + var foldLine; + + var row = firstRow; + lastRow = Math.min(lastRow, lines.length - 1); + while (row <= lastRow) { + foldLine = this.getFoldLine(row, foldLine); + if (!foldLine) { + tokens = this.$getDisplayTokens(lines[row]); + wrapData[row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize); + row ++; + } else { + tokens = []; + foldLine.walk(function(placeholder, row, column, lastColumn) { + var walkTokens; + if (placeholder != null) { + walkTokens = this.$getDisplayTokens( + placeholder, tokens.length); + walkTokens[0] = PLACEHOLDER_START; + for (var i = 1; i < walkTokens.length; i++) { + walkTokens[i] = PLACEHOLDER_BODY; + } + } else { + walkTokens = this.$getDisplayTokens( + lines[row].substring(lastColumn, column), + tokens.length); + } + tokens = tokens.concat(walkTokens); + }.bind(this), + foldLine.end.row, + lines[foldLine.end.row].length + 1 + ); + + wrapData[foldLine.start.row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize); + row = foldLine.end.row + 1; + } + } + }; + var CHAR = 1, + CHAR_EXT = 2, + PLACEHOLDER_START = 3, + PLACEHOLDER_BODY = 4, + PUNCTUATION = 9, + SPACE = 10, + TAB = 11, + TAB_SPACE = 12; + + + this.$computeWrapSplits = function(tokens, wrapLimit) { + if (tokens.length == 0) { + return []; + } + + var splits = []; + var displayLength = tokens.length; + var lastSplit = 0, lastDocSplit = 0; + + var isCode = this.$wrapAsCode; + + function addSplit(screenPos) { + var displayed = tokens.slice(lastSplit, screenPos); + var len = displayed.length; + displayed.join(""). + replace(/12/g, function() { + len -= 1; + }). + replace(/2/g, function() { + len -= 1; + }); + + lastDocSplit += len; + splits.push(lastDocSplit); + lastSplit = screenPos; + } + + while (displayLength - lastSplit > wrapLimit) { + var split = lastSplit + wrapLimit; + if (tokens[split - 1] >= SPACE && tokens[split] >= SPACE) { + addSplit(split); + continue; + } + if (tokens[split] == PLACEHOLDER_START || tokens[split] == PLACEHOLDER_BODY) { + for (split; split != lastSplit - 1; split--) { + if (tokens[split] == PLACEHOLDER_START) { + break; + } + } + if (split > lastSplit) { + addSplit(split); + continue; + } + split = lastSplit + wrapLimit; + for (split; split < tokens.length; split++) { + if (tokens[split] != PLACEHOLDER_BODY) { + break; + } + } + if (split == tokens.length) { + break; // Breaks the while-loop. + } + addSplit(split); + continue; + } + var minSplit = Math.max(split - (isCode ? 10 : wrapLimit-(wrapLimit>>2)), lastSplit - 1); + while (split > minSplit && tokens[split] < PLACEHOLDER_START) { + split --; + } + if (isCode) { + while (split > minSplit && tokens[split] < PLACEHOLDER_START) { + split --; + } + while (split > minSplit && tokens[split] == PUNCTUATION) { + split --; + } + } else { + while (split > minSplit && tokens[split] < SPACE) { + split --; + } + } + if (split > minSplit) { + addSplit(++split); + continue; + } + split = lastSplit + wrapLimit; + if (tokens[split] == CHAR_EXT) + split--; + addSplit(split); + } + return splits; + }; + this.$getDisplayTokens = function(str, offset) { + var arr = []; + var tabSize; + offset = offset || 0; + + for (var i = 0; i < str.length; i++) { + var c = str.charCodeAt(i); + if (c == 9) { + tabSize = this.getScreenTabSize(arr.length + offset); + arr.push(TAB); + for (var n = 1; n < tabSize; n++) { + arr.push(TAB_SPACE); + } + } + else if (c == 32) { + arr.push(SPACE); + } else if((c > 39 && c < 48) || (c > 57 && c < 64)) { + arr.push(PUNCTUATION); + } + else if (c >= 0x1100 && isFullWidth(c)) { + arr.push(CHAR, CHAR_EXT); + } else { + arr.push(CHAR); + } + } + return arr; + }; + this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) { + if (maxScreenColumn == 0) + return [0, 0]; + if (maxScreenColumn == null) + maxScreenColumn = Infinity; + screenColumn = screenColumn || 0; + + var c, column; + for (column = 0; column < str.length; column++) { + c = str.charCodeAt(column); + if (c == 9) { + screenColumn += this.getScreenTabSize(screenColumn); + } + else if (c >= 0x1100 && isFullWidth(c)) { + screenColumn += 2; + } else { + screenColumn += 1; + } + if (screenColumn > maxScreenColumn) { + break; + } + } + + return [screenColumn, column]; + }; + + this.lineWidgets = null; + this.getRowLength = function(row) { + if (this.lineWidgets) + var h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0; + else + h = 0 + if (!this.$useWrapMode || !this.$wrapData[row]) { + return 1 + h; + } else { + return this.$wrapData[row].length + 1 + h; + } + }; + this.getRowLineCount = function(row) { + if (!this.$useWrapMode || !this.$wrapData[row]) { + return 1; + } else { + return this.$wrapData[row].length + 1; + } + }; + this.getScreenLastRowColumn = function(screenRow) { + var pos = this.screenToDocumentPosition(screenRow, Number.MAX_VALUE); + return this.documentToScreenColumn(pos.row, pos.column); + }; + this.getDocumentLastRowColumn = function(docRow, docColumn) { + var screenRow = this.documentToScreenRow(docRow, docColumn); + return this.getScreenLastRowColumn(screenRow); + }; + this.getDocumentLastRowColumnPosition = function(docRow, docColumn) { + var screenRow = this.documentToScreenRow(docRow, docColumn); + return this.screenToDocumentPosition(screenRow, Number.MAX_VALUE / 10); + }; + this.getRowSplitData = function(row) { + if (!this.$useWrapMode) { + return undefined; + } else { + return this.$wrapData[row]; + } + }; + this.getScreenTabSize = function(screenColumn) { + return this.$tabSize - screenColumn % this.$tabSize; + }; + + + this.screenToDocumentRow = function(screenRow, screenColumn) { + return this.screenToDocumentPosition(screenRow, screenColumn).row; + }; + + + this.screenToDocumentColumn = function(screenRow, screenColumn) { + return this.screenToDocumentPosition(screenRow, screenColumn).column; + }; + this.screenToDocumentPosition = function(screenRow, screenColumn) { + if (screenRow < 0) + return {row: 0, column: 0}; + + var line; + var docRow = 0; + var docColumn = 0; + var column; + var row = 0; + var rowLength = 0; + + var rowCache = this.$screenRowCache; + var i = this.$getRowCacheIndex(rowCache, screenRow); + var l = rowCache.length; + if (l && i >= 0) { + var row = rowCache[i]; + var docRow = this.$docRowCache[i]; + var doCache = screenRow > rowCache[l - 1]; + } else { + var doCache = !l; + } + + var maxRow = this.getLength() - 1; + var foldLine = this.getNextFoldLine(docRow); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (row <= screenRow) { + rowLength = this.getRowLength(docRow); + if (row + rowLength > screenRow || docRow >= maxRow) { + break; + } else { + row += rowLength; + docRow++; + if (docRow > foldStart) { + docRow = foldLine.end.row+1; + foldLine = this.getNextFoldLine(docRow, foldLine); + foldStart = foldLine ? foldLine.start.row : Infinity; + } + } + + if (doCache) { + this.$docRowCache.push(docRow); + this.$screenRowCache.push(row); + } + } + + if (foldLine && foldLine.start.row <= docRow) { + line = this.getFoldDisplayLine(foldLine); + docRow = foldLine.start.row; + } else if (row + rowLength <= screenRow || docRow > maxRow) { + return { + row: maxRow, + column: this.getLine(maxRow).length + }; + } else { + line = this.getLine(docRow); + foldLine = null; + } + + if (this.$useWrapMode) { + var splits = this.$wrapData[docRow]; + if (splits) { + var splitIndex = Math.floor(screenRow - row); + column = splits[splitIndex]; + if(splitIndex > 0 && splits.length) { + docColumn = splits[splitIndex - 1] || splits[splits.length - 1]; + line = line.substring(docColumn); + } + } + } + + docColumn += this.$getStringScreenWidth(line, screenColumn)[1]; + if (this.$useWrapMode && docColumn >= column) + docColumn = column - 1; + + if (foldLine) + return foldLine.idxToPosition(docColumn); + + return {row: docRow, column: docColumn}; + }; + this.documentToScreenPosition = function(docRow, docColumn) { + if (typeof docColumn === "undefined") + var pos = this.$clipPositionToDocument(docRow.row, docRow.column); + else + pos = this.$clipPositionToDocument(docRow, docColumn); + + docRow = pos.row; + docColumn = pos.column; + + var screenRow = 0; + var foldStartRow = null; + var fold = null; + fold = this.getFoldAt(docRow, docColumn, 1); + if (fold) { + docRow = fold.start.row; + docColumn = fold.start.column; + } + + var rowEnd, row = 0; + + + var rowCache = this.$docRowCache; + var i = this.$getRowCacheIndex(rowCache, docRow); + var l = rowCache.length; + if (l && i >= 0) { + var row = rowCache[i]; + var screenRow = this.$screenRowCache[i]; + var doCache = docRow > rowCache[l - 1]; + } else { + var doCache = !l; + } + + var foldLine = this.getNextFoldLine(row); + var foldStart = foldLine ?foldLine.start.row :Infinity; + + while (row < docRow) { + if (row >= foldStart) { + rowEnd = foldLine.end.row + 1; + if (rowEnd > docRow) + break; + foldLine = this.getNextFoldLine(rowEnd, foldLine); + foldStart = foldLine ?foldLine.start.row :Infinity; + } + else { + rowEnd = row + 1; + } + + screenRow += this.getRowLength(row); + row = rowEnd; + + if (doCache) { + this.$docRowCache.push(row); + this.$screenRowCache.push(screenRow); + } + } + var textLine = ""; + if (foldLine && row >= foldStart) { + textLine = this.getFoldDisplayLine(foldLine, docRow, docColumn); + foldStartRow = foldLine.start.row; + } else { + textLine = this.getLine(docRow).substring(0, docColumn); + foldStartRow = docRow; + } + if (this.$useWrapMode) { + var wrapRow = this.$wrapData[foldStartRow]; + if (wrapRow) { + var screenRowOffset = 0; + while (textLine.length >= wrapRow[screenRowOffset]) { + screenRow ++; + screenRowOffset++; + } + textLine = textLine.substring( + wrapRow[screenRowOffset - 1] || 0, textLine.length + ); + } + } + + return { + row: screenRow, + column: this.$getStringScreenWidth(textLine)[0] + }; + }; + this.documentToScreenColumn = function(row, docColumn) { + return this.documentToScreenPosition(row, docColumn).column; + }; + this.documentToScreenRow = function(docRow, docColumn) { + return this.documentToScreenPosition(docRow, docColumn).row; + }; + this.getScreenLength = function() { + var screenRows = 0; + var fold = null; + if (!this.$useWrapMode) { + screenRows = this.getLength(); + var foldData = this.$foldData; + for (var i = 0; i < foldData.length; i++) { + fold = foldData[i]; + screenRows -= fold.end.row - fold.start.row; + } + } else { + var lastRow = this.$wrapData.length; + var row = 0, i = 0; + var fold = this.$foldData[i++]; + var foldStart = fold ? fold.start.row :Infinity; + + while (row < lastRow) { + var splits = this.$wrapData[row]; + screenRows += splits ? splits.length + 1 : 1; + row ++; + if (row > foldStart) { + row = fold.end.row+1; + fold = this.$foldData[i++]; + foldStart = fold ?fold.start.row :Infinity; + } + } + } + if (this.lineWidgets) + screenRows += this.$getWidgetScreenLength(); + + return screenRows; + }; + this.$setFontMetrics = function(fm) { + }; + + this.destroy = function() { + if (this.bgTokenizer) { + this.bgTokenizer.setDocument(null); + this.bgTokenizer = null; + } + this.$stopWorker(); + }; + function isFullWidth(c) { + if (c < 0x1100) + return false; + return c >= 0x1100 && c <= 0x115F || + c >= 0x11A3 && c <= 0x11A7 || + c >= 0x11FA && c <= 0x11FF || + c >= 0x2329 && c <= 0x232A || + c >= 0x2E80 && c <= 0x2E99 || + c >= 0x2E9B && c <= 0x2EF3 || + c >= 0x2F00 && c <= 0x2FD5 || + c >= 0x2FF0 && c <= 0x2FFB || + c >= 0x3000 && c <= 0x303E || + c >= 0x3041 && c <= 0x3096 || + c >= 0x3099 && c <= 0x30FF || + c >= 0x3105 && c <= 0x312D || + c >= 0x3131 && c <= 0x318E || + c >= 0x3190 && c <= 0x31BA || + c >= 0x31C0 && c <= 0x31E3 || + c >= 0x31F0 && c <= 0x321E || + c >= 0x3220 && c <= 0x3247 || + c >= 0x3250 && c <= 0x32FE || + c >= 0x3300 && c <= 0x4DBF || + c >= 0x4E00 && c <= 0xA48C || + c >= 0xA490 && c <= 0xA4C6 || + c >= 0xA960 && c <= 0xA97C || + c >= 0xAC00 && c <= 0xD7A3 || + c >= 0xD7B0 && c <= 0xD7C6 || + c >= 0xD7CB && c <= 0xD7FB || + c >= 0xF900 && c <= 0xFAFF || + c >= 0xFE10 && c <= 0xFE19 || + c >= 0xFE30 && c <= 0xFE52 || + c >= 0xFE54 && c <= 0xFE66 || + c >= 0xFE68 && c <= 0xFE6B || + c >= 0xFF01 && c <= 0xFF60 || + c >= 0xFFE0 && c <= 0xFFE6; + }; + +}).call(EditSession.prototype); + +require("./edit_session/folding").Folding.call(EditSession.prototype); +require("./edit_session/bracket_match").BracketMatch.call(EditSession.prototype); + + +config.defineOptions(EditSession.prototype, "session", { + wrap: { + set: function(value) { + if (!value || value == "off") + value = false; + else if (value == "free") + value = true; + else if (value == "printMargin") + value = -1; + else if (typeof value == "string") + value = parseInt(value, 10) || false; + + if (this.$wrap == value) + return; + this.$wrap = value; + if (!value) { + this.setUseWrapMode(false); + } else { + var col = typeof value == "number" ? value : null; + this.setWrapLimitRange(col, col); + this.setUseWrapMode(true); + } + }, + get: function() { + if (this.getUseWrapMode()) { + if (this.$wrap == -1) + return "printMargin"; + if (!this.getWrapLimitRange().min) + return "free"; + return this.$wrap; + } + return "off"; + }, + handlesSet: true + }, + wrapMethod: { + set: function(val) { + val = val == "auto" + ? this.$mode.type != "text" + : val != "text"; + if (val != this.$wrapAsCode) { + this.$wrapAsCode = val; + if (this.$useWrapMode) { + this.$modified = true; + this.$resetRowCache(0); + this.$updateWrapData(0, this.getLength() - 1); + } + } + }, + initialValue: "auto" + }, + firstLineNumber: { + set: function() {this._signal("changeBreakpoint");}, + initialValue: 1 + }, + useWorker: { + set: function(useWorker) { + this.$useWorker = useWorker; + + this.$stopWorker(); + if (useWorker) + this.$startWorker(); + }, + initialValue: true + }, + useSoftTabs: {initialValue: true}, + tabSize: { + set: function(tabSize) { + if (isNaN(tabSize) || this.$tabSize === tabSize) return; + + this.$modified = true; + this.$rowLengthCache = []; + this.$tabSize = tabSize; + this._signal("changeTabSize"); + }, + initialValue: 4, + handlesSet: true + }, + overwrite: { + set: function(val) {this._signal("changeOverwrite");}, + initialValue: false + }, + newLineMode: { + set: function(val) {this.doc.setNewLineMode(val)}, + get: function() {return this.doc.getNewLineMode()}, + handlesSet: true + }, + mode: { + set: function(val) { this.setMode(val) }, + get: function() { return this.$modeId } + } +}); + +exports.EditSession = EditSession; +}); + +define("ace/search",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"], function(require, exports, module) { +"use strict"; + +var lang = require("./lib/lang"); +var oop = require("./lib/oop"); +var Range = require("./range").Range; + +var Search = function() { + this.$options = {}; +}; + +(function() { + this.set = function(options) { + oop.mixin(this.$options, options); + return this; + }; + this.getOptions = function() { + return lang.copyObject(this.$options); + }; + this.setOptions = function(options) { + this.$options = options; + }; + this.find = function(session) { + var options = this.$options; + var iterator = this.$matchIterator(session, options); + if (!iterator) + return false; + + var firstRange = null; + iterator.forEach(function(range, row, offset) { + if (!range.start) { + var column = range.offset + (offset || 0); + firstRange = new Range(row, column, row, column + range.length); + if (!range.length && options.start && options.start.start + && options.skipCurrent != false && firstRange.isEqual(options.start) + ) { + firstRange = null; + return false; + } + } else + firstRange = range; + return true; + }); + + return firstRange; + }; + this.findAll = function(session) { + var options = this.$options; + if (!options.needle) + return []; + this.$assembleRegExp(options); + + var range = options.range; + var lines = range + ? session.getLines(range.start.row, range.end.row) + : session.doc.getAllLines(); + + var ranges = []; + var re = options.re; + if (options.$isMultiLine) { + var len = re.length; + var maxRow = lines.length - len; + var prevRange; + outer: for (var row = re.offset || 0; row <= maxRow; row++) { + for (var j = 0; j < len; j++) + if (lines[row + j].search(re[j]) == -1) + continue outer; + + var startLine = lines[row]; + var line = lines[row + len - 1]; + var startIndex = startLine.length - startLine.match(re[0])[0].length; + var endIndex = line.match(re[len - 1])[0].length; + + if (prevRange && prevRange.end.row === row && + prevRange.end.column > startIndex + ) { + continue; + } + ranges.push(prevRange = new Range( + row, startIndex, row + len - 1, endIndex + )); + if (len > 2) + row = row + len - 2; + } + } else { + for (var i = 0; i < lines.length; i++) { + var matches = lang.getMatchOffsets(lines[i], re); + for (var j = 0; j < matches.length; j++) { + var match = matches[j]; + ranges.push(new Range(i, match.offset, i, match.offset + match.length)); + } + } + } + + if (range) { + var startColumn = range.start.column; + var endColumn = range.start.column; + var i = 0, j = ranges.length - 1; + while (i < j && ranges[i].start.column < startColumn && ranges[i].start.row == range.start.row) + i++; + + while (i < j && ranges[j].end.column > endColumn && ranges[j].end.row == range.end.row) + j--; + + ranges = ranges.slice(i, j + 1); + for (i = 0, j = ranges.length; i < j; i++) { + ranges[i].start.row += range.start.row; + ranges[i].end.row += range.start.row; + } + } + + return ranges; + }; + this.replace = function(input, replacement) { + var options = this.$options; + + var re = this.$assembleRegExp(options); + if (options.$isMultiLine) + return replacement; + + if (!re) + return; + + var match = re.exec(input); + if (!match || match[0].length != input.length) + return null; + + replacement = input.replace(re, replacement); + if (options.preserveCase) { + replacement = replacement.split(""); + for (var i = Math.min(input.length, input.length); i--; ) { + var ch = input[i]; + if (ch && ch.toLowerCase() != ch) + replacement[i] = replacement[i].toUpperCase(); + else + replacement[i] = replacement[i].toLowerCase(); + } + replacement = replacement.join(""); + } + + return replacement; + }; + + this.$matchIterator = function(session, options) { + var re = this.$assembleRegExp(options); + if (!re) + return false; + + var callback; + if (options.$isMultiLine) { + var len = re.length; + var matchIterator = function(line, row, offset) { + var startIndex = line.search(re[0]); + if (startIndex == -1) + return; + for (var i = 1; i < len; i++) { + line = session.getLine(row + i); + if (line.search(re[i]) == -1) + return; + } + + var endIndex = line.match(re[len - 1])[0].length; + + var range = new Range(row, startIndex, row + len - 1, endIndex); + if (re.offset == 1) { + range.start.row--; + range.start.column = Number.MAX_VALUE; + } else if (offset) + range.start.column += offset; + + if (callback(range)) + return true; + }; + } else if (options.backwards) { + var matchIterator = function(line, row, startIndex) { + var matches = lang.getMatchOffsets(line, re); + for (var i = matches.length-1; i >= 0; i--) + if (callback(matches[i], row, startIndex)) + return true; + }; + } else { + var matchIterator = function(line, row, startIndex) { + var matches = lang.getMatchOffsets(line, re); + for (var i = 0; i < matches.length; i++) + if (callback(matches[i], row, startIndex)) + return true; + }; + } + + var lineIterator = this.$lineIterator(session, options); + + return { + forEach: function(_callback) { + callback = _callback; + lineIterator.forEach(matchIterator); + } + }; + }; + + this.$assembleRegExp = function(options, $disableFakeMultiline) { + if (options.needle instanceof RegExp) + return options.re = options.needle; + + var needle = options.needle; + + if (!options.needle) + return options.re = false; + + if (!options.regExp) + needle = lang.escapeRegExp(needle); + + if (options.wholeWord) + needle = "\\b" + needle + "\\b"; + + var modifier = options.caseSensitive ? "gm" : "gmi"; + + options.$isMultiLine = !$disableFakeMultiline && /[\n\r]/.test(needle); + if (options.$isMultiLine) + return options.re = this.$assembleMultilineRegExp(needle, modifier); + + try { + var re = new RegExp(needle, modifier); + } catch(e) { + re = false; + } + return options.re = re; + }; + + this.$assembleMultilineRegExp = function(needle, modifier) { + var parts = needle.replace(/\r\n|\r|\n/g, "$\n^").split("\n"); + var re = []; + for (var i = 0; i < parts.length; i++) try { + re.push(new RegExp(parts[i], modifier)); + } catch(e) { + return false; + } + if (parts[0] == "") { + re.shift(); + re.offset = 1; + } else { + re.offset = 0; + } + return re; + }; + + this.$lineIterator = function(session, options) { + var backwards = options.backwards == true; + var skipCurrent = options.skipCurrent != false; + + var range = options.range; + var start = options.start; + if (!start) + start = range ? range[backwards ? "end" : "start"] : session.selection.getRange(); + + if (start.start) + start = start[skipCurrent != backwards ? "end" : "start"]; + + var firstRow = range ? range.start.row : 0; + var lastRow = range ? range.end.row : session.getLength() - 1; + + var forEach = backwards ? function(callback) { + var row = start.row; + + var line = session.getLine(row).substring(0, start.column); + if (callback(line, row)) + return; + + for (row--; row >= firstRow; row--) + if (callback(session.getLine(row), row)) + return; + + if (options.wrap == false) + return; + + for (row = lastRow, firstRow = start.row; row >= firstRow; row--) + if (callback(session.getLine(row), row)) + return; + } : function(callback) { + var row = start.row; + + var line = session.getLine(row).substr(start.column); + if (callback(line, row, start.column)) + return; + + for (row = row+1; row <= lastRow; row++) + if (callback(session.getLine(row), row)) + return; + + if (options.wrap == false) + return; + + for (row = firstRow, lastRow = start.row; row <= lastRow; row++) + if (callback(session.getLine(row), row)) + return; + }; + + return {forEach: forEach}; + }; + +}).call(Search.prototype); + +exports.Search = Search; +}); + +define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys","ace/lib/useragent"], function(require, exports, module) { +"use strict"; + +var keyUtil = require("../lib/keys"); +var useragent = require("../lib/useragent"); +var KEY_MODS = keyUtil.KEY_MODS; + +function HashHandler(config, platform) { + this.platform = platform || (useragent.isMac ? "mac" : "win"); + this.commands = {}; + this.commandKeyBinding = {}; + this.addCommands(config); + this.$singleCommand = true; +} + +function MultiHashHandler(config, platform) { + HashHandler.call(this, config, platform); + this.$singleCommand = false; +} + +MultiHashHandler.prototype = HashHandler.prototype; + +(function() { + + + this.addCommand = function(command) { + if (this.commands[command.name]) + this.removeCommand(command); + + this.commands[command.name] = command; + + if (command.bindKey) + this._buildKeyHash(command); + }; + + this.removeCommand = function(command, keepCommand) { + var name = command && (typeof command === 'string' ? command : command.name); + command = this.commands[name]; + if (!keepCommand) + delete this.commands[name]; + var ckb = this.commandKeyBinding; + for (var keyId in ckb) { + var cmdGroup = ckb[keyId]; + if (cmdGroup == command) { + delete ckb[keyId]; + } else if (Array.isArray(cmdGroup)) { + var i = cmdGroup.indexOf(command); + if (i != -1) { + cmdGroup.splice(i, 1); + if (cmdGroup.length == 1) + ckb[keyId] = cmdGroup[0]; + } + } + } + }; + + this.bindKey = function(key, command, asDefault) { + if (typeof key == "object") + key = key[this.platform]; + if (!key) + return; + if (typeof command == "function") + return this.addCommand({exec: command, bindKey: key, name: command.name || key}); + + key.split("|").forEach(function(keyPart) { + var chain = ""; + if (keyPart.indexOf(" ") != -1) { + var parts = keyPart.split(/\s+/); + keyPart = parts.pop(); + parts.forEach(function(keyPart) { + var binding = this.parseKeys(keyPart); + var id = KEY_MODS[binding.hashId] + binding.key; + chain += (chain ? " " : "") + id; + this._addCommandToBinding(chain, "chainKeys"); + }, this); + chain += " "; + } + var binding = this.parseKeys(keyPart); + var id = KEY_MODS[binding.hashId] + binding.key; + this._addCommandToBinding(chain + id, command, asDefault); + }, this); + }; + + this._addCommandToBinding = function(keyId, command, asDefault) { + var ckb = this.commandKeyBinding, i; + if (!command) { + delete ckb[keyId]; + } else if (!ckb[keyId] || this.$singleCommand) { + ckb[keyId] = command; + } else { + if (!Array.isArray(ckb[keyId])) { + ckb[keyId] = [ckb[keyId]]; + } else if ((i = ckb[keyId].indexOf(command)) != -1) { + ckb[keyId].splice(i, 1); + } + + if (asDefault || command.isDefault) + ckb[keyId].unshift(command); + else + ckb[keyId].push(command); + } + }; + + this.addCommands = function(commands) { + commands && Object.keys(commands).forEach(function(name) { + var command = commands[name]; + if (!command) + return; + + if (typeof command === "string") + return this.bindKey(command, name); + + if (typeof command === "function") + command = { exec: command }; + + if (typeof command !== "object") + return; + + if (!command.name) + command.name = name; + + this.addCommand(command); + }, this); + }; + + this.removeCommands = function(commands) { + Object.keys(commands).forEach(function(name) { + this.removeCommand(commands[name]); + }, this); + }; + + this.bindKeys = function(keyList) { + Object.keys(keyList).forEach(function(key) { + this.bindKey(key, keyList[key]); + }, this); + }; + + this._buildKeyHash = function(command) { + this.bindKey(command.bindKey, command); + }; + this.parseKeys = function(keys) { + var parts = keys.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(x){return x}); + var key = parts.pop(); + + var keyCode = keyUtil[key]; + if (keyUtil.FUNCTION_KEYS[keyCode]) + key = keyUtil.FUNCTION_KEYS[keyCode].toLowerCase(); + else if (!parts.length) + return {key: key, hashId: -1}; + else if (parts.length == 1 && parts[0] == "shift") + return {key: key.toUpperCase(), hashId: -1}; + + var hashId = 0; + for (var i = parts.length; i--;) { + var modifier = keyUtil.KEY_MODS[parts[i]]; + if (modifier == null) { + if (typeof console != "undefined") + console.error("invalid modifier " + parts[i] + " in " + keys); + return false; + } + hashId |= modifier; + } + return {key: key, hashId: hashId}; + }; + + this.findKeyCommand = function findKeyCommand(hashId, keyString) { + var key = KEY_MODS[hashId] + keyString; + return this.commandKeyBinding[key]; + }; + + this.handleKeyboard = function(data, hashId, keyString, keyCode) { + var key = KEY_MODS[hashId] + keyString; + var command = this.commandKeyBinding[key]; + if (data.$keyChain) { + data.$keyChain += " " + key; + command = this.commandKeyBinding[data.$keyChain] || command; + } + + if (command) { + if (command == "chainKeys" || command[command.length - 1] == "chainKeys") { + data.$keyChain = data.$keyChain || key; + return {command: "null"}; + } + } + + if (data.$keyChain && keyCode > 0) + data.$keyChain = ""; + return {command: command}; + }; + +}).call(HashHandler.prototype); + +exports.HashHandler = HashHandler; +exports.MultiHashHandler = MultiHashHandler; +}); + +define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var MultiHashHandler = require("../keyboard/hash_handler").MultiHashHandler; +var EventEmitter = require("../lib/event_emitter").EventEmitter; + +var CommandManager = function(platform, commands) { + MultiHashHandler.call(this, commands, platform); + this.byName = this.commands; + this.setDefaultHandler("exec", function(e) { + return e.command.exec(e.editor, e.args || {}); + }); +}; + +oop.inherits(CommandManager, MultiHashHandler); + +(function() { + + oop.implement(this, EventEmitter); + + this.exec = function(command, editor, args) { + if (Array.isArray(command)) { + for (var i = command.length; i--; ) { + if (this.exec(command[i], editor, args)) return true; + } + return false; + } + + if (typeof command === "string") + command = this.commands[command]; + + if (!command) + return false; + + if (editor && editor.$readOnly && !command.readOnly) + return false; + + var e = {editor: editor, command: command, args: args}; + e.returnValue = this._emit("exec", e); + this._signal("afterExec", e); + + return e.returnValue === false ? false : true; + }; + + this.toggleRecording = function(editor) { + if (this.$inReplay) + return; + + editor && editor._emit("changeStatus"); + if (this.recording) { + this.macro.pop(); + this.removeEventListener("exec", this.$addCommandToMacro); + + if (!this.macro.length) + this.macro = this.oldMacro; + + return this.recording = false; + } + if (!this.$addCommandToMacro) { + this.$addCommandToMacro = function(e) { + this.macro.push([e.command, e.args]); + }.bind(this); + } + + this.oldMacro = this.macro; + this.macro = []; + this.on("exec", this.$addCommandToMacro); + return this.recording = true; + }; + + this.replay = function(editor) { + if (this.$inReplay || !this.macro) + return; + + if (this.recording) + return this.toggleRecording(editor); + + try { + this.$inReplay = true; + this.macro.forEach(function(x) { + if (typeof x == "string") + this.exec(x, editor); + else + this.exec(x[0], editor, x[1]); + }, this); + } finally { + this.$inReplay = false; + } + }; + + this.trimMacro = function(m) { + return m.map(function(x){ + if (typeof x[0] != "string") + x[0] = x[0].name; + if (!x[1]) + x = x[0]; + return x; + }); + }; + +}).call(CommandManager.prototype); + +exports.CommandManager = CommandManager; + +}); + +define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config","ace/range"], function(require, exports, module) { +"use strict"; + +var lang = require("../lib/lang"); +var config = require("../config"); +var Range = require("../range").Range; + +function bindKey(win, mac) { + return {win: win, mac: mac}; +} +exports.commands = [{ + name: "showSettingsMenu", + bindKey: bindKey("Ctrl-,", "Command-,"), + exec: function(editor) { + config.loadModule("ace/ext/settings_menu", function(module) { + module.init(editor); + editor.showSettingsMenu(); + }); + }, + readOnly: true +}, { + name: "goToNextError", + bindKey: bindKey("Alt-E", "Ctrl-E"), + exec: function(editor) { + config.loadModule("ace/ext/error_marker", function(module) { + module.showErrorMarker(editor, 1); + }); + }, + scrollIntoView: "animate", + readOnly: true +}, { + name: "goToPreviousError", + bindKey: bindKey("Alt-Shift-E", "Ctrl-Shift-E"), + exec: function(editor) { + config.loadModule("ace/ext/error_marker", function(module) { + module.showErrorMarker(editor, -1); + }); + }, + scrollIntoView: "animate", + readOnly: true +}, { + name: "selectall", + bindKey: bindKey("Ctrl-A", "Command-A"), + exec: function(editor) { editor.selectAll(); }, + readOnly: true +}, { + name: "centerselection", + bindKey: bindKey(null, "Ctrl-L"), + exec: function(editor) { editor.centerSelection(); }, + readOnly: true +}, { + name: "gotoline", + bindKey: bindKey("Ctrl-L", "Command-L"), + exec: function(editor) { + var line = parseInt(prompt("Enter line number:"), 10); + if (!isNaN(line)) { + editor.gotoLine(line); + } + }, + readOnly: true +}, { + name: "fold", + bindKey: bindKey("Alt-L|Ctrl-F1", "Command-Alt-L|Command-F1"), + exec: function(editor) { editor.session.toggleFold(false); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true +}, { + name: "unfold", + bindKey: bindKey("Alt-Shift-L|Ctrl-Shift-F1", "Command-Alt-Shift-L|Command-Shift-F1"), + exec: function(editor) { editor.session.toggleFold(true); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true +}, { + name: "toggleFoldWidget", + bindKey: bindKey("F2", "F2"), + exec: function(editor) { editor.session.toggleFoldWidget(); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true +}, { + name: "toggleParentFoldWidget", + bindKey: bindKey("Alt-F2", "Alt-F2"), + exec: function(editor) { editor.session.toggleFoldWidget(true); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true +}, { + name: "foldall", + bindKey: bindKey(null, "Ctrl-Command-Option-0"), + exec: function(editor) { editor.session.foldAll(); }, + scrollIntoView: "center", + readOnly: true +}, { + name: "foldOther", + bindKey: bindKey("Alt-0", "Command-Option-0"), + exec: function(editor) { + editor.session.foldAll(); + editor.session.unfold(editor.selection.getAllRanges()); + }, + scrollIntoView: "center", + readOnly: true +}, { + name: "unfoldall", + bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"), + exec: function(editor) { editor.session.unfold(); }, + scrollIntoView: "center", + readOnly: true +}, { + name: "findnext", + bindKey: bindKey("Ctrl-K", "Command-G"), + exec: function(editor) { editor.findNext(); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true +}, { + name: "findprevious", + bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"), + exec: function(editor) { editor.findPrevious(); }, + multiSelectAction: "forEach", + scrollIntoView: "center", + readOnly: true +}, { + name: "selectOrFindNext", + bindKey: bindKey("Alt-K", "Ctrl-G"), + exec: function(editor) { + if (editor.selection.isEmpty()) + editor.selection.selectWord(); + else + editor.findNext(); + }, + readOnly: true +}, { + name: "selectOrFindPrevious", + bindKey: bindKey("Alt-Shift-K", "Ctrl-Shift-G"), + exec: function(editor) { + if (editor.selection.isEmpty()) + editor.selection.selectWord(); + else + editor.findPrevious(); + }, + readOnly: true +}, { + name: "find", + bindKey: bindKey("Ctrl-F", "Command-F"), + exec: function(editor) { + config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor)}); + }, + readOnly: true +}, { + name: "overwrite", + bindKey: "Insert", + exec: function(editor) { editor.toggleOverwrite(); }, + readOnly: true +}, { + name: "selecttostart", + bindKey: bindKey("Ctrl-Shift-Home", "Command-Shift-Up"), + exec: function(editor) { editor.getSelection().selectFileStart(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" +}, { + name: "gotostart", + bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"), + exec: function(editor) { editor.navigateFileStart(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" +}, { + name: "selectup", + bindKey: bindKey("Shift-Up", "Shift-Up"), + exec: function(editor) { editor.getSelection().selectUp(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "golineup", + bindKey: bindKey("Up", "Up|Ctrl-P"), + exec: function(editor, args) { editor.navigateUp(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "selecttoend", + bindKey: bindKey("Ctrl-Shift-End", "Command-Shift-Down"), + exec: function(editor) { editor.getSelection().selectFileEnd(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" +}, { + name: "gotoend", + bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"), + exec: function(editor) { editor.navigateFileEnd(); }, + multiSelectAction: "forEach", + readOnly: true, + scrollIntoView: "animate", + aceCommandGroup: "fileJump" +}, { + name: "selectdown", + bindKey: bindKey("Shift-Down", "Shift-Down"), + exec: function(editor) { editor.getSelection().selectDown(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "golinedown", + bindKey: bindKey("Down", "Down|Ctrl-N"), + exec: function(editor, args) { editor.navigateDown(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "selectwordleft", + bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"), + exec: function(editor) { editor.getSelection().selectWordLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "gotowordleft", + bindKey: bindKey("Ctrl-Left", "Option-Left"), + exec: function(editor) { editor.navigateWordLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "selecttolinestart", + bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"), + exec: function(editor) { editor.getSelection().selectLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "gotolinestart", + bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"), + exec: function(editor) { editor.navigateLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "selectleft", + bindKey: bindKey("Shift-Left", "Shift-Left"), + exec: function(editor) { editor.getSelection().selectLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "gotoleft", + bindKey: bindKey("Left", "Left|Ctrl-B"), + exec: function(editor, args) { editor.navigateLeft(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "selectwordright", + bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"), + exec: function(editor) { editor.getSelection().selectWordRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "gotowordright", + bindKey: bindKey("Ctrl-Right", "Option-Right"), + exec: function(editor) { editor.navigateWordRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "selecttolineend", + bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"), + exec: function(editor) { editor.getSelection().selectLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "gotolineend", + bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"), + exec: function(editor) { editor.navigateLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "selectright", + bindKey: bindKey("Shift-Right", "Shift-Right"), + exec: function(editor) { editor.getSelection().selectRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "gotoright", + bindKey: bindKey("Right", "Right|Ctrl-F"), + exec: function(editor, args) { editor.navigateRight(args.times); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "selectpagedown", + bindKey: "Shift-PageDown", + exec: function(editor) { editor.selectPageDown(); }, + readOnly: true +}, { + name: "pagedown", + bindKey: bindKey(null, "Option-PageDown"), + exec: function(editor) { editor.scrollPageDown(); }, + readOnly: true +}, { + name: "gotopagedown", + bindKey: bindKey("PageDown", "PageDown|Ctrl-V"), + exec: function(editor) { editor.gotoPageDown(); }, + readOnly: true +}, { + name: "selectpageup", + bindKey: "Shift-PageUp", + exec: function(editor) { editor.selectPageUp(); }, + readOnly: true +}, { + name: "pageup", + bindKey: bindKey(null, "Option-PageUp"), + exec: function(editor) { editor.scrollPageUp(); }, + readOnly: true +}, { + name: "gotopageup", + bindKey: "PageUp", + exec: function(editor) { editor.gotoPageUp(); }, + readOnly: true +}, { + name: "scrollup", + bindKey: bindKey("Ctrl-Up", null), + exec: function(e) { e.renderer.scrollBy(0, -2 * e.renderer.layerConfig.lineHeight); }, + readOnly: true +}, { + name: "scrolldown", + bindKey: bindKey("Ctrl-Down", null), + exec: function(e) { e.renderer.scrollBy(0, 2 * e.renderer.layerConfig.lineHeight); }, + readOnly: true +}, { + name: "selectlinestart", + bindKey: "Shift-Home", + exec: function(editor) { editor.getSelection().selectLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "selectlineend", + bindKey: "Shift-End", + exec: function(editor) { editor.getSelection().selectLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "togglerecording", + bindKey: bindKey("Ctrl-Alt-E", "Command-Option-E"), + exec: function(editor) { editor.commands.toggleRecording(editor); }, + readOnly: true +}, { + name: "replaymacro", + bindKey: bindKey("Ctrl-Shift-E", "Command-Shift-E"), + exec: function(editor) { editor.commands.replay(editor); }, + readOnly: true +}, { + name: "jumptomatching", + bindKey: bindKey("Ctrl-P", "Ctrl-P"), + exec: function(editor) { editor.jumpToMatching(); }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: true +}, { + name: "selecttomatching", + bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"), + exec: function(editor) { editor.jumpToMatching(true); }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: true +}, { + name: "expandToMatching", + bindKey: bindKey("Ctrl-Shift-M", "Ctrl-Shift-M"), + exec: function(editor) { editor.jumpToMatching(true, true); }, + multiSelectAction: "forEach", + scrollIntoView: "animate", + readOnly: true +}, { + name: "passKeysToBrowser", + bindKey: bindKey(null, null), + exec: function() {}, + passEvent: true, + readOnly: true +}, +{ + name: "cut", + exec: function(editor) { + var range = editor.getSelectionRange(); + editor._emit("cut", range); + + if (!editor.selection.isEmpty()) { + editor.session.remove(range); + editor.clearSelection(); + } + }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" +}, { + name: "removeline", + bindKey: bindKey("Ctrl-D", "Command-D"), + exec: function(editor) { editor.removeLines(); }, + scrollIntoView: "cursor", + multiSelectAction: "forEachLine" +}, { + name: "duplicateSelection", + bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"), + exec: function(editor) { editor.duplicateSelection(); }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" +}, { + name: "sortlines", + bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"), + exec: function(editor) { editor.sortLines(); }, + scrollIntoView: "selection", + multiSelectAction: "forEachLine" +}, { + name: "togglecomment", + bindKey: bindKey("Ctrl-/", "Command-/"), + exec: function(editor) { editor.toggleCommentLines(); }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart" +}, { + name: "toggleBlockComment", + bindKey: bindKey("Ctrl-Shift-/", "Command-Shift-/"), + exec: function(editor) { editor.toggleBlockComment(); }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart" +}, { + name: "modifyNumberUp", + bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"), + exec: function(editor) { editor.modifyNumber(1); }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" +}, { + name: "modifyNumberDown", + bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"), + exec: function(editor) { editor.modifyNumber(-1); }, + scrollIntoView: "cursor", + multiSelectAction: "forEach" +}, { + name: "replace", + bindKey: bindKey("Ctrl-H", "Command-Option-F"), + exec: function(editor) { + config.loadModule("ace/ext/searchbox", function(e) {e.Search(editor, true)}); + } +}, { + name: "undo", + bindKey: bindKey("Ctrl-Z", "Command-Z"), + exec: function(editor) { editor.undo(); } +}, { + name: "redo", + bindKey: bindKey("Ctrl-Shift-Z|Ctrl-Y", "Command-Shift-Z|Command-Y"), + exec: function(editor) { editor.redo(); } +}, { + name: "copylinesup", + bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"), + exec: function(editor) { editor.copyLinesUp(); }, + scrollIntoView: "cursor" +}, { + name: "movelinesup", + bindKey: bindKey("Alt-Up", "Option-Up"), + exec: function(editor) { editor.moveLinesUp(); }, + scrollIntoView: "cursor" +}, { + name: "copylinesdown", + bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"), + exec: function(editor) { editor.copyLinesDown(); }, + scrollIntoView: "cursor" +}, { + name: "movelinesdown", + bindKey: bindKey("Alt-Down", "Option-Down"), + exec: function(editor) { editor.moveLinesDown(); }, + scrollIntoView: "cursor" +}, { + name: "del", + bindKey: bindKey("Delete", "Delete|Ctrl-D|Shift-Delete"), + exec: function(editor) { editor.remove("right"); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "backspace", + bindKey: bindKey( + "Shift-Backspace|Backspace", + "Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H" + ), + exec: function(editor) { editor.remove("left"); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "cut_or_delete", + bindKey: bindKey("Shift-Delete", null), + exec: function(editor) { + if (editor.selection.isEmpty()) { + editor.remove("left"); + } else { + return false; + } + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "removetolinestart", + bindKey: bindKey("Alt-Backspace", "Command-Backspace"), + exec: function(editor) { editor.removeToLineStart(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "removetolineend", + bindKey: bindKey("Alt-Delete", "Ctrl-K"), + exec: function(editor) { editor.removeToLineEnd(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "removewordleft", + bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"), + exec: function(editor) { editor.removeWordLeft(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "removewordright", + bindKey: bindKey("Ctrl-Delete", "Alt-Delete"), + exec: function(editor) { editor.removeWordRight(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "outdent", + bindKey: bindKey("Shift-Tab", "Shift-Tab"), + exec: function(editor) { editor.blockOutdent(); }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart" +}, { + name: "indent", + bindKey: bindKey("Tab", "Tab"), + exec: function(editor) { editor.indent(); }, + multiSelectAction: "forEach", + scrollIntoView: "selectionPart" +}, { + name: "blockoutdent", + bindKey: bindKey("Ctrl-[", "Ctrl-["), + exec: function(editor) { editor.blockOutdent(); }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart" +}, { + name: "blockindent", + bindKey: bindKey("Ctrl-]", "Ctrl-]"), + exec: function(editor) { editor.blockIndent(); }, + multiSelectAction: "forEachLine", + scrollIntoView: "selectionPart" +}, { + name: "insertstring", + exec: function(editor, str) { editor.insert(str); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "inserttext", + exec: function(editor, args) { + editor.insert(lang.stringRepeat(args.text || "", args.times || 1)); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "splitline", + bindKey: bindKey(null, "Ctrl-O"), + exec: function(editor) { editor.splitLine(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "transposeletters", + bindKey: bindKey("Ctrl-T", "Ctrl-T"), + exec: function(editor) { editor.transposeLetters(); }, + multiSelectAction: function(editor) {editor.transposeSelections(1); }, + scrollIntoView: "cursor" +}, { + name: "touppercase", + bindKey: bindKey("Ctrl-U", "Ctrl-U"), + exec: function(editor) { editor.toUpperCase(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "tolowercase", + bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"), + exec: function(editor) { editor.toLowerCase(); }, + multiSelectAction: "forEach", + scrollIntoView: "cursor" +}, { + name: "expandtoline", + bindKey: bindKey("Ctrl-Shift-L", "Command-Shift-L"), + exec: function(editor) { + var range = editor.selection.getRange(); + + range.start.column = range.end.column = 0; + range.end.row++; + editor.selection.setRange(range, false); + }, + multiSelectAction: "forEach", + scrollIntoView: "cursor", + readOnly: true +}, { + name: "joinlines", + bindKey: bindKey(null, null), + exec: function(editor) { + var isBackwards = editor.selection.isBackwards(); + var selectionStart = isBackwards ? editor.selection.getSelectionLead() : editor.selection.getSelectionAnchor(); + var selectionEnd = isBackwards ? editor.selection.getSelectionAnchor() : editor.selection.getSelectionLead(); + var firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length; + var selectedText = editor.session.doc.getTextRange(editor.selection.getRange()); + var selectedCount = selectedText.replace(/\n\s*/, " ").length; + var insertLine = editor.session.doc.getLine(selectionStart.row); + + for (var i = selectionStart.row + 1; i <= selectionEnd.row + 1; i++) { + var curLine = lang.stringTrimLeft(lang.stringTrimRight(editor.session.doc.getLine(i))); + if (curLine.length !== 0) { + curLine = " " + curLine; + } + insertLine += curLine; + } + + if (selectionEnd.row + 1 < (editor.session.doc.getLength() - 1)) { + insertLine += editor.session.doc.getNewLineCharacter(); + } + + editor.clearSelection(); + editor.session.doc.replace(new Range(selectionStart.row, 0, selectionEnd.row + 2, 0), insertLine); + + if (selectedCount > 0) { + editor.selection.moveCursorTo(selectionStart.row, selectionStart.column); + editor.selection.selectTo(selectionStart.row, selectionStart.column + selectedCount); + } else { + firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length > firstLineEndCol ? (firstLineEndCol + 1) : firstLineEndCol; + editor.selection.moveCursorTo(selectionStart.row, firstLineEndCol); + } + }, + multiSelectAction: "forEach", + readOnly: true +}, { + name: "invertSelection", + bindKey: bindKey(null, null), + exec: function(editor) { + var endRow = editor.session.doc.getLength() - 1; + var endCol = editor.session.doc.getLine(endRow).length; + var ranges = editor.selection.rangeList.ranges; + var newRanges = []; + if (ranges.length < 1) { + ranges = [editor.selection.getRange()]; + } + + for (var i = 0; i < ranges.length; i++) { + if (i == (ranges.length - 1)) { + if (!(ranges[i].end.row === endRow && ranges[i].end.column === endCol)) { + newRanges.push(new Range(ranges[i].end.row, ranges[i].end.column, endRow, endCol)); + } + } + + if (i === 0) { + if (!(ranges[i].start.row === 0 && ranges[i].start.column === 0)) { + newRanges.push(new Range(0, 0, ranges[i].start.row, ranges[i].start.column)); + } + } else { + newRanges.push(new Range(ranges[i-1].end.row, ranges[i-1].end.column, ranges[i].start.row, ranges[i].start.column)); + } + } + + editor.exitMultiSelectMode(); + editor.clearSelection(); + + for(var i = 0; i < newRanges.length; i++) { + editor.selection.addRange(newRanges[i], false); + } + }, + readOnly: true, + scrollIntoView: "none" +}]; + +}); + +define("ace/editor",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/keyboard/textinput","ace/mouse/mouse_handler","ace/mouse/fold_handler","ace/keyboard/keybinding","ace/edit_session","ace/search","ace/range","ace/lib/event_emitter","ace/commands/command_manager","ace/commands/default_commands","ace/config","ace/token_iterator"], function(require, exports, module) { +"use strict"; + +require("./lib/fixoldbrowsers"); + +var oop = require("./lib/oop"); +var dom = require("./lib/dom"); +var lang = require("./lib/lang"); +var useragent = require("./lib/useragent"); +var TextInput = require("./keyboard/textinput").TextInput; +var MouseHandler = require("./mouse/mouse_handler").MouseHandler; +var FoldHandler = require("./mouse/fold_handler").FoldHandler; +var KeyBinding = require("./keyboard/keybinding").KeyBinding; +var EditSession = require("./edit_session").EditSession; +var Search = require("./search").Search; +var Range = require("./range").Range; +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var CommandManager = require("./commands/command_manager").CommandManager; +var defaultCommands = require("./commands/default_commands").commands; +var config = require("./config"); +var TokenIterator = require("./token_iterator").TokenIterator; +var Editor = function(renderer, session) { + var container = renderer.getContainerElement(); + this.container = container; + this.renderer = renderer; + + this.commands = new CommandManager(useragent.isMac ? "mac" : "win", defaultCommands); + this.textInput = new TextInput(renderer.getTextAreaContainer(), this); + this.renderer.textarea = this.textInput.getElement(); + this.keyBinding = new KeyBinding(this); + this.$mouseHandler = new MouseHandler(this); + new FoldHandler(this); + + this.$blockScrolling = 0; + this.$search = new Search().set({ + wrap: true + }); + + this.$historyTracker = this.$historyTracker.bind(this); + this.commands.on("exec", this.$historyTracker); + + this.$initOperationListeners(); + + this._$emitInputEvent = lang.delayedCall(function() { + this._signal("input", {}); + if (this.session && this.session.bgTokenizer) + this.session.bgTokenizer.scheduleStart(); + }.bind(this)); + + this.on("change", function(_, _self) { + _self._$emitInputEvent.schedule(31); + }); + + this.setSession(session || new EditSession("")); + config.resetOptions(this); + config._signal("editor", this); +}; + +(function(){ + + oop.implement(this, EventEmitter); + + this.$initOperationListeners = function() { + function last(a) {return a[a.length - 1]} + + this.selections = []; + this.commands.on("exec", this.startOperation.bind(this), true); + this.commands.on("afterExec", this.endOperation.bind(this), true); + + this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this)); + + this.on("change", function() { + this.curOp || this.startOperation(); + this.curOp.docChanged = true; + }.bind(this), true); + + this.on("changeSelection", function() { + this.curOp || this.startOperation(); + this.curOp.selectionChanged = true; + }.bind(this), true); + }; + + this.curOp = null; + this.prevOp = {}; + this.startOperation = function(commadEvent) { + if (this.curOp) { + if (!commadEvent || this.curOp.command) + return; + this.prevOp = this.curOp; + } + if (!commadEvent) { + this.previousCommand = null; + commadEvent = {}; + } + + this.$opResetTimer.schedule(); + this.curOp = { + command: commadEvent.command || {}, + args: commadEvent.args, + scrollTop: this.renderer.scrollTop + }; + if (this.curOp.command.name) + this.$blockScrolling++; + }; + + this.endOperation = function(e) { + if (this.curOp) { + if (e && e.returnValue === false) + return this.curOp = null; + this._signal("beforeEndOperation"); + var command = this.curOp.command; + if (command.name && this.$blockScrolling) + this.$blockScrolling--; + if (command && command.scrollIntoView) { + switch (command.scrollIntoView) { + case "center": + this.renderer.scrollCursorIntoView(null, 0.5); + break; + case "animate": + case "cursor": + this.renderer.scrollCursorIntoView(); + break; + case "selectionPart": + var range = this.selection.getRange(); + var config = this.renderer.layerConfig; + if (range.start.row >= config.lastRow || range.end.row <= config.firstRow) { + this.renderer.scrollSelectionIntoView(this.selection.anchor, this.selection.lead); + } + break; + default: + break; + } + if (command.scrollIntoView == "animate") + this.renderer.animateScrolling(this.curOp.scrollTop); + } + + this.prevOp = this.curOp; + this.curOp = null; + } + }; + this.$mergeableCommands = ["backspace", "del", "insertstring"]; + this.$historyTracker = function(e) { + if (!this.$mergeUndoDeltas) + return; + + var prev = this.prevOp; + var mergeableCommands = this.$mergeableCommands; + var shouldMerge = prev.command && (e.command.name == prev.command.name); + if (e.command.name == "insertstring") { + var text = e.args; + if (this.mergeNextCommand === undefined) + this.mergeNextCommand = true; + + shouldMerge = shouldMerge + && this.mergeNextCommand // previous command allows to coalesce with + && (!/\s/.test(text) || /\s/.test(prev.args)); // previous insertion was of same type + + this.mergeNextCommand = true; + } else { + shouldMerge = shouldMerge + && mergeableCommands.indexOf(e.command.name) !== -1; // the command is mergeable + } + + if ( + this.$mergeUndoDeltas != "always" + && Date.now() - this.sequenceStartTime > 2000 + ) { + shouldMerge = false; // the sequence is too long + } + + if (shouldMerge) + this.session.mergeUndoDeltas = true; + else if (mergeableCommands.indexOf(e.command.name) !== -1) + this.sequenceStartTime = Date.now(); + }; + this.setKeyboardHandler = function(keyboardHandler, cb) { + if (keyboardHandler && typeof keyboardHandler === "string") { + this.$keybindingId = keyboardHandler; + var _self = this; + config.loadModule(["keybinding", keyboardHandler], function(module) { + if (_self.$keybindingId == keyboardHandler) + _self.keyBinding.setKeyboardHandler(module && module.handler); + cb && cb(); + }); + } else { + this.$keybindingId = null; + this.keyBinding.setKeyboardHandler(keyboardHandler); + cb && cb(); + } + }; + this.getKeyboardHandler = function() { + return this.keyBinding.getKeyboardHandler(); + }; + this.setSession = function(session) { + if (this.session == session) + return; + + var oldSession = this.session; + if (oldSession) { + this.session.removeEventListener("change", this.$onDocumentChange); + this.session.removeEventListener("changeMode", this.$onChangeMode); + this.session.removeEventListener("tokenizerUpdate", this.$onTokenizerUpdate); + this.session.removeEventListener("changeTabSize", this.$onChangeTabSize); + this.session.removeEventListener("changeWrapLimit", this.$onChangeWrapLimit); + this.session.removeEventListener("changeWrapMode", this.$onChangeWrapMode); + this.session.removeEventListener("onChangeFold", this.$onChangeFold); + this.session.removeEventListener("changeFrontMarker", this.$onChangeFrontMarker); + this.session.removeEventListener("changeBackMarker", this.$onChangeBackMarker); + this.session.removeEventListener("changeBreakpoint", this.$onChangeBreakpoint); + this.session.removeEventListener("changeAnnotation", this.$onChangeAnnotation); + this.session.removeEventListener("changeOverwrite", this.$onCursorChange); + this.session.removeEventListener("changeScrollTop", this.$onScrollTopChange); + this.session.removeEventListener("changeScrollLeft", this.$onScrollLeftChange); + + var selection = this.session.getSelection(); + selection.removeEventListener("changeCursor", this.$onCursorChange); + selection.removeEventListener("changeSelection", this.$onSelectionChange); + } + + this.session = session; + if (session) { + this.$onDocumentChange = this.onDocumentChange.bind(this); + session.addEventListener("change", this.$onDocumentChange); + this.renderer.setSession(session); + + this.$onChangeMode = this.onChangeMode.bind(this); + session.addEventListener("changeMode", this.$onChangeMode); + + this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this); + session.addEventListener("tokenizerUpdate", this.$onTokenizerUpdate); + + this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer); + session.addEventListener("changeTabSize", this.$onChangeTabSize); + + this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this); + session.addEventListener("changeWrapLimit", this.$onChangeWrapLimit); + + this.$onChangeWrapMode = this.onChangeWrapMode.bind(this); + session.addEventListener("changeWrapMode", this.$onChangeWrapMode); + + this.$onChangeFold = this.onChangeFold.bind(this); + session.addEventListener("changeFold", this.$onChangeFold); + + this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this); + this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker); + + this.$onChangeBackMarker = this.onChangeBackMarker.bind(this); + this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker); + + this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this); + this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint); + + this.$onChangeAnnotation = this.onChangeAnnotation.bind(this); + this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation); + + this.$onCursorChange = this.onCursorChange.bind(this); + this.session.addEventListener("changeOverwrite", this.$onCursorChange); + + this.$onScrollTopChange = this.onScrollTopChange.bind(this); + this.session.addEventListener("changeScrollTop", this.$onScrollTopChange); + + this.$onScrollLeftChange = this.onScrollLeftChange.bind(this); + this.session.addEventListener("changeScrollLeft", this.$onScrollLeftChange); + + this.selection = session.getSelection(); + this.selection.addEventListener("changeCursor", this.$onCursorChange); + + this.$onSelectionChange = this.onSelectionChange.bind(this); + this.selection.addEventListener("changeSelection", this.$onSelectionChange); + + this.onChangeMode(); + + this.$blockScrolling += 1; + this.onCursorChange(); + this.$blockScrolling -= 1; + + this.onScrollTopChange(); + this.onScrollLeftChange(); + this.onSelectionChange(); + this.onChangeFrontMarker(); + this.onChangeBackMarker(); + this.onChangeBreakpoint(); + this.onChangeAnnotation(); + this.session.getUseWrapMode() && this.renderer.adjustWrapLimit(); + this.renderer.updateFull(); + } else { + this.selection = null; + this.renderer.setSession(session); + } + + this._signal("changeSession", { + session: session, + oldSession: oldSession + }); + + oldSession && oldSession._signal("changeEditor", {oldEditor: this}); + session && session._signal("changeEditor", {editor: this}); + }; + this.getSession = function() { + return this.session; + }; + this.setValue = function(val, cursorPos) { + this.session.doc.setValue(val); + + if (!cursorPos) + this.selectAll(); + else if (cursorPos == 1) + this.navigateFileEnd(); + else if (cursorPos == -1) + this.navigateFileStart(); + + return val; + }; + this.getValue = function() { + return this.session.getValue(); + }; + this.getSelection = function() { + return this.selection; + }; + this.resize = function(force) { + this.renderer.onResize(force); + }; + this.setTheme = function(theme, cb) { + this.renderer.setTheme(theme, cb); + }; + this.getTheme = function() { + return this.renderer.getTheme(); + }; + this.setStyle = function(style) { + this.renderer.setStyle(style); + }; + this.unsetStyle = function(style) { + this.renderer.unsetStyle(style); + }; + this.getFontSize = function () { + return this.getOption("fontSize") || + dom.computedStyle(this.container, "fontSize"); + }; + this.setFontSize = function(size) { + this.setOption("fontSize", size); + }; + + this.$highlightBrackets = function() { + if (this.session.$bracketHighlight) { + this.session.removeMarker(this.session.$bracketHighlight); + this.session.$bracketHighlight = null; + } + + if (this.$highlightPending) { + return; + } + var self = this; + this.$highlightPending = true; + setTimeout(function() { + self.$highlightPending = false; + var session = self.session; + if (!session || !session.bgTokenizer) return; + var pos = session.findMatchingBracket(self.getCursorPosition()); + if (pos) { + var range = new Range(pos.row, pos.column, pos.row, pos.column + 1); + } else if (session.$mode.getMatching) { + var range = session.$mode.getMatching(self.session); + } + if (range) + session.$bracketHighlight = session.addMarker(range, "ace_bracket", "text"); + }, 50); + }; + this.$highlightTags = function() { + if (this.$highlightTagPending) + return; + var self = this; + this.$highlightTagPending = true; + setTimeout(function() { + self.$highlightTagPending = false; + + var session = self.session; + if (!session || !session.bgTokenizer) return; + + var pos = self.getCursorPosition(); + var iterator = new TokenIterator(self.session, pos.row, pos.column); + var token = iterator.getCurrentToken(); + + if (!token || !/\b(?:tag-open|tag-name)/.test(token.type)) { + session.removeMarker(session.$tagHighlight); + session.$tagHighlight = null; + return; + } + + if (token.type.indexOf("tag-open") != -1) { + token = iterator.stepForward(); + if (!token) + return; + } + + var tag = token.value; + var depth = 0; + var prevToken = iterator.stepBackward(); + + if (prevToken.value == '<'){ + do { + prevToken = token; + token = iterator.stepForward(); + + if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) { + if (prevToken.value === '<'){ + depth++; + } else if (prevToken.value === '= 0); + } else { + do { + token = prevToken; + prevToken = iterator.stepBackward(); + + if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) { + if (prevToken.value === '<') { + depth++; + } else if (prevToken.value === ' 1)) + highlight = false; + } + + if (session.$highlightLineMarker && !highlight) { + session.removeMarker(session.$highlightLineMarker.id); + session.$highlightLineMarker = null; + } else if (!session.$highlightLineMarker && highlight) { + var range = new Range(highlight.row, highlight.column, highlight.row, Infinity); + range.id = session.addMarker(range, "ace_active-line", "screenLine"); + session.$highlightLineMarker = range; + } else if (highlight) { + session.$highlightLineMarker.start.row = highlight.row; + session.$highlightLineMarker.end.row = highlight.row; + session.$highlightLineMarker.start.column = highlight.column; + session._signal("changeBackMarker"); + } + }; + + this.onSelectionChange = function(e) { + var session = this.session; + + if (session.$selectionMarker) { + session.removeMarker(session.$selectionMarker); + } + session.$selectionMarker = null; + + if (!this.selection.isEmpty()) { + var range = this.selection.getRange(); + var style = this.getSelectionStyle(); + session.$selectionMarker = session.addMarker(range, "ace_selection", style); + } else { + this.$updateHighlightActiveLine(); + } + + var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp(); + this.session.highlight(re); + + this._signal("changeSelection"); + }; + + this.$getSelectionHighLightRegexp = function() { + var session = this.session; + + var selection = this.getSelectionRange(); + if (selection.isEmpty() || selection.isMultiLine()) + return; + + var startOuter = selection.start.column - 1; + var endOuter = selection.end.column + 1; + var line = session.getLine(selection.start.row); + var lineCols = line.length; + var needle = line.substring(Math.max(startOuter, 0), + Math.min(endOuter, lineCols)); + if ((startOuter >= 0 && /^[\w\d]/.test(needle)) || + (endOuter <= lineCols && /[\w\d]$/.test(needle))) + return; + + needle = line.substring(selection.start.column, selection.end.column); + if (!/^[\w\d]+$/.test(needle)) + return; + + var re = this.$search.$assembleRegExp({ + wholeWord: true, + caseSensitive: true, + needle: needle + }); + + return re; + }; + + + this.onChangeFrontMarker = function() { + this.renderer.updateFrontMarkers(); + }; + + this.onChangeBackMarker = function() { + this.renderer.updateBackMarkers(); + }; + + + this.onChangeBreakpoint = function() { + this.renderer.updateBreakpoints(); + }; + + this.onChangeAnnotation = function() { + this.renderer.setAnnotations(this.session.getAnnotations()); + }; + + + this.onChangeMode = function(e) { + this.renderer.updateText(); + this._emit("changeMode", e); + }; + + + this.onChangeWrapLimit = function() { + this.renderer.updateFull(); + }; + + this.onChangeWrapMode = function() { + this.renderer.onResize(true); + }; + + + this.onChangeFold = function() { + this.$updateHighlightActiveLine(); + this.renderer.updateFull(); + }; + this.getSelectedText = function() { + return this.session.getTextRange(this.getSelectionRange()); + }; + this.getCopyText = function() { + var text = this.getSelectedText(); + this._signal("copy", text); + return text; + }; + this.onCopy = function() { + this.commands.exec("copy", this); + }; + this.onCut = function() { + this.commands.exec("cut", this); + }; + this.onPaste = function(text) { + if (this.$readOnly) + return; + + var e = {text: text}; + this._signal("paste", e); + text = e.text; + if (!this.inMultiSelectMode || this.inVirtualSelectionMode) { + this.insert(text); + } else { + var lines = text.split(/\r\n|\r|\n/); + var ranges = this.selection.rangeList.ranges; + + if (lines.length > ranges.length || lines.length < 2 || !lines[1]) + return this.commands.exec("insertstring", this, text); + + for (var i = ranges.length; i--;) { + var range = ranges[i]; + if (!range.isEmpty()) + this.session.remove(range); + + this.session.insert(range.start, lines[i]); + } + } + this.renderer.scrollCursorIntoView(); + }; + + this.execCommand = function(command, args) { + return this.commands.exec(command, this, args); + }; + this.insert = function(text, pasted) { + var session = this.session; + var mode = session.getMode(); + var cursor = this.getCursorPosition(); + + if (this.getBehavioursEnabled() && !pasted) { + var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text); + if (transform) { + if (text !== transform.text) { + this.session.mergeUndoDeltas = false; + this.$mergeNextCommand = false; + } + text = transform.text; + + } + } + + if (text == "\t") + text = this.session.getTabString(); + if (!this.selection.isEmpty()) { + var range = this.getSelectionRange(); + cursor = this.session.remove(range); + this.clearSelection(); + } + else if (this.session.getOverwrite()) { + var range = new Range.fromPoints(cursor, cursor); + range.end.column += text.length; + this.session.remove(range); + } + + if (text == "\n" || text == "\r\n") { + var line = session.getLine(cursor.row); + if (cursor.column > line.search(/\S|$/)) { + var d = line.substr(cursor.column).search(/\S|$/); + session.doc.removeInLine(cursor.row, cursor.column, cursor.column + d); + } + } + this.clearSelection(); + + var start = cursor.column; + var lineState = session.getState(cursor.row); + var line = session.getLine(cursor.row); + var shouldOutdent = mode.checkOutdent(lineState, line, text); + var end = session.insert(cursor, text); + + if (transform && transform.selection) { + if (transform.selection.length == 2) { // Transform relative to the current column + this.selection.setSelectionRange( + new Range(cursor.row, start + transform.selection[0], + cursor.row, start + transform.selection[1])); + } else { // Transform relative to the current row. + this.selection.setSelectionRange( + new Range(cursor.row + transform.selection[0], + transform.selection[1], + cursor.row + transform.selection[2], + transform.selection[3])); + } + } + + if (session.getDocument().isNewLine(text)) { + var lineIndent = mode.getNextLineIndent(lineState, line.slice(0, cursor.column), session.getTabString()); + + session.insert({row: cursor.row+1, column: 0}, lineIndent); + } + if (shouldOutdent) + mode.autoOutdent(lineState, session, cursor.row); + }; + + this.onTextInput = function(text) { + this.keyBinding.onTextInput(text); + }; + + this.onCommandKey = function(e, hashId, keyCode) { + this.keyBinding.onCommandKey(e, hashId, keyCode); + }; + this.setOverwrite = function(overwrite) { + this.session.setOverwrite(overwrite); + }; + this.getOverwrite = function() { + return this.session.getOverwrite(); + }; + this.toggleOverwrite = function() { + this.session.toggleOverwrite(); + }; + this.setScrollSpeed = function(speed) { + this.setOption("scrollSpeed", speed); + }; + this.getScrollSpeed = function() { + return this.getOption("scrollSpeed"); + }; + this.setDragDelay = function(dragDelay) { + this.setOption("dragDelay", dragDelay); + }; + this.getDragDelay = function() { + return this.getOption("dragDelay"); + }; + this.setSelectionStyle = function(val) { + this.setOption("selectionStyle", val); + }; + this.getSelectionStyle = function() { + return this.getOption("selectionStyle"); + }; + this.setHighlightActiveLine = function(shouldHighlight) { + this.setOption("highlightActiveLine", shouldHighlight); + }; + this.getHighlightActiveLine = function() { + return this.getOption("highlightActiveLine"); + }; + this.setHighlightGutterLine = function(shouldHighlight) { + this.setOption("highlightGutterLine", shouldHighlight); + }; + + this.getHighlightGutterLine = function() { + return this.getOption("highlightGutterLine"); + }; + this.setHighlightSelectedWord = function(shouldHighlight) { + this.setOption("highlightSelectedWord", shouldHighlight); + }; + this.getHighlightSelectedWord = function() { + return this.$highlightSelectedWord; + }; + + this.setAnimatedScroll = function(shouldAnimate){ + this.renderer.setAnimatedScroll(shouldAnimate); + }; + + this.getAnimatedScroll = function(){ + return this.renderer.getAnimatedScroll(); + }; + this.setShowInvisibles = function(showInvisibles) { + this.renderer.setShowInvisibles(showInvisibles); + }; + this.getShowInvisibles = function() { + return this.renderer.getShowInvisibles(); + }; + + this.setDisplayIndentGuides = function(display) { + this.renderer.setDisplayIndentGuides(display); + }; + + this.getDisplayIndentGuides = function() { + return this.renderer.getDisplayIndentGuides(); + }; + this.setShowPrintMargin = function(showPrintMargin) { + this.renderer.setShowPrintMargin(showPrintMargin); + }; + this.getShowPrintMargin = function() { + return this.renderer.getShowPrintMargin(); + }; + this.setPrintMarginColumn = function(showPrintMargin) { + this.renderer.setPrintMarginColumn(showPrintMargin); + }; + this.getPrintMarginColumn = function() { + return this.renderer.getPrintMarginColumn(); + }; + this.setReadOnly = function(readOnly) { + this.setOption("readOnly", readOnly); + }; + this.getReadOnly = function() { + return this.getOption("readOnly"); + }; + this.setBehavioursEnabled = function (enabled) { + this.setOption("behavioursEnabled", enabled); + }; + this.getBehavioursEnabled = function () { + return this.getOption("behavioursEnabled"); + }; + this.setWrapBehavioursEnabled = function (enabled) { + this.setOption("wrapBehavioursEnabled", enabled); + }; + this.getWrapBehavioursEnabled = function () { + return this.getOption("wrapBehavioursEnabled"); + }; + this.setShowFoldWidgets = function(show) { + this.setOption("showFoldWidgets", show); + + }; + this.getShowFoldWidgets = function() { + return this.getOption("showFoldWidgets"); + }; + + this.setFadeFoldWidgets = function(fade) { + this.setOption("fadeFoldWidgets", fade); + }; + + this.getFadeFoldWidgets = function() { + return this.getOption("fadeFoldWidgets"); + }; + this.remove = function(dir) { + if (this.selection.isEmpty()){ + if (dir == "left") + this.selection.selectLeft(); + else + this.selection.selectRight(); + } + + var range = this.getSelectionRange(); + if (this.getBehavioursEnabled()) { + var session = this.session; + var state = session.getState(range.start.row); + var new_range = session.getMode().transformAction(state, 'deletion', this, session, range); + + if (range.end.column === 0) { + var text = session.getTextRange(range); + if (text[text.length - 1] == "\n") { + var line = session.getLine(range.end.row); + if (/^\s+$/.test(line)) { + range.end.column = line.length; + } + } + } + if (new_range) + range = new_range; + } + + this.session.remove(range); + this.clearSelection(); + }; + this.removeWordRight = function() { + if (this.selection.isEmpty()) + this.selection.selectWordRight(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeWordLeft = function() { + if (this.selection.isEmpty()) + this.selection.selectWordLeft(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeToLineStart = function() { + if (this.selection.isEmpty()) + this.selection.selectLineStart(); + + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + }; + this.removeToLineEnd = function() { + if (this.selection.isEmpty()) + this.selection.selectLineEnd(); + + var range = this.getSelectionRange(); + if (range.start.column == range.end.column && range.start.row == range.end.row) { + range.end.column = 0; + range.end.row++; + } + + this.session.remove(range); + this.clearSelection(); + }; + this.splitLine = function() { + if (!this.selection.isEmpty()) { + this.session.remove(this.getSelectionRange()); + this.clearSelection(); + } + + var cursor = this.getCursorPosition(); + this.insert("\n"); + this.moveCursorToPosition(cursor); + }; + this.transposeLetters = function() { + if (!this.selection.isEmpty()) { + return; + } + + var cursor = this.getCursorPosition(); + var column = cursor.column; + if (column === 0) + return; + + var line = this.session.getLine(cursor.row); + var swap, range; + if (column < line.length) { + swap = line.charAt(column) + line.charAt(column-1); + range = new Range(cursor.row, column-1, cursor.row, column+1); + } + else { + swap = line.charAt(column-1) + line.charAt(column-2); + range = new Range(cursor.row, column-2, cursor.row, column); + } + this.session.replace(range, swap); + }; + this.toLowerCase = function() { + var originalRange = this.getSelectionRange(); + if (this.selection.isEmpty()) { + this.selection.selectWord(); + } + + var range = this.getSelectionRange(); + var text = this.session.getTextRange(range); + this.session.replace(range, text.toLowerCase()); + this.selection.setSelectionRange(originalRange); + }; + this.toUpperCase = function() { + var originalRange = this.getSelectionRange(); + if (this.selection.isEmpty()) { + this.selection.selectWord(); + } + + var range = this.getSelectionRange(); + var text = this.session.getTextRange(range); + this.session.replace(range, text.toUpperCase()); + this.selection.setSelectionRange(originalRange); + }; + this.indent = function() { + var session = this.session; + var range = this.getSelectionRange(); + + if (range.start.row < range.end.row) { + var rows = this.$getSelectedRows(); + session.indentRows(rows.first, rows.last, "\t"); + return; + } else if (range.start.column < range.end.column) { + var text = session.getTextRange(range); + if (!/^\s+$/.test(text)) { + var rows = this.$getSelectedRows(); + session.indentRows(rows.first, rows.last, "\t"); + return; + } + } + + var line = session.getLine(range.start.row); + var position = range.start; + var size = session.getTabSize(); + var column = session.documentToScreenColumn(position.row, position.column); + + if (this.session.getUseSoftTabs()) { + var count = (size - column % size); + var indentString = lang.stringRepeat(" ", count); + } else { + var count = column % size; + while (line[range.start.column] == " " && count) { + range.start.column--; + count--; + } + this.selection.setSelectionRange(range); + indentString = "\t"; + } + return this.insert(indentString); + }; + this.blockIndent = function() { + var rows = this.$getSelectedRows(); + this.session.indentRows(rows.first, rows.last, "\t"); + }; + this.blockOutdent = function() { + var selection = this.session.getSelection(); + this.session.outdentRows(selection.getRange()); + }; + this.sortLines = function() { + var rows = this.$getSelectedRows(); + var session = this.session; + + var lines = []; + for (i = rows.first; i <= rows.last; i++) + lines.push(session.getLine(i)); + + lines.sort(function(a, b) { + if (a.toLowerCase() < b.toLowerCase()) return -1; + if (a.toLowerCase() > b.toLowerCase()) return 1; + return 0; + }); + + var deleteRange = new Range(0, 0, 0, 0); + for (var i = rows.first; i <= rows.last; i++) { + var line = session.getLine(i); + deleteRange.start.row = i; + deleteRange.end.row = i; + deleteRange.end.column = line.length; + session.replace(deleteRange, lines[i-rows.first]); + } + }; + this.toggleCommentLines = function() { + var state = this.session.getState(this.getCursorPosition().row); + var rows = this.$getSelectedRows(); + this.session.getMode().toggleCommentLines(state, this.session, rows.first, rows.last); + }; + + this.toggleBlockComment = function() { + var cursor = this.getCursorPosition(); + var state = this.session.getState(cursor.row); + var range = this.getSelectionRange(); + this.session.getMode().toggleBlockComment(state, this.session, range, cursor); + }; + this.getNumberAt = function(row, column) { + var _numberRx = /[\-]?[0-9]+(?:\.[0-9]+)?/g; + _numberRx.lastIndex = 0; + + var s = this.session.getLine(row); + while (_numberRx.lastIndex < column) { + var m = _numberRx.exec(s); + if(m.index <= column && m.index+m[0].length >= column){ + var number = { + value: m[0], + start: m.index, + end: m.index+m[0].length + }; + return number; + } + } + return null; + }; + this.modifyNumber = function(amount) { + var row = this.selection.getCursor().row; + var column = this.selection.getCursor().column; + var charRange = new Range(row, column-1, row, column); + + var c = this.session.getTextRange(charRange); + if (!isNaN(parseFloat(c)) && isFinite(c)) { + var nr = this.getNumberAt(row, column); + if (nr) { + var fp = nr.value.indexOf(".") >= 0 ? nr.start + nr.value.indexOf(".") + 1 : nr.end; + var decimals = nr.start + nr.value.length - fp; + + var t = parseFloat(nr.value); + t *= Math.pow(10, decimals); + + + if(fp !== nr.end && column < fp){ + amount *= Math.pow(10, nr.end - column - 1); + } else { + amount *= Math.pow(10, nr.end - column); + } + + t += amount; + t /= Math.pow(10, decimals); + var nnr = t.toFixed(decimals); + var replaceRange = new Range(row, nr.start, row, nr.end); + this.session.replace(replaceRange, nnr); + this.moveCursorTo(row, Math.max(nr.start +1, column + nnr.length - nr.value.length)); + + } + } + }; + this.removeLines = function() { + var rows = this.$getSelectedRows(); + var range; + if (rows.first === 0 || rows.last+1 < this.session.getLength()) + range = new Range(rows.first, 0, rows.last+1, 0); + else + range = new Range( + rows.first-1, this.session.getLine(rows.first-1).length, + rows.last, this.session.getLine(rows.last).length + ); + this.session.remove(range); + this.clearSelection(); + }; + + this.duplicateSelection = function() { + var sel = this.selection; + var doc = this.session; + var range = sel.getRange(); + var reverse = sel.isBackwards(); + if (range.isEmpty()) { + var row = range.start.row; + doc.duplicateLines(row, row); + } else { + var point = reverse ? range.start : range.end; + var endPoint = doc.insert(point, doc.getTextRange(range), false); + range.start = point; + range.end = endPoint; + + sel.setSelectionRange(range, reverse); + } + }; + this.moveLinesDown = function() { + this.$moveLines(1, false); + }; + this.moveLinesUp = function() { + this.$moveLines(-1, false); + }; + this.moveText = function(range, toPosition, copy) { + return this.session.moveText(range, toPosition, copy); + }; + this.copyLinesUp = function() { + this.$moveLines(-1, true); + }; + this.copyLinesDown = function() { + this.$moveLines(1, true); + }; + this.$moveLines = function(dir, copy) { + var rows, moved; + var selection = this.selection; + if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) { + var range = selection.toOrientedRange(); + rows = this.$getSelectedRows(range); + moved = this.session.$moveLines(rows.first, rows.last, copy ? 0 : dir); + if (copy && dir == -1) moved = 0; + range.moveBy(moved, 0); + selection.fromOrientedRange(range); + } else { + var ranges = selection.rangeList.ranges; + selection.rangeList.detach(this.session); + this.inVirtualSelectionMode = true; + + var diff = 0; + var totalDiff = 0; + var l = ranges.length; + for (var i = 0; i < l; i++) { + var rangeIndex = i; + ranges[i].moveBy(diff, 0); + rows = this.$getSelectedRows(ranges[i]); + var first = rows.first; + var last = rows.last; + while (++i < l) { + if (totalDiff) ranges[i].moveBy(totalDiff, 0); + var subRows = this.$getSelectedRows(ranges[i]); + if (copy && subRows.first != last) + break; + else if (!copy && subRows.first > last + 1) + break; + last = subRows.last; + } + i--; + diff = this.session.$moveLines(first, last, copy ? 0 : dir); + if (copy && dir == -1) rangeIndex = i + 1; + while (rangeIndex <= i) { + ranges[rangeIndex].moveBy(diff, 0); + rangeIndex++; + } + if (!copy) diff = 0; + totalDiff += diff; + } + + selection.fromOrientedRange(selection.ranges[0]); + selection.rangeList.attach(this.session); + this.inVirtualSelectionMode = false; + } + }; + this.$getSelectedRows = function(range) { + range = (range || this.getSelectionRange()).collapseRows(); + + return { + first: this.session.getRowFoldStart(range.start.row), + last: this.session.getRowFoldEnd(range.end.row) + }; + }; + + this.onCompositionStart = function(text) { + this.renderer.showComposition(this.getCursorPosition()); + }; + + this.onCompositionUpdate = function(text) { + this.renderer.setCompositionText(text); + }; + + this.onCompositionEnd = function() { + this.renderer.hideComposition(); + }; + this.getFirstVisibleRow = function() { + return this.renderer.getFirstVisibleRow(); + }; + this.getLastVisibleRow = function() { + return this.renderer.getLastVisibleRow(); + }; + this.isRowVisible = function(row) { + return (row >= this.getFirstVisibleRow() && row <= this.getLastVisibleRow()); + }; + this.isRowFullyVisible = function(row) { + return (row >= this.renderer.getFirstFullyVisibleRow() && row <= this.renderer.getLastFullyVisibleRow()); + }; + this.$getVisibleRowCount = function() { + return this.renderer.getScrollBottomRow() - this.renderer.getScrollTopRow() + 1; + }; + + this.$moveByPage = function(dir, select) { + var renderer = this.renderer; + var config = this.renderer.layerConfig; + var rows = dir * Math.floor(config.height / config.lineHeight); + + this.$blockScrolling++; + if (select === true) { + this.selection.$moveSelection(function(){ + this.moveCursorBy(rows, 0); + }); + } else if (select === false) { + this.selection.moveCursorBy(rows, 0); + this.selection.clearSelection(); + } + this.$blockScrolling--; + + var scrollTop = renderer.scrollTop; + + renderer.scrollBy(0, rows * config.lineHeight); + if (select != null) + renderer.scrollCursorIntoView(null, 0.5); + + renderer.animateScrolling(scrollTop); + }; + this.selectPageDown = function() { + this.$moveByPage(1, true); + }; + this.selectPageUp = function() { + this.$moveByPage(-1, true); + }; + this.gotoPageDown = function() { + this.$moveByPage(1, false); + }; + this.gotoPageUp = function() { + this.$moveByPage(-1, false); + }; + this.scrollPageDown = function() { + this.$moveByPage(1); + }; + this.scrollPageUp = function() { + this.$moveByPage(-1); + }; + this.scrollToRow = function(row) { + this.renderer.scrollToRow(row); + }; + this.scrollToLine = function(line, center, animate, callback) { + this.renderer.scrollToLine(line, center, animate, callback); + }; + this.centerSelection = function() { + var range = this.getSelectionRange(); + var pos = { + row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2), + column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2) + }; + this.renderer.alignCursor(pos, 0.5); + }; + this.getCursorPosition = function() { + return this.selection.getCursor(); + }; + this.getCursorPositionScreen = function() { + return this.session.documentToScreenPosition(this.getCursorPosition()); + }; + this.getSelectionRange = function() { + return this.selection.getRange(); + }; + this.selectAll = function() { + this.$blockScrolling += 1; + this.selection.selectAll(); + this.$blockScrolling -= 1; + }; + this.clearSelection = function() { + this.selection.clearSelection(); + }; + this.moveCursorTo = function(row, column) { + this.selection.moveCursorTo(row, column); + }; + this.moveCursorToPosition = function(pos) { + this.selection.moveCursorToPosition(pos); + }; + this.jumpToMatching = function(select, expand) { + var cursor = this.getCursorPosition(); + var iterator = new TokenIterator(this.session, cursor.row, cursor.column); + var prevToken = iterator.getCurrentToken(); + var token = prevToken || iterator.stepForward(); + + if (!token) return; + var matchType; + var found = false; + var depth = {}; + var i = cursor.column - token.start; + var bracketType; + var brackets = { + ")": "(", + "(": "(", + "]": "[", + "[": "[", + "{": "{", + "}": "{" + }; + + do { + if (token.value.match(/[{}()\[\]]/g)) { + for (; i < token.value.length && !found; i++) { + if (!brackets[token.value[i]]) { + continue; + } + + bracketType = brackets[token.value[i]] + '.' + token.type.replace("rparen", "lparen"); + + if (isNaN(depth[bracketType])) { + depth[bracketType] = 0; + } + + switch (token.value[i]) { + case '(': + case '[': + case '{': + depth[bracketType]++; + break; + case ')': + case ']': + case '}': + depth[bracketType]--; + + if (depth[bracketType] === -1) { + matchType = 'bracket'; + found = true; + } + break; + } + } + } + else if (token && token.type.indexOf('tag-name') !== -1) { + if (isNaN(depth[token.value])) { + depth[token.value] = 0; + } + + if (prevToken.value === '<') { + depth[token.value]++; + } + else if (prevToken.value === '= 0; --i) { + if(this.$tryReplace(ranges[i], replacement)) { + replaced++; + } + } + + this.selection.setSelectionRange(selection); + this.$blockScrolling -= 1; + + return replaced; + }; + + this.$tryReplace = function(range, replacement) { + var input = this.session.getTextRange(range); + replacement = this.$search.replace(input, replacement); + if (replacement !== null) { + range.end = this.session.replace(range, replacement); + return range; + } else { + return null; + } + }; + this.getLastSearchOptions = function() { + return this.$search.getOptions(); + }; + this.find = function(needle, options, animate) { + if (!options) + options = {}; + + if (typeof needle == "string" || needle instanceof RegExp) + options.needle = needle; + else if (typeof needle == "object") + oop.mixin(options, needle); + + var range = this.selection.getRange(); + if (options.needle == null) { + needle = this.session.getTextRange(range) + || this.$search.$options.needle; + if (!needle) { + range = this.session.getWordRange(range.start.row, range.start.column); + needle = this.session.getTextRange(range); + } + this.$search.set({needle: needle}); + } + + this.$search.set(options); + if (!options.start) + this.$search.set({start: range}); + + var newRange = this.$search.find(this.session); + if (options.preventScroll) + return newRange; + if (newRange) { + this.revealRange(newRange, animate); + return newRange; + } + if (options.backwards) + range.start = range.end; + else + range.end = range.start; + this.selection.setRange(range); + }; + this.findNext = function(options, animate) { + this.find({skipCurrent: true, backwards: false}, options, animate); + }; + this.findPrevious = function(options, animate) { + this.find(options, {skipCurrent: true, backwards: true}, animate); + }; + + this.revealRange = function(range, animate) { + this.$blockScrolling += 1; + this.session.unfold(range); + this.selection.setSelectionRange(range); + this.$blockScrolling -= 1; + + var scrollTop = this.renderer.scrollTop; + this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5); + if (animate !== false) + this.renderer.animateScrolling(scrollTop); + }; + this.undo = function() { + this.$blockScrolling++; + this.session.getUndoManager().undo(); + this.$blockScrolling--; + this.renderer.scrollCursorIntoView(null, 0.5); + }; + this.redo = function() { + this.$blockScrolling++; + this.session.getUndoManager().redo(); + this.$blockScrolling--; + this.renderer.scrollCursorIntoView(null, 0.5); + }; + this.destroy = function() { + this.renderer.destroy(); + this._signal("destroy", this); + if (this.session) { + this.session.destroy(); + } + }; + this.setAutoScrollEditorIntoView = function(enable) { + if (!enable) + return; + var rect; + var self = this; + var shouldScroll = false; + if (!this.$scrollAnchor) + this.$scrollAnchor = document.createElement("div"); + var scrollAnchor = this.$scrollAnchor; + scrollAnchor.style.cssText = "position:absolute"; + this.container.insertBefore(scrollAnchor, this.container.firstChild); + var onChangeSelection = this.on("changeSelection", function() { + shouldScroll = true; + }); + var onBeforeRender = this.renderer.on("beforeRender", function() { + if (shouldScroll) + rect = self.renderer.container.getBoundingClientRect(); + }); + var onAfterRender = this.renderer.on("afterRender", function() { + if (shouldScroll && rect && (self.isFocused() + || self.searchBox && self.searchBox.isFocused()) + ) { + var renderer = self.renderer; + var pos = renderer.$cursorLayer.$pixelPos; + var config = renderer.layerConfig; + var top = pos.top - config.offset; + if (pos.top >= 0 && top + rect.top < 0) { + shouldScroll = true; + } else if (pos.top < config.height && + pos.top + rect.top + config.lineHeight > window.innerHeight) { + shouldScroll = false; + } else { + shouldScroll = null; + } + if (shouldScroll != null) { + scrollAnchor.style.top = top + "px"; + scrollAnchor.style.left = pos.left + "px"; + scrollAnchor.style.height = config.lineHeight + "px"; + scrollAnchor.scrollIntoView(shouldScroll); + } + shouldScroll = rect = null; + } + }); + this.setAutoScrollEditorIntoView = function(enable) { + if (enable) + return; + delete this.setAutoScrollEditorIntoView; + this.removeEventListener("changeSelection", onChangeSelection); + this.renderer.removeEventListener("afterRender", onAfterRender); + this.renderer.removeEventListener("beforeRender", onBeforeRender); + }; + }; + + + this.$resetCursorStyle = function() { + var style = this.$cursorStyle || "ace"; + var cursorLayer = this.renderer.$cursorLayer; + if (!cursorLayer) + return; + cursorLayer.setSmoothBlinking(/smooth/.test(style)); + cursorLayer.isBlinking = !this.$readOnly && style != "wide"; + dom.setCssClass(cursorLayer.element, "ace_slim-cursors", /slim/.test(style)); + }; + +}).call(Editor.prototype); + + + +config.defineOptions(Editor.prototype, "editor", { + selectionStyle: { + set: function(style) { + this.onSelectionChange(); + this._signal("changeSelectionStyle", {data: style}); + }, + initialValue: "line" + }, + highlightActiveLine: { + set: function() {this.$updateHighlightActiveLine();}, + initialValue: true + }, + highlightSelectedWord: { + set: function(shouldHighlight) {this.$onSelectionChange();}, + initialValue: true + }, + readOnly: { + set: function(readOnly) { + this.$resetCursorStyle(); + }, + initialValue: false + }, + cursorStyle: { + set: function(val) { this.$resetCursorStyle(); }, + values: ["ace", "slim", "smooth", "wide"], + initialValue: "ace" + }, + mergeUndoDeltas: { + values: [false, true, "always"], + initialValue: true + }, + behavioursEnabled: {initialValue: true}, + wrapBehavioursEnabled: {initialValue: true}, + autoScrollEditorIntoView: { + set: function(val) {this.setAutoScrollEditorIntoView(val)} + }, + + hScrollBarAlwaysVisible: "renderer", + vScrollBarAlwaysVisible: "renderer", + highlightGutterLine: "renderer", + animatedScroll: "renderer", + showInvisibles: "renderer", + showPrintMargin: "renderer", + printMarginColumn: "renderer", + printMargin: "renderer", + fadeFoldWidgets: "renderer", + showFoldWidgets: "renderer", + showLineNumbers: "renderer", + showGutter: "renderer", + displayIndentGuides: "renderer", + fontSize: "renderer", + fontFamily: "renderer", + maxLines: "renderer", + minLines: "renderer", + scrollPastEnd: "renderer", + fixedWidthGutter: "renderer", + theme: "renderer", + + scrollSpeed: "$mouseHandler", + dragDelay: "$mouseHandler", + dragEnabled: "$mouseHandler", + focusTimout: "$mouseHandler", + tooltipFollowsMouse: "$mouseHandler", + + firstLineNumber: "session", + overwrite: "session", + newLineMode: "session", + useWorker: "session", + useSoftTabs: "session", + tabSize: "session", + wrap: "session", + foldStyle: "session", + mode: "session" +}); + +exports.Editor = Editor; +}); + +define("ace/undomanager",["require","exports","module"], function(require, exports, module) { +"use strict"; +var UndoManager = function() { + this.reset(); +}; + +(function() { + this.execute = function(options) { + var deltas = options.args[0]; + this.$doc = options.args[1]; + if (options.merge && this.hasUndo()){ + this.dirtyCounter--; + deltas = this.$undoStack.pop().concat(deltas); + } + this.$undoStack.push(deltas); + this.$redoStack = []; + + if (this.dirtyCounter < 0) { + this.dirtyCounter = NaN; + } + this.dirtyCounter++; + }; + this.undo = function(dontSelect) { + var deltas = this.$undoStack.pop(); + var undoSelectionRange = null; + if (deltas) { + undoSelectionRange = + this.$doc.undoChanges(deltas, dontSelect); + this.$redoStack.push(deltas); + this.dirtyCounter--; + } + + return undoSelectionRange; + }; + this.redo = function(dontSelect) { + var deltas = this.$redoStack.pop(); + var redoSelectionRange = null; + if (deltas) { + redoSelectionRange = + this.$doc.redoChanges(deltas, dontSelect); + this.$undoStack.push(deltas); + this.dirtyCounter++; + } + + return redoSelectionRange; + }; + this.reset = function() { + this.$undoStack = []; + this.$redoStack = []; + this.dirtyCounter = 0; + }; + this.hasUndo = function() { + return this.$undoStack.length > 0; + }; + this.hasRedo = function() { + return this.$redoStack.length > 0; + }; + this.markClean = function() { + this.dirtyCounter = 0; + }; + this.isClean = function() { + return this.dirtyCounter === 0; + }; + +}).call(UndoManager.prototype); + +exports.UndoManager = UndoManager; +}); + +define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"], function(require, exports, module) { +"use strict"; + +var dom = require("../lib/dom"); +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var EventEmitter = require("../lib/event_emitter").EventEmitter; + +var Gutter = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_gutter-layer"; + parentEl.appendChild(this.element); + this.setShowFoldWidgets(this.$showFoldWidgets); + + this.gutterWidth = 0; + + this.$annotations = []; + this.$updateAnnotations = this.$updateAnnotations.bind(this); + + this.$cells = []; +}; + +(function() { + + oop.implement(this, EventEmitter); + + this.setSession = function(session) { + if (this.session) + this.session.removeEventListener("change", this.$updateAnnotations); + this.session = session; + if (session) + session.on("change", this.$updateAnnotations); + }; + + this.addGutterDecoration = function(row, className){ + if (window.console) + console.warn && console.warn("deprecated use session.addGutterDecoration"); + this.session.addGutterDecoration(row, className); + }; + + this.removeGutterDecoration = function(row, className){ + if (window.console) + console.warn && console.warn("deprecated use session.removeGutterDecoration"); + this.session.removeGutterDecoration(row, className); + }; + + this.setAnnotations = function(annotations) { + this.$annotations = []; + for (var i = 0; i < annotations.length; i++) { + var annotation = annotations[i]; + var row = annotation.row; + var rowInfo = this.$annotations[row]; + if (!rowInfo) + rowInfo = this.$annotations[row] = {text: []}; + + var annoText = annotation.text; + annoText = annoText ? lang.escapeHTML(annoText) : annotation.html || ""; + + if (rowInfo.text.indexOf(annoText) === -1) + rowInfo.text.push(annoText); + + var type = annotation.type; + if (type == "error") + rowInfo.className = " ace_error"; + else if (type == "warning" && rowInfo.className != " ace_error") + rowInfo.className = " ace_warning"; + else if (type == "info" && (!rowInfo.className)) + rowInfo.className = " ace_info"; + } + }; + + this.$updateAnnotations = function (e) { + if (!this.$annotations.length) + return; + var delta = e.data; + var range = delta.range; + var firstRow = range.start.row; + var len = range.end.row - firstRow; + if (len === 0) { + } else if (delta.action == "removeText" || delta.action == "removeLines") { + this.$annotations.splice(firstRow, len + 1, null); + } else { + var args = new Array(len + 1); + args.unshift(firstRow, 1); + this.$annotations.splice.apply(this.$annotations, args); + } + }; + + this.update = function(config) { + var session = this.session; + var firstRow = config.firstRow; + var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar + session.getLength() - 1); + var fold = session.getNextFoldLine(firstRow); + var foldStart = fold ? fold.start.row : Infinity; + var foldWidgets = this.$showFoldWidgets && session.foldWidgets; + var breakpoints = session.$breakpoints; + var decorations = session.$decorations; + var firstLineNumber = session.$firstLineNumber; + var lastLineNumber = 0; + + var gutterRenderer = session.gutterRenderer || this.$renderer; + + var cell = null; + var index = -1; + var row = firstRow; + while (true) { + if (row > foldStart) { + row = fold.end.row + 1; + fold = session.getNextFoldLine(row, fold); + foldStart = fold ? fold.start.row : Infinity; + } + if (row > lastRow) { + while (this.$cells.length > index + 1) { + cell = this.$cells.pop(); + this.element.removeChild(cell.element); + } + break; + } + + cell = this.$cells[++index]; + if (!cell) { + cell = {element: null, textNode: null, foldWidget: null}; + cell.element = dom.createElement("div"); + cell.textNode = document.createTextNode(''); + cell.element.appendChild(cell.textNode); + this.element.appendChild(cell.element); + this.$cells[index] = cell; + } + + var className = "ace_gutter-cell "; + if (breakpoints[row]) + className += breakpoints[row]; + if (decorations[row]) + className += decorations[row]; + if (this.$annotations[row]) + className += this.$annotations[row].className; + if (cell.element.className != className) + cell.element.className = className; + + var height = session.getRowLength(row) * config.lineHeight + "px"; + if (height != cell.element.style.height) + cell.element.style.height = height; + + if (foldWidgets) { + var c = foldWidgets[row]; + if (c == null) + c = foldWidgets[row] = session.getFoldWidget(row); + } + + if (c) { + if (!cell.foldWidget) { + cell.foldWidget = dom.createElement("span"); + cell.element.appendChild(cell.foldWidget); + } + var className = "ace_fold-widget ace_" + c; + if (c == "start" && row == foldStart && row < fold.end.row) + className += " ace_closed"; + else + className += " ace_open"; + if (cell.foldWidget.className != className) + cell.foldWidget.className = className; + + var height = config.lineHeight + "px"; + if (cell.foldWidget.style.height != height) + cell.foldWidget.style.height = height; + } else { + if (cell.foldWidget) { + cell.element.removeChild(cell.foldWidget); + cell.foldWidget = null; + } + } + + var text = lastLineNumber = gutterRenderer + ? gutterRenderer.getText(session, row) + : row + firstLineNumber; + if (text != cell.textNode.data) + cell.textNode.data = text; + + row++; + } + + this.element.style.height = config.minHeight + "px"; + + if (this.$fixedWidth || session.$useWrapMode) + lastLineNumber = session.getLength() + firstLineNumber; + + var gutterWidth = gutterRenderer + ? gutterRenderer.getWidth(session, lastLineNumber, config) + : lastLineNumber.toString().length * config.characterWidth; + + var padding = this.$padding || this.$computePadding(); + gutterWidth += padding.left + padding.right; + if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) { + this.gutterWidth = gutterWidth; + this.element.style.width = Math.ceil(this.gutterWidth) + "px"; + this._emit("changeGutterWidth", gutterWidth); + } + }; + + this.$fixedWidth = false; + + this.$showLineNumbers = true; + this.$renderer = ""; + this.setShowLineNumbers = function(show) { + this.$renderer = !show && { + getWidth: function() {return ""}, + getText: function() {return ""} + }; + }; + + this.getShowLineNumbers = function() { + return this.$showLineNumbers; + }; + + this.$showFoldWidgets = true; + this.setShowFoldWidgets = function(show) { + if (show) + dom.addCssClass(this.element, "ace_folding-enabled"); + else + dom.removeCssClass(this.element, "ace_folding-enabled"); + + this.$showFoldWidgets = show; + this.$padding = null; + }; + + this.getShowFoldWidgets = function() { + return this.$showFoldWidgets; + }; + + this.$computePadding = function() { + if (!this.element.firstChild) + return {left: 0, right: 0}; + var style = dom.computedStyle(this.element.firstChild); + this.$padding = {}; + this.$padding.left = parseInt(style.paddingLeft) + 1 || 0; + this.$padding.right = parseInt(style.paddingRight) || 0; + return this.$padding; + }; + + this.getRegion = function(point) { + var padding = this.$padding || this.$computePadding(); + var rect = this.element.getBoundingClientRect(); + if (point.x < padding.left + rect.left) + return "markers"; + if (this.$showFoldWidgets && point.x > rect.right - padding.right) + return "foldWidgets"; + }; + +}).call(Gutter.prototype); + +exports.Gutter = Gutter; + +}); + +define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"], function(require, exports, module) { +"use strict"; + +var Range = require("../range").Range; +var dom = require("../lib/dom"); + +var Marker = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_marker-layer"; + parentEl.appendChild(this.element); +}; + +(function() { + + this.$padding = 0; + + this.setPadding = function(padding) { + this.$padding = padding; + }; + this.setSession = function(session) { + this.session = session; + }; + + this.setMarkers = function(markers) { + this.markers = markers; + }; + + this.update = function(config) { + var config = config || this.config; + if (!config) + return; + + this.config = config; + + + var html = []; + for (var key in this.markers) { + var marker = this.markers[key]; + + if (!marker.range) { + marker.update(html, this, this.session, config); + continue; + } + + var range = marker.range.clipRows(config.firstRow, config.lastRow); + if (range.isEmpty()) continue; + + range = range.toScreenRange(this.session); + if (marker.renderer) { + var top = this.$getTop(range.start.row, config); + var left = this.$padding + range.start.column * config.characterWidth; + marker.renderer(html, range, left, top, config); + } else if (marker.type == "fullLine") { + this.drawFullLineMarker(html, range, marker.clazz, config); + } else if (marker.type == "screenLine") { + this.drawScreenLineMarker(html, range, marker.clazz, config); + } else if (range.isMultiLine()) { + if (marker.type == "text") + this.drawTextMarker(html, range, marker.clazz, config); + else + this.drawMultiLineMarker(html, range, marker.clazz, config); + } else { + this.drawSingleLineMarker(html, range, marker.clazz + " ace_start", config); + } + } + this.element.innerHTML = html.join(""); + }; + + this.$getTop = function(row, layerConfig) { + return (row - layerConfig.firstRowScreen) * layerConfig.lineHeight; + }; + this.drawTextMarker = function(stringBuilder, range, clazz, layerConfig, extraStyle) { + var row = range.start.row; + + var lineRange = new Range( + row, range.start.column, + row, this.session.getScreenLastRowColumn(row) + ); + this.drawSingleLineMarker(stringBuilder, lineRange, clazz + " ace_start", layerConfig, 1, extraStyle); + row = range.end.row; + lineRange = new Range(row, 0, row, range.end.column); + this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 0, extraStyle); + + for (row = range.start.row + 1; row < range.end.row; row++) { + lineRange.start.row = row; + lineRange.end.row = row; + lineRange.end.column = this.session.getScreenLastRowColumn(row); + this.drawSingleLineMarker(stringBuilder, lineRange, clazz, layerConfig, 1, extraStyle); + } + }; + this.drawMultiLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { + var padding = this.$padding; + var height = config.lineHeight; + var top = this.$getTop(range.start.row, config); + var left = padding + range.start.column * config.characterWidth; + extraStyle = extraStyle || ""; + + stringBuilder.push( + "
" + ); + top = this.$getTop(range.end.row, config); + var width = range.end.column * config.characterWidth; + + stringBuilder.push( + "
" + ); + height = (range.end.row - range.start.row - 1) * config.lineHeight; + if (height < 0) + return; + top = this.$getTop(range.start.row + 1, config); + + stringBuilder.push( + "
" + ); + }; + this.drawSingleLineMarker = function(stringBuilder, range, clazz, config, extraLength, extraStyle) { + var height = config.lineHeight; + var width = (range.end.column + (extraLength || 0) - range.start.column) * config.characterWidth; + + var top = this.$getTop(range.start.row, config); + var left = this.$padding + range.start.column * config.characterWidth; + + stringBuilder.push( + "
" + ); + }; + + this.drawFullLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { + var top = this.$getTop(range.start.row, config); + var height = config.lineHeight; + if (range.start.row != range.end.row) + height += this.$getTop(range.end.row, config) - top; + + stringBuilder.push( + "
" + ); + }; + + this.drawScreenLineMarker = function(stringBuilder, range, clazz, config, extraStyle) { + var top = this.$getTop(range.start.row, config); + var height = config.lineHeight; + + stringBuilder.push( + "
" + ); + }; + +}).call(Marker.prototype); + +exports.Marker = Marker; + +}); + +define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var dom = require("../lib/dom"); +var lang = require("../lib/lang"); +var useragent = require("../lib/useragent"); +var EventEmitter = require("../lib/event_emitter").EventEmitter; + +var Text = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_text-layer"; + parentEl.appendChild(this.element); + this.$updateEolChar = this.$updateEolChar.bind(this); +}; + +(function() { + + oop.implement(this, EventEmitter); + + this.EOF_CHAR = "\xB6"; + this.EOL_CHAR_LF = "\xAC"; + this.EOL_CHAR_CRLF = "\xa4"; + this.EOL_CHAR = this.EOL_CHAR_LF; + this.TAB_CHAR = "\u2192"; //"\u21E5"; + this.SPACE_CHAR = "\xB7"; + this.$padding = 0; + + this.$updateEolChar = function() { + var EOL_CHAR = this.session.doc.getNewLineCharacter() == "\n" + ? this.EOL_CHAR_LF + : this.EOL_CHAR_CRLF; + if (this.EOL_CHAR != EOL_CHAR) { + this.EOL_CHAR = EOL_CHAR; + return true; + } + } + + this.setPadding = function(padding) { + this.$padding = padding; + this.element.style.padding = "0 " + padding + "px"; + }; + + this.getLineHeight = function() { + return this.$fontMetrics.$characterSize.height || 0; + }; + + this.getCharacterWidth = function() { + return this.$fontMetrics.$characterSize.width || 0; + }; + + this.$setFontMetrics = function(measure) { + this.$fontMetrics = measure; + this.$fontMetrics.on("changeCharacterSize", function(e) { + this._signal("changeCharacterSize", e); + }.bind(this)); + this.$pollSizeChanges(); + } + + this.checkForSizeChanges = function() { + this.$fontMetrics.checkForSizeChanges(); + }; + this.$pollSizeChanges = function() { + return this.$pollSizeChangesTimer = this.$fontMetrics.$pollSizeChanges(); + }; + this.setSession = function(session) { + this.session = session; + if (session) + this.$computeTabString(); + }; + + this.showInvisibles = false; + this.setShowInvisibles = function(showInvisibles) { + if (this.showInvisibles == showInvisibles) + return false; + + this.showInvisibles = showInvisibles; + this.$computeTabString(); + return true; + }; + + this.displayIndentGuides = true; + this.setDisplayIndentGuides = function(display) { + if (this.displayIndentGuides == display) + return false; + + this.displayIndentGuides = display; + this.$computeTabString(); + return true; + }; + + this.$tabStrings = []; + this.onChangeTabSize = + this.$computeTabString = function() { + var tabSize = this.session.getTabSize(); + this.tabSize = tabSize; + var tabStr = this.$tabStrings = [0]; + for (var i = 1; i < tabSize + 1; i++) { + if (this.showInvisibles) { + tabStr.push("" + + this.TAB_CHAR + + lang.stringRepeat("\xa0", i - 1) + + ""); + } else { + tabStr.push(lang.stringRepeat("\xa0", i)); + } + } + if (this.displayIndentGuides) { + this.$indentGuideRe = /\s\S| \t|\t |\s$/; + var className = "ace_indent-guide"; + var spaceClass = ""; + var tabClass = ""; + if (this.showInvisibles) { + className += " ace_invisible"; + spaceClass = " ace_invisible_space"; + tabClass = " ace_invisible_tab"; + var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize); + var tabContent = this.TAB_CHAR + lang.stringRepeat("\xa0", this.tabSize - 1); + } else{ + var spaceContent = lang.stringRepeat("\xa0", this.tabSize); + var tabContent = spaceContent; + } + + this.$tabStrings[" "] = "" + spaceContent + ""; + this.$tabStrings["\t"] = "" + tabContent + ""; + } + }; + + this.updateLines = function(config, firstRow, lastRow) { + if (this.config.lastRow != config.lastRow || + this.config.firstRow != config.firstRow) { + this.scrollLines(config); + } + this.config = config; + + var first = Math.max(firstRow, config.firstRow); + var last = Math.min(lastRow, config.lastRow); + + var lineElements = this.element.childNodes; + var lineElementsIdx = 0; + + for (var row = config.firstRow; row < first; row++) { + var foldLine = this.session.getFoldLine(row); + if (foldLine) { + if (foldLine.containsRow(first)) { + first = foldLine.start.row; + break; + } else { + row = foldLine.end.row; + } + } + lineElementsIdx ++; + } + + var row = first; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row :Infinity; + } + if (row > last) + break; + + var lineElement = lineElements[lineElementsIdx++]; + if (lineElement) { + var html = []; + this.$renderLine( + html, row, !this.$useLineGroups(), row == foldStart ? foldLine : false + ); + lineElement.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; + lineElement.innerHTML = html.join(""); + } + row++; + } + }; + + this.scrollLines = function(config) { + var oldConfig = this.config; + this.config = config; + + if (!oldConfig || oldConfig.lastRow < config.firstRow) + return this.update(config); + + if (config.lastRow < oldConfig.firstRow) + return this.update(config); + + var el = this.element; + if (oldConfig.firstRow < config.firstRow) + for (var row=this.session.getFoldedRowCount(oldConfig.firstRow, config.firstRow - 1); row>0; row--) + el.removeChild(el.firstChild); + + if (oldConfig.lastRow > config.lastRow) + for (var row=this.session.getFoldedRowCount(config.lastRow + 1, oldConfig.lastRow); row>0; row--) + el.removeChild(el.lastChild); + + if (config.firstRow < oldConfig.firstRow) { + var fragment = this.$renderLinesFragment(config, config.firstRow, oldConfig.firstRow - 1); + if (el.firstChild) + el.insertBefore(fragment, el.firstChild); + else + el.appendChild(fragment); + } + + if (config.lastRow > oldConfig.lastRow) { + var fragment = this.$renderLinesFragment(config, oldConfig.lastRow + 1, config.lastRow); + el.appendChild(fragment); + } + }; + + this.$renderLinesFragment = function(config, firstRow, lastRow) { + var fragment = this.element.ownerDocument.createDocumentFragment(); + var row = firstRow; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row : Infinity; + } + if (row > lastRow) + break; + + var container = dom.createElement("div"); + + var html = []; + this.$renderLine(html, row, false, row == foldStart ? foldLine : false); + container.innerHTML = html.join(""); + if (this.$useLineGroups()) { + container.className = 'ace_line_group'; + fragment.appendChild(container); + container.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; + + } else { + while(container.firstChild) + fragment.appendChild(container.firstChild); + } + + row++; + } + return fragment; + }; + + this.update = function(config) { + this.config = config; + + var html = []; + var firstRow = config.firstRow, lastRow = config.lastRow; + + var row = firstRow; + var foldLine = this.session.getNextFoldLine(row); + var foldStart = foldLine ? foldLine.start.row : Infinity; + + while (true) { + if (row > foldStart) { + row = foldLine.end.row+1; + foldLine = this.session.getNextFoldLine(row, foldLine); + foldStart = foldLine ? foldLine.start.row :Infinity; + } + if (row > lastRow) + break; + + if (this.$useLineGroups()) + html.push("
") + + this.$renderLine(html, row, false, row == foldStart ? foldLine : false); + + if (this.$useLineGroups()) + html.push("
"); // end the line group + + row++; + } + this.element.innerHTML = html.join(""); + }; + + this.$textToken = { + "text": true, + "rparen": true, + "lparen": true + }; + + this.$renderToken = function(stringBuilder, screenColumn, token, value) { + var self = this; + var replaceReg = /\t|&|<|( +)|([\x00-\x1f\x80-\xa0\xad\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g; + var replaceFunc = function(c, a, b, tabIdx, idx4) { + if (a) { + return self.showInvisibles ? + "" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "" : + lang.stringRepeat("\xa0", c.length); + } else if (c == "&") { + return "&"; + } else if (c == "<") { + return "<"; + } else if (c == "\t") { + var tabSize = self.session.getScreenTabSize(screenColumn + tabIdx); + screenColumn += tabSize - 1; + return self.$tabStrings[tabSize]; + } else if (c == "\u3000") { + var classToUse = self.showInvisibles ? "ace_cjk ace_invisible ace_invisible_space" : "ace_cjk"; + var space = self.showInvisibles ? self.SPACE_CHAR : ""; + screenColumn += 1; + return "" + space + ""; + } else if (b) { + return "" + self.SPACE_CHAR + ""; + } else { + screenColumn += 1; + return "" + c + ""; + } + }; + + var output = value.replace(replaceReg, replaceFunc); + + if (!this.$textToken[token.type]) { + var classes = "ace_" + token.type.replace(/\./g, " ace_"); + var style = ""; + if (token.type == "fold") + style = " style='width:" + (token.value.length * this.config.characterWidth) + "px;' "; + stringBuilder.push("", output, ""); + } + else { + stringBuilder.push(output); + } + return screenColumn + value.length; + }; + + this.renderIndentGuide = function(stringBuilder, value, max) { + var cols = value.search(this.$indentGuideRe); + if (cols <= 0 || cols >= max) + return value; + if (value[0] == " ") { + cols -= cols % this.tabSize; + stringBuilder.push(lang.stringRepeat(this.$tabStrings[" "], cols/this.tabSize)); + return value.substr(cols); + } else if (value[0] == "\t") { + stringBuilder.push(lang.stringRepeat(this.$tabStrings["\t"], cols)); + return value.substr(cols); + } + return value; + }; + + this.$renderWrappedLine = function(stringBuilder, tokens, splits, onlyContents) { + var chars = 0; + var split = 0; + var splitChars = splits[0]; + var screenColumn = 0; + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + var value = token.value; + if (i == 0 && this.displayIndentGuides) { + chars = value.length; + value = this.renderIndentGuide(stringBuilder, value, splitChars); + if (!value) + continue; + chars -= value.length; + } + + if (chars + value.length < splitChars) { + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + chars += value.length; + } else { + while (chars + value.length >= splitChars) { + screenColumn = this.$renderToken( + stringBuilder, screenColumn, + token, value.substring(0, splitChars - chars) + ); + value = value.substring(splitChars - chars); + chars = splitChars; + + if (!onlyContents) { + stringBuilder.push("", + "
" + ); + } + + split ++; + screenColumn = 0; + splitChars = splits[split] || Number.MAX_VALUE; + } + if (value.length != 0) { + chars += value.length; + screenColumn = this.$renderToken( + stringBuilder, screenColumn, token, value + ); + } + } + } + }; + + this.$renderSimpleLine = function(stringBuilder, tokens) { + var screenColumn = 0; + var token = tokens[0]; + var value = token.value; + if (this.displayIndentGuides) + value = this.renderIndentGuide(stringBuilder, value); + if (value) + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + for (var i = 1; i < tokens.length; i++) { + token = tokens[i]; + value = token.value; + screenColumn = this.$renderToken(stringBuilder, screenColumn, token, value); + } + }; + this.$renderLine = function(stringBuilder, row, onlyContents, foldLine) { + if (!foldLine && foldLine != false) + foldLine = this.session.getFoldLine(row); + + if (foldLine) + var tokens = this.$getFoldLineTokens(row, foldLine); + else + var tokens = this.session.getTokens(row); + + + if (!onlyContents) { + stringBuilder.push( + "
" + ); + } + + if (tokens.length) { + var splits = this.session.getRowSplitData(row); + if (splits && splits.length) + this.$renderWrappedLine(stringBuilder, tokens, splits, onlyContents); + else + this.$renderSimpleLine(stringBuilder, tokens); + } + + if (this.showInvisibles) { + if (foldLine) + row = foldLine.end.row + + stringBuilder.push( + "", + row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR, + "" + ); + } + if (!onlyContents) + stringBuilder.push("
"); + }; + + this.$getFoldLineTokens = function(row, foldLine) { + var session = this.session; + var renderTokens = []; + + function addTokens(tokens, from, to) { + var idx = 0, col = 0; + while ((col + tokens[idx].value.length) < from) { + col += tokens[idx].value.length; + idx++; + + if (idx == tokens.length) + return; + } + if (col != from) { + var value = tokens[idx].value.substring(from - col); + if (value.length > (to - from)) + value = value.substring(0, to - from); + + renderTokens.push({ + type: tokens[idx].type, + value: value + }); + + col = from + value.length; + idx += 1; + } + + while (col < to && idx < tokens.length) { + var value = tokens[idx].value; + if (value.length + col > to) { + renderTokens.push({ + type: tokens[idx].type, + value: value.substring(0, to - col) + }); + } else + renderTokens.push(tokens[idx]); + col += value.length; + idx += 1; + } + } + + var tokens = session.getTokens(row); + foldLine.walk(function(placeholder, row, column, lastColumn, isNewRow) { + if (placeholder != null) { + renderTokens.push({ + type: "fold", + value: placeholder + }); + } else { + if (isNewRow) + tokens = session.getTokens(row); + + if (tokens.length) + addTokens(tokens, lastColumn, column); + } + }, foldLine.end.row, this.session.getLine(foldLine.end.row).length); + + return renderTokens; + }; + + this.$useLineGroups = function() { + return this.session.getUseWrapMode(); + }; + + this.destroy = function() { + clearInterval(this.$pollSizeChangesTimer); + if (this.$measureNode) + this.$measureNode.parentNode.removeChild(this.$measureNode); + delete this.$measureNode; + }; + +}).call(Text.prototype); + +exports.Text = Text; + +}); + +define("ace/layer/cursor",["require","exports","module","ace/lib/dom"], function(require, exports, module) { +"use strict"; + +var dom = require("../lib/dom"); +var IE8; + +var Cursor = function(parentEl) { + this.element = dom.createElement("div"); + this.element.className = "ace_layer ace_cursor-layer"; + parentEl.appendChild(this.element); + + if (IE8 === undefined) + IE8 = "opacity" in this.element; + + this.isVisible = false; + this.isBlinking = true; + this.blinkInterval = 1000; + this.smoothBlinking = false; + + this.cursors = []; + this.cursor = this.addCursor(); + dom.addCssClass(this.element, "ace_hidden-cursors"); + this.$updateCursors = this.$updateVisibility.bind(this); +}; + +(function() { + + this.$updateVisibility = function(val) { + var cursors = this.cursors; + for (var i = cursors.length; i--; ) + cursors[i].style.visibility = val ? "" : "hidden"; + }; + this.$updateOpacity = function(val) { + var cursors = this.cursors; + for (var i = cursors.length; i--; ) + cursors[i].style.opacity = val ? "" : "0"; + }; + + + this.$padding = 0; + this.setPadding = function(padding) { + this.$padding = padding; + }; + + this.setSession = function(session) { + this.session = session; + }; + + this.setBlinking = function(blinking) { + if (blinking != this.isBlinking){ + this.isBlinking = blinking; + this.restartTimer(); + } + }; + + this.setBlinkInterval = function(blinkInterval) { + if (blinkInterval != this.blinkInterval){ + this.blinkInterval = blinkInterval; + this.restartTimer(); + } + }; + + this.setSmoothBlinking = function(smoothBlinking) { + if (smoothBlinking != this.smoothBlinking && !IE8) { + this.smoothBlinking = smoothBlinking; + dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking); + this.$updateCursors(true); + this.$updateCursors = (smoothBlinking + ? this.$updateOpacity + : this.$updateVisibility).bind(this); + this.restartTimer(); + } + }; + + this.addCursor = function() { + var el = dom.createElement("div"); + el.className = "ace_cursor"; + this.element.appendChild(el); + this.cursors.push(el); + return el; + }; + + this.removeCursor = function() { + if (this.cursors.length > 1) { + var el = this.cursors.pop(); + el.parentNode.removeChild(el); + return el; + } + }; + + this.hideCursor = function() { + this.isVisible = false; + dom.addCssClass(this.element, "ace_hidden-cursors"); + this.restartTimer(); + }; + + this.showCursor = function() { + this.isVisible = true; + dom.removeCssClass(this.element, "ace_hidden-cursors"); + this.restartTimer(); + }; + + this.restartTimer = function() { + var update = this.$updateCursors; + clearInterval(this.intervalId); + clearTimeout(this.timeoutId); + if (this.smoothBlinking) { + dom.removeCssClass(this.element, "ace_smooth-blinking"); + } + + update(true); + + if (!this.isBlinking || !this.blinkInterval || !this.isVisible) + return; + + if (this.smoothBlinking) { + setTimeout(function(){ + dom.addCssClass(this.element, "ace_smooth-blinking"); + }.bind(this)); + } + + var blink = function(){ + this.timeoutId = setTimeout(function() { + update(false); + }, 0.6 * this.blinkInterval); + }.bind(this); + + this.intervalId = setInterval(function() { + update(true); + blink(); + }, this.blinkInterval); + + blink(); + }; + + this.getPixelPosition = function(position, onScreen) { + if (!this.config || !this.session) + return {left : 0, top : 0}; + + if (!position) + position = this.session.selection.getCursor(); + var pos = this.session.documentToScreenPosition(position); + var cursorLeft = this.$padding + pos.column * this.config.characterWidth; + var cursorTop = (pos.row - (onScreen ? this.config.firstRowScreen : 0)) * + this.config.lineHeight; + + return {left : cursorLeft, top : cursorTop}; + }; + + this.update = function(config) { + this.config = config; + + var selections = this.session.$selectionMarkers; + var i = 0, cursorIndex = 0; + + if (selections === undefined || selections.length === 0){ + selections = [{cursor: null}]; + } + + for (var i = 0, n = selections.length; i < n; i++) { + var pixelPos = this.getPixelPosition(selections[i].cursor, true); + if ((pixelPos.top > config.height + config.offset || + pixelPos.top < 0) && i > 1) { + continue; + } + + var style = (this.cursors[cursorIndex++] || this.addCursor()).style; + + if (!this.drawCursor) { + style.left = pixelPos.left + "px"; + style.top = pixelPos.top + "px"; + style.width = config.characterWidth + "px"; + style.height = config.lineHeight + "px"; + } else { + this.drawCursor(style, pixelPos, config, selections[i], this.session); + } + } + while (this.cursors.length > cursorIndex) + this.removeCursor(); + + var overwrite = this.session.getOverwrite(); + this.$setOverwrite(overwrite); + this.$pixelPos = pixelPos; + this.restartTimer(); + }; + + this.drawCursor = null; + + this.$setOverwrite = function(overwrite) { + if (overwrite != this.overwrite) { + this.overwrite = overwrite; + if (overwrite) + dom.addCssClass(this.element, "ace_overwrite-cursors"); + else + dom.removeCssClass(this.element, "ace_overwrite-cursors"); + } + }; + + this.destroy = function() { + clearInterval(this.intervalId); + clearTimeout(this.timeoutId); + }; + +}).call(Cursor.prototype); + +exports.Cursor = Cursor; + +}); + +define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var dom = require("./lib/dom"); +var event = require("./lib/event"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var ScrollBar = function(parent) { + this.element = dom.createElement("div"); + this.element.className = "ace_scrollbar ace_scrollbar" + this.classSuffix; + + this.inner = dom.createElement("div"); + this.inner.className = "ace_scrollbar-inner"; + this.element.appendChild(this.inner); + + parent.appendChild(this.element); + + this.setVisible(false); + this.skipEvent = false; + + event.addListener(this.element, "scroll", this.onScroll.bind(this)); + event.addListener(this.element, "mousedown", event.preventDefault); +}; + +(function() { + oop.implement(this, EventEmitter); + + this.setVisible = function(isVisible) { + this.element.style.display = isVisible ? "" : "none"; + this.isVisible = isVisible; + }; +}).call(ScrollBar.prototype); +var VScrollBar = function(parent, renderer) { + ScrollBar.call(this, parent); + this.scrollTop = 0; + renderer.$scrollbarWidth = + this.width = dom.scrollbarWidth(parent.ownerDocument); + this.inner.style.width = + this.element.style.width = (this.width || 15) + 5 + "px"; +}; + +oop.inherits(VScrollBar, ScrollBar); + +(function() { + + this.classSuffix = '-v'; + this.onScroll = function() { + if (!this.skipEvent) { + this.scrollTop = this.element.scrollTop; + this._emit("scroll", {data: this.scrollTop}); + } + this.skipEvent = false; + }; + this.getWidth = function() { + return this.isVisible ? this.width : 0; + }; + this.setHeight = function(height) { + this.element.style.height = height + "px"; + }; + this.setInnerHeight = function(height) { + this.inner.style.height = height + "px"; + }; + this.setScrollHeight = function(height) { + this.inner.style.height = height + "px"; + }; + this.setScrollTop = function(scrollTop) { + if (this.scrollTop != scrollTop) { + this.skipEvent = true; + this.scrollTop = this.element.scrollTop = scrollTop; + } + }; + +}).call(VScrollBar.prototype); +var HScrollBar = function(parent, renderer) { + ScrollBar.call(this, parent); + this.scrollLeft = 0; + this.height = renderer.$scrollbarWidth; + this.inner.style.height = + this.element.style.height = (this.height || 15) + 5 + "px"; +}; + +oop.inherits(HScrollBar, ScrollBar); + +(function() { + + this.classSuffix = '-h'; + this.onScroll = function() { + if (!this.skipEvent) { + this.scrollLeft = this.element.scrollLeft; + this._emit("scroll", {data: this.scrollLeft}); + } + this.skipEvent = false; + }; + this.getHeight = function() { + return this.isVisible ? this.height : 0; + }; + this.setWidth = function(width) { + this.element.style.width = width + "px"; + }; + this.setInnerWidth = function(width) { + this.inner.style.width = width + "px"; + }; + this.setScrollWidth = function(width) { + this.inner.style.width = width + "px"; + }; + this.setScrollLeft = function(scrollLeft) { + if (this.scrollLeft != scrollLeft) { + this.skipEvent = true; + this.scrollLeft = this.element.scrollLeft = scrollLeft; + } + }; + +}).call(HScrollBar.prototype); + + +exports.ScrollBar = VScrollBar; // backward compatibility +exports.ScrollBarV = VScrollBar; // backward compatibility +exports.ScrollBarH = HScrollBar; // backward compatibility + +exports.VScrollBar = VScrollBar; +exports.HScrollBar = HScrollBar; +}); + +define("ace/renderloop",["require","exports","module","ace/lib/event"], function(require, exports, module) { +"use strict"; + +var event = require("./lib/event"); + + +var RenderLoop = function(onRender, win) { + this.onRender = onRender; + this.pending = false; + this.changes = 0; + this.window = win || window; +}; + +(function() { + + + this.schedule = function(change) { + this.changes = this.changes | change; + if (!this.pending && this.changes) { + this.pending = true; + var _self = this; + event.nextFrame(function() { + _self.pending = false; + var changes; + while (changes = _self.changes) { + _self.changes = 0; + _self.onRender(changes); + } + }, this.window); + } + }; + +}).call(RenderLoop.prototype); + +exports.RenderLoop = RenderLoop; +}); + +define("ace/layer/font_metrics",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"], function(require, exports, module) { + +var oop = require("../lib/oop"); +var dom = require("../lib/dom"); +var lang = require("../lib/lang"); +var useragent = require("../lib/useragent"); +var EventEmitter = require("../lib/event_emitter").EventEmitter; + +var CHAR_COUNT = 0; + +var FontMetrics = exports.FontMetrics = function(parentEl, interval) { + this.el = dom.createElement("div"); + this.$setMeasureNodeStyles(this.el.style, true); + + this.$main = dom.createElement("div"); + this.$setMeasureNodeStyles(this.$main.style); + + this.$measureNode = dom.createElement("div"); + this.$setMeasureNodeStyles(this.$measureNode.style); + + + this.el.appendChild(this.$main); + this.el.appendChild(this.$measureNode); + parentEl.appendChild(this.el); + + if (!CHAR_COUNT) + this.$testFractionalRect(); + this.$measureNode.innerHTML = lang.stringRepeat("X", CHAR_COUNT); + + this.$characterSize = {width: 0, height: 0}; + this.checkForSizeChanges(); +}; + +(function() { + + oop.implement(this, EventEmitter); + + this.$characterSize = {width: 0, height: 0}; + + this.$testFractionalRect = function() { + var el = dom.createElement("div"); + this.$setMeasureNodeStyles(el.style); + el.style.width = "0.2px"; + document.documentElement.appendChild(el); + var w = el.getBoundingClientRect().width; + if (w > 0 && w < 1) + CHAR_COUNT = 50; + else + CHAR_COUNT = 100; + el.parentNode.removeChild(el); + }; + + this.$setMeasureNodeStyles = function(style, isRoot) { + style.width = style.height = "auto"; + style.left = style.top = "0px"; + style.visibility = "hidden"; + style.position = "absolute"; + style.whiteSpace = "pre"; + + if (useragent.isIE < 8) { + style["font-family"] = "inherit"; + } else { + style.font = "inherit"; + } + style.overflow = isRoot ? "hidden" : "visible"; + }; + + this.checkForSizeChanges = function() { + var size = this.$measureSizes(); + if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) { + this.$measureNode.style.fontWeight = "bold"; + var boldSize = this.$measureSizes(); + this.$measureNode.style.fontWeight = ""; + this.$characterSize = size; + this.charSizes = Object.create(null); + this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height; + this._emit("changeCharacterSize", {data: size}); + } + }; + + this.$pollSizeChanges = function() { + if (this.$pollSizeChangesTimer) + return this.$pollSizeChangesTimer; + var self = this; + return this.$pollSizeChangesTimer = setInterval(function() { + self.checkForSizeChanges(); + }, 500); + }; + + this.setPolling = function(val) { + if (val) { + this.$pollSizeChanges(); + } else { + if (this.$pollSizeChangesTimer) + this.$pollSizeChangesTimer; + } + }; + + this.$measureSizes = function() { + if (CHAR_COUNT === 50) { + var rect = null; + try { + rect = this.$measureNode.getBoundingClientRect(); + } catch(e) { + rect = {width: 0, height:0 }; + }; + var size = { + height: rect.height, + width: rect.width / CHAR_COUNT + }; + } else { + var size = { + height: this.$measureNode.clientHeight, + width: this.$measureNode.clientWidth / CHAR_COUNT + }; + } + if (size.width === 0 || size.height === 0) + return null; + return size; + }; + + this.$measureCharWidth = function(ch) { + this.$main.innerHTML = lang.stringRepeat(ch, CHAR_COUNT); + var rect = this.$main.getBoundingClientRect(); + return rect.width / CHAR_COUNT; + }; + + this.getCharacterWidth = function(ch) { + var w = this.charSizes[ch]; + if (w === undefined) { + this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width; + } + return w; + }; + + this.destroy = function() { + clearInterval(this.$pollSizeChangesTimer); + if (this.el && this.el.parentNode) + this.el.parentNode.removeChild(this.el); + }; + +}).call(FontMetrics.prototype); + +}); + +define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/config","ace/lib/useragent","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/scrollbar","ace/renderloop","ace/layer/font_metrics","ace/lib/event_emitter"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var dom = require("./lib/dom"); +var config = require("./config"); +var useragent = require("./lib/useragent"); +var GutterLayer = require("./layer/gutter").Gutter; +var MarkerLayer = require("./layer/marker").Marker; +var TextLayer = require("./layer/text").Text; +var CursorLayer = require("./layer/cursor").Cursor; +var HScrollBar = require("./scrollbar").HScrollBar; +var VScrollBar = require("./scrollbar").VScrollBar; +var RenderLoop = require("./renderloop").RenderLoop; +var FontMetrics = require("./layer/font_metrics").FontMetrics; +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var editorCss = ".ace_editor {\ +position: relative;\ +overflow: hidden;\ +font: 12px/normal 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;\ +direction: ltr;\ +}\ +.ace_scroller {\ +position: absolute;\ +overflow: hidden;\ +top: 0;\ +bottom: 0;\ +background-color: inherit;\ +-ms-user-select: none;\ +-moz-user-select: none;\ +-webkit-user-select: none;\ +user-select: none;\ +cursor: text;\ +}\ +.ace_content {\ +position: absolute;\ +-moz-box-sizing: border-box;\ +-webkit-box-sizing: border-box;\ +box-sizing: border-box;\ +min-width: 100%;\ +}\ +.ace_dragging .ace_scroller:before{\ +position: absolute;\ +top: 0;\ +left: 0;\ +right: 0;\ +bottom: 0;\ +content: '';\ +background: rgba(250, 250, 250, 0.01);\ +z-index: 1000;\ +}\ +.ace_dragging.ace_dark .ace_scroller:before{\ +background: rgba(0, 0, 0, 0.01);\ +}\ +.ace_selecting, .ace_selecting * {\ +cursor: text !important;\ +}\ +.ace_gutter {\ +position: absolute;\ +overflow : hidden;\ +width: auto;\ +top: 0;\ +bottom: 0;\ +left: 0;\ +cursor: default;\ +z-index: 4;\ +-ms-user-select: none;\ +-moz-user-select: none;\ +-webkit-user-select: none;\ +user-select: none;\ +}\ +.ace_gutter-active-line {\ +position: absolute;\ +left: 0;\ +right: 0;\ +}\ +.ace_scroller.ace_scroll-left {\ +box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;\ +}\ +.ace_gutter-cell {\ +padding-left: 19px;\ +padding-right: 6px;\ +background-repeat: no-repeat;\ +}\ +.ace_gutter-cell.ace_error {\ +background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABOFBMVEX/////////QRswFAb/Ui4wFAYwFAYwFAaWGAfDRymzOSH/PxswFAb/SiUwFAYwFAbUPRvjQiDllog5HhHdRybsTi3/Tyv9Tir+Syj/UC3////XurebMBIwFAb/RSHbPx/gUzfdwL3kzMivKBAwFAbbvbnhPx66NhowFAYwFAaZJg8wFAaxKBDZurf/RB6mMxb/SCMwFAYwFAbxQB3+RB4wFAb/Qhy4Oh+4QifbNRcwFAYwFAYwFAb/QRzdNhgwFAYwFAbav7v/Uy7oaE68MBK5LxLewr/r2NXewLswFAaxJw4wFAbkPRy2PyYwFAaxKhLm1tMwFAazPiQwFAaUGAb/QBrfOx3bvrv/VC/maE4wFAbRPBq6MRO8Qynew8Dp2tjfwb0wFAbx6eju5+by6uns4uH9/f36+vr/GkHjAAAAYnRSTlMAGt+64rnWu/bo8eAA4InH3+DwoN7j4eLi4xP99Nfg4+b+/u9B/eDs1MD1mO7+4PHg2MXa347g7vDizMLN4eG+Pv7i5evs/v79yu7S3/DV7/498Yv24eH+4ufQ3Ozu/v7+y13sRqwAAADLSURBVHjaZc/XDsFgGIBhtDrshlitmk2IrbHFqL2pvXf/+78DPokj7+Fz9qpU/9UXJIlhmPaTaQ6QPaz0mm+5gwkgovcV6GZzd5JtCQwgsxoHOvJO15kleRLAnMgHFIESUEPmawB9ngmelTtipwwfASilxOLyiV5UVUyVAfbG0cCPHig+GBkzAENHS0AstVF6bacZIOzgLmxsHbt2OecNgJC83JERmePUYq8ARGkJx6XtFsdddBQgZE2nPR6CICZhawjA4Fb/chv+399kfR+MMMDGOQAAAABJRU5ErkJggg==\");\ +background-repeat: no-repeat;\ +background-position: 2px center;\ +}\ +.ace_gutter-cell.ace_warning {\ +background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAmVBMVEX///8AAAD///8AAAAAAABPSzb/5sAAAAB/blH/73z/ulkAAAAAAAD85pkAAAAAAAACAgP/vGz/rkDerGbGrV7/pkQICAf////e0IsAAAD/oED/qTvhrnUAAAD/yHD/njcAAADuv2r/nz//oTj/p064oGf/zHAAAAA9Nir/tFIAAAD/tlTiuWf/tkIAAACynXEAAAAAAAAtIRW7zBpBAAAAM3RSTlMAABR1m7RXO8Ln31Z36zT+neXe5OzooRDfn+TZ4p3h2hTf4t3k3ucyrN1K5+Xaks52Sfs9CXgrAAAAjklEQVR42o3PbQ+CIBQFYEwboPhSYgoYunIqqLn6/z8uYdH8Vmdnu9vz4WwXgN/xTPRD2+sgOcZjsge/whXZgUaYYvT8QnuJaUrjrHUQreGczuEafQCO/SJTufTbroWsPgsllVhq3wJEk2jUSzX3CUEDJC84707djRc5MTAQxoLgupWRwW6UB5fS++NV8AbOZgnsC7BpEAAAAABJRU5ErkJggg==\");\ +background-position: 2px center;\ +}\ +.ace_gutter-cell.ace_info {\ +background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAJ0Uk5TAAB2k804AAAAPklEQVQY02NgIB68QuO3tiLznjAwpKTgNyDbMegwisCHZUETUZV0ZqOquBpXj2rtnpSJT1AEnnRmL2OgGgAAIKkRQap2htgAAAAASUVORK5CYII=\");\ +background-position: 2px center;\ +}\ +.ace_dark .ace_gutter-cell.ace_info {\ +background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAJFBMVEUAAAChoaGAgIAqKiq+vr6tra1ZWVmUlJSbm5s8PDxubm56enrdgzg3AAAAAXRSTlMAQObYZgAAAClJREFUeNpjYMAPdsMYHegyJZFQBlsUlMFVCWUYKkAZMxZAGdxlDMQBAG+TBP4B6RyJAAAAAElFTkSuQmCC\");\ +}\ +.ace_scrollbar {\ +position: absolute;\ +right: 0;\ +bottom: 0;\ +z-index: 6;\ +}\ +.ace_scrollbar-inner {\ +position: absolute;\ +cursor: text;\ +left: 0;\ +top: 0;\ +}\ +.ace_scrollbar-v{\ +overflow-x: hidden;\ +overflow-y: scroll;\ +top: 0;\ +}\ +.ace_scrollbar-h {\ +overflow-x: scroll;\ +overflow-y: hidden;\ +left: 0;\ +}\ +.ace_print-margin {\ +position: absolute;\ +height: 100%;\ +}\ +.ace_text-input {\ +position: absolute;\ +z-index: 0;\ +width: 0.5em;\ +height: 1em;\ +opacity: 0;\ +background: transparent;\ +-moz-appearance: none;\ +appearance: none;\ +border: none;\ +resize: none;\ +outline: none;\ +overflow: hidden;\ +font: inherit;\ +padding: 0 1px;\ +margin: 0 -1px;\ +text-indent: -1em;\ +-ms-user-select: text;\ +-moz-user-select: text;\ +-webkit-user-select: text;\ +user-select: text;\ +}\ +.ace_text-input.ace_composition {\ +background: inherit;\ +color: inherit;\ +z-index: 1000;\ +opacity: 1;\ +text-indent: 0;\ +}\ +.ace_layer {\ +z-index: 1;\ +position: absolute;\ +overflow: hidden;\ +word-wrap: normal;\ +white-space: pre;\ +height: 100%;\ +width: 100%;\ +-moz-box-sizing: border-box;\ +-webkit-box-sizing: border-box;\ +box-sizing: border-box;\ +pointer-events: none;\ +}\ +.ace_gutter-layer {\ +position: relative;\ +width: auto;\ +text-align: right;\ +pointer-events: auto;\ +}\ +.ace_text-layer {\ +font: inherit !important;\ +}\ +.ace_cjk {\ +display: inline-block;\ +text-align: center;\ +}\ +.ace_cursor-layer {\ +z-index: 4;\ +}\ +.ace_cursor {\ +z-index: 4;\ +position: absolute;\ +-moz-box-sizing: border-box;\ +-webkit-box-sizing: border-box;\ +box-sizing: border-box;\ +border-left: 2px solid\ +}\ +.ace_slim-cursors .ace_cursor {\ +border-left-width: 1px;\ +}\ +.ace_overwrite-cursors .ace_cursor {\ +border-left-width: 0;\ +border-bottom: 1px solid;\ +}\ +.ace_hidden-cursors .ace_cursor {\ +opacity: 0.2;\ +}\ +.ace_smooth-blinking .ace_cursor {\ +-webkit-transition: opacity 0.18s;\ +transition: opacity 0.18s;\ +}\ +.ace_editor.ace_multiselect .ace_cursor {\ +border-left-width: 1px;\ +}\ +.ace_marker-layer .ace_step, .ace_marker-layer .ace_stack {\ +position: absolute;\ +z-index: 3;\ +}\ +.ace_marker-layer .ace_selection {\ +position: absolute;\ +z-index: 5;\ +}\ +.ace_marker-layer .ace_bracket {\ +position: absolute;\ +z-index: 6;\ +}\ +.ace_marker-layer .ace_active-line {\ +position: absolute;\ +z-index: 2;\ +}\ +.ace_marker-layer .ace_selected-word {\ +position: absolute;\ +z-index: 4;\ +-moz-box-sizing: border-box;\ +-webkit-box-sizing: border-box;\ +box-sizing: border-box;\ +}\ +.ace_line .ace_fold {\ +-moz-box-sizing: border-box;\ +-webkit-box-sizing: border-box;\ +box-sizing: border-box;\ +display: inline-block;\ +height: 11px;\ +margin-top: -2px;\ +vertical-align: middle;\ +background-image:\ +url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\ +url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACJJREFUeNpi+P//fxgTAwPDBxDxD078RSX+YeEyDFMCIMAAI3INmXiwf2YAAAAASUVORK5CYII=\");\ +background-repeat: no-repeat, repeat-x;\ +background-position: center center, top left;\ +color: transparent;\ +border: 1px solid black;\ +border-radius: 2px;\ +cursor: pointer;\ +pointer-events: auto;\ +}\ +.ace_dark .ace_fold {\ +}\ +.ace_fold:hover{\ +background-image:\ +url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAJCAYAAADU6McMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAJpJREFUeNpi/P//PwOlgAXGYGRklAVSokD8GmjwY1wasKljQpYACtpCFeADcHVQfQyMQAwzwAZI3wJKvCLkfKBaMSClBlR7BOQikCFGQEErIH0VqkabiGCAqwUadAzZJRxQr/0gwiXIal8zQQPnNVTgJ1TdawL0T5gBIP1MUJNhBv2HKoQHHjqNrA4WO4zY0glyNKLT2KIfIMAAQsdgGiXvgnYAAAAASUVORK5CYII=\"),\ +url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAA3CAYAAADNNiA5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAACBJREFUeNpi+P//fz4TAwPDZxDxD5X4i5fLMEwJgAADAEPVDbjNw87ZAAAAAElFTkSuQmCC\");\ +}\ +.ace_tooltip {\ +background-color: #FFF;\ +background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));\ +background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));\ +border: 1px solid gray;\ +border-radius: 1px;\ +box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);\ +color: black;\ +max-width: 100%;\ +padding: 3px 4px;\ +position: fixed;\ +z-index: 999999;\ +-moz-box-sizing: border-box;\ +-webkit-box-sizing: border-box;\ +box-sizing: border-box;\ +cursor: default;\ +white-space: pre;\ +word-wrap: break-word;\ +line-height: normal;\ +font-style: normal;\ +font-weight: normal;\ +letter-spacing: normal;\ +pointer-events: none;\ +}\ +.ace_folding-enabled > .ace_gutter-cell {\ +padding-right: 13px;\ +}\ +.ace_fold-widget {\ +-moz-box-sizing: border-box;\ +-webkit-box-sizing: border-box;\ +box-sizing: border-box;\ +margin: 0 -12px 0 1px;\ +display: none;\ +width: 11px;\ +vertical-align: top;\ +background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==\");\ +background-repeat: no-repeat;\ +background-position: center;\ +border-radius: 3px;\ +border: 1px solid transparent;\ +cursor: pointer;\ +}\ +.ace_folding-enabled .ace_fold-widget {\ +display: inline-block; \ +}\ +.ace_fold-widget.ace_end {\ +background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg==\");\ +}\ +.ace_fold-widget.ace_closed {\ +background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA==\");\ +}\ +.ace_fold-widget:hover {\ +border: 1px solid rgba(0, 0, 0, 0.3);\ +background-color: rgba(255, 255, 255, 0.2);\ +box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);\ +}\ +.ace_fold-widget:active {\ +border: 1px solid rgba(0, 0, 0, 0.4);\ +background-color: rgba(0, 0, 0, 0.05);\ +box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);\ +}\ +.ace_dark .ace_fold-widget {\ +background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");\ +}\ +.ace_dark .ace_fold-widget.ace_end {\ +background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");\ +}\ +.ace_dark .ace_fold-widget.ace_closed {\ +background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");\ +}\ +.ace_dark .ace_fold-widget:hover {\ +box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\ +background-color: rgba(255, 255, 255, 0.1);\ +}\ +.ace_dark .ace_fold-widget:active {\ +box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);\ +}\ +.ace_fold-widget.ace_invalid {\ +background-color: #FFB4B4;\ +border-color: #DE5555;\ +}\ +.ace_fade-fold-widgets .ace_fold-widget {\ +-webkit-transition: opacity 0.4s ease 0.05s;\ +transition: opacity 0.4s ease 0.05s;\ +opacity: 0;\ +}\ +.ace_fade-fold-widgets:hover .ace_fold-widget {\ +-webkit-transition: opacity 0.05s ease 0.05s;\ +transition: opacity 0.05s ease 0.05s;\ +opacity:1;\ +}\ +.ace_underline {\ +text-decoration: underline;\ +}\ +.ace_bold {\ +font-weight: bold;\ +}\ +.ace_nobold .ace_bold {\ +font-weight: normal;\ +}\ +.ace_italic {\ +font-style: italic;\ +}\ +.ace_error-marker {\ +background-color: rgba(255, 0, 0,0.2);\ +position: absolute;\ +z-index: 9;\ +}\ +.ace_highlight-marker {\ +background-color: rgba(255, 255, 0,0.2);\ +position: absolute;\ +z-index: 8;\ +}\ +"; + +dom.importCssString(editorCss, "ace_editor"); + +var VirtualRenderer = function(container, theme) { + var _self = this; + + this.container = container || dom.createElement("div"); + this.$keepTextAreaAtCursor = !useragent.isOldIE; + + dom.addCssClass(this.container, "ace_editor"); + + this.setTheme(theme); + + this.$gutter = dom.createElement("div"); + this.$gutter.className = "ace_gutter"; + this.container.appendChild(this.$gutter); + + this.scroller = dom.createElement("div"); + this.scroller.className = "ace_scroller"; + this.container.appendChild(this.scroller); + + this.content = dom.createElement("div"); + this.content.className = "ace_content"; + this.scroller.appendChild(this.content); + + this.$gutterLayer = new GutterLayer(this.$gutter); + this.$gutterLayer.on("changeGutterWidth", this.onGutterResize.bind(this)); + + this.$markerBack = new MarkerLayer(this.content); + + var textLayer = this.$textLayer = new TextLayer(this.content); + this.canvas = textLayer.element; + + this.$markerFront = new MarkerLayer(this.content); + + this.$cursorLayer = new CursorLayer(this.content); + this.$horizScroll = false; + this.$vScroll = false; + + this.scrollBar = + this.scrollBarV = new VScrollBar(this.container, this); + this.scrollBarH = new HScrollBar(this.container, this); + this.scrollBarV.addEventListener("scroll", function(e) { + if (!_self.$scrollAnimation) + _self.session.setScrollTop(e.data - _self.scrollMargin.top); + }); + this.scrollBarH.addEventListener("scroll", function(e) { + if (!_self.$scrollAnimation) + _self.session.setScrollLeft(e.data - _self.scrollMargin.left); + }); + + this.scrollTop = 0; + this.scrollLeft = 0; + + this.cursorPos = { + row : 0, + column : 0 + }; + + this.$fontMetrics = new FontMetrics(this.container, 500); + this.$textLayer.$setFontMetrics(this.$fontMetrics); + this.$textLayer.addEventListener("changeCharacterSize", function(e) { + _self.updateCharacterSize(); + _self.onResize(true, _self.gutterWidth, _self.$size.width, _self.$size.height); + _self._signal("changeCharacterSize", e); + }); + + this.$size = { + width: 0, + height: 0, + scrollerHeight: 0, + scrollerWidth: 0, + $dirty: true + }; + + this.layerConfig = { + width : 1, + padding : 0, + firstRow : 0, + firstRowScreen: 0, + lastRow : 0, + lineHeight : 0, + characterWidth : 0, + minHeight : 1, + maxHeight : 1, + offset : 0, + height : 1, + gutterOffset: 1 + }; + + this.scrollMargin = { + left: 0, + right: 0, + top: 0, + bottom: 0, + v: 0, + h: 0 + }; + + this.$loop = new RenderLoop( + this.$renderChanges.bind(this), + this.container.ownerDocument.defaultView + ); + this.$loop.schedule(this.CHANGE_FULL); + + this.updateCharacterSize(); + this.setPadding(4); + config.resetOptions(this); + config._emit("renderer", this); +}; + +(function() { + + this.CHANGE_CURSOR = 1; + this.CHANGE_MARKER = 2; + this.CHANGE_GUTTER = 4; + this.CHANGE_SCROLL = 8; + this.CHANGE_LINES = 16; + this.CHANGE_TEXT = 32; + this.CHANGE_SIZE = 64; + this.CHANGE_MARKER_BACK = 128; + this.CHANGE_MARKER_FRONT = 256; + this.CHANGE_FULL = 512; + this.CHANGE_H_SCROLL = 1024; + + oop.implement(this, EventEmitter); + + this.updateCharacterSize = function() { + if (this.$textLayer.allowBoldFonts != this.$allowBoldFonts) { + this.$allowBoldFonts = this.$textLayer.allowBoldFonts; + this.setStyle("ace_nobold", !this.$allowBoldFonts); + } + + this.layerConfig.characterWidth = + this.characterWidth = this.$textLayer.getCharacterWidth(); + this.layerConfig.lineHeight = + this.lineHeight = this.$textLayer.getLineHeight(); + this.$updatePrintMargin(); + }; + this.setSession = function(session) { + if (this.session) + this.session.doc.off("changeNewLineMode", this.onChangeNewLineMode); + + this.session = session; + if (session && this.scrollMargin.top && session.getScrollTop() <= 0) + session.setScrollTop(-this.scrollMargin.top); + + this.$cursorLayer.setSession(session); + this.$markerBack.setSession(session); + this.$markerFront.setSession(session); + this.$gutterLayer.setSession(session); + this.$textLayer.setSession(session); + if (!session) + return; + + this.$loop.schedule(this.CHANGE_FULL); + this.session.$setFontMetrics(this.$fontMetrics); + + this.onChangeNewLineMode = this.onChangeNewLineMode.bind(this); + this.onChangeNewLineMode() + this.session.doc.on("changeNewLineMode", this.onChangeNewLineMode); + }; + this.updateLines = function(firstRow, lastRow, force) { + if (lastRow === undefined) + lastRow = Infinity; + + if (!this.$changedLines) { + this.$changedLines = { + firstRow: firstRow, + lastRow: lastRow + }; + } + else { + if (this.$changedLines.firstRow > firstRow) + this.$changedLines.firstRow = firstRow; + + if (this.$changedLines.lastRow < lastRow) + this.$changedLines.lastRow = lastRow; + } + if (this.$changedLines.lastRow < this.layerConfig.firstRow) { + if (force) + this.$changedLines.lastRow = this.layerConfig.lastRow; + else + return; + } + if (this.$changedLines.firstRow > this.layerConfig.lastRow) + return; + this.$loop.schedule(this.CHANGE_LINES); + }; + + this.onChangeNewLineMode = function() { + this.$loop.schedule(this.CHANGE_TEXT); + this.$textLayer.$updateEolChar(); + }; + + this.onChangeTabSize = function() { + this.$loop.schedule(this.CHANGE_TEXT | this.CHANGE_MARKER); + this.$textLayer.onChangeTabSize(); + }; + this.updateText = function() { + this.$loop.schedule(this.CHANGE_TEXT); + }; + this.updateFull = function(force) { + if (force) + this.$renderChanges(this.CHANGE_FULL, true); + else + this.$loop.schedule(this.CHANGE_FULL); + }; + this.updateFontSize = function() { + this.$textLayer.checkForSizeChanges(); + }; + + this.$changes = 0; + this.$updateSizeAsync = function() { + if (this.$loop.pending) + this.$size.$dirty = true; + else + this.onResize(); + }; + this.onResize = function(force, gutterWidth, width, height) { + if (this.resizing > 2) + return; + else if (this.resizing > 0) + this.resizing++; + else + this.resizing = force ? 1 : 0; + var el = this.container; + if (!height) + height = el.clientHeight || el.scrollHeight; + if (!width) + width = el.clientWidth || el.scrollWidth; + var changes = this.$updateCachedSize(force, gutterWidth, width, height); + + + if (!this.$size.scrollerHeight || (!width && !height)) + return this.resizing = 0; + + if (force) + this.$gutterLayer.$padding = null; + + if (force) + this.$renderChanges(changes | this.$changes, true); + else + this.$loop.schedule(changes | this.$changes); + + if (this.resizing) + this.resizing = 0; + this.scrollBarV.scrollLeft = this.scrollBarV.scrollTop = null; + }; + + this.$updateCachedSize = function(force, gutterWidth, width, height) { + height -= (this.$extraHeight || 0); + var changes = 0; + var size = this.$size; + var oldSize = { + width: size.width, + height: size.height, + scrollerHeight: size.scrollerHeight, + scrollerWidth: size.scrollerWidth + }; + if (height && (force || size.height != height)) { + size.height = height; + changes |= this.CHANGE_SIZE; + + size.scrollerHeight = size.height; + if (this.$horizScroll) + size.scrollerHeight -= this.scrollBarH.getHeight(); + this.scrollBarV.element.style.bottom = this.scrollBarH.getHeight() + "px"; + + changes = changes | this.CHANGE_SCROLL; + } + + if (width && (force || size.width != width)) { + changes |= this.CHANGE_SIZE; + size.width = width; + + if (gutterWidth == null) + gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; + + this.gutterWidth = gutterWidth; + + this.scrollBarH.element.style.left = + this.scroller.style.left = gutterWidth + "px"; + size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth()); + + this.scrollBarH.element.style.right = + this.scroller.style.right = this.scrollBarV.getWidth() + "px"; + this.scroller.style.bottom = this.scrollBarH.getHeight() + "px"; + + if (this.session && this.session.getUseWrapMode() && this.adjustWrapLimit() || force) + changes |= this.CHANGE_FULL; + } + + size.$dirty = !width || !height; + + if (changes) + this._signal("resize", oldSize); + + return changes; + }; + + this.onGutterResize = function() { + var gutterWidth = this.$showGutter ? this.$gutter.offsetWidth : 0; + if (gutterWidth != this.gutterWidth) + this.$changes |= this.$updateCachedSize(true, gutterWidth, this.$size.width, this.$size.height); + + if (this.session.getUseWrapMode() && this.adjustWrapLimit()) { + this.$loop.schedule(this.CHANGE_FULL); + } else if (this.$size.$dirty) { + this.$loop.schedule(this.CHANGE_FULL); + } else { + this.$computeLayerConfig(); + this.$loop.schedule(this.CHANGE_MARKER); + } + }; + this.adjustWrapLimit = function() { + var availableWidth = this.$size.scrollerWidth - this.$padding * 2; + var limit = Math.floor(availableWidth / this.characterWidth); + return this.session.adjustWrapLimit(limit, this.$showPrintMargin && this.$printMarginColumn); + }; + this.setAnimatedScroll = function(shouldAnimate){ + this.setOption("animatedScroll", shouldAnimate); + }; + this.getAnimatedScroll = function() { + return this.$animatedScroll; + }; + this.setShowInvisibles = function(showInvisibles) { + this.setOption("showInvisibles", showInvisibles); + }; + this.getShowInvisibles = function() { + return this.getOption("showInvisibles"); + }; + this.getDisplayIndentGuides = function() { + return this.getOption("displayIndentGuides"); + }; + + this.setDisplayIndentGuides = function(display) { + this.setOption("displayIndentGuides", display); + }; + this.setShowPrintMargin = function(showPrintMargin) { + this.setOption("showPrintMargin", showPrintMargin); + }; + this.getShowPrintMargin = function() { + return this.getOption("showPrintMargin"); + }; + this.setPrintMarginColumn = function(showPrintMargin) { + this.setOption("printMarginColumn", showPrintMargin); + }; + this.getPrintMarginColumn = function() { + return this.getOption("printMarginColumn"); + }; + this.getShowGutter = function(){ + return this.getOption("showGutter"); + }; + this.setShowGutter = function(show){ + return this.setOption("showGutter", show); + }; + + this.getFadeFoldWidgets = function(){ + return this.getOption("fadeFoldWidgets") + }; + + this.setFadeFoldWidgets = function(show) { + this.setOption("fadeFoldWidgets", show); + }; + + this.setHighlightGutterLine = function(shouldHighlight) { + this.setOption("highlightGutterLine", shouldHighlight); + }; + + this.getHighlightGutterLine = function() { + return this.getOption("highlightGutterLine"); + }; + + this.$updateGutterLineHighlight = function() { + var pos = this.$cursorLayer.$pixelPos; + var height = this.layerConfig.lineHeight; + if (this.session.getUseWrapMode()) { + var cursor = this.session.selection.getCursor(); + cursor.column = 0; + pos = this.$cursorLayer.getPixelPosition(cursor, true); + height *= this.session.getRowLength(cursor.row); + } + this.$gutterLineHighlight.style.top = pos.top - this.layerConfig.offset + "px"; + this.$gutterLineHighlight.style.height = height + "px"; + }; + + this.$updatePrintMargin = function() { + if (!this.$showPrintMargin && !this.$printMarginEl) + return; + + if (!this.$printMarginEl) { + var containerEl = dom.createElement("div"); + containerEl.className = "ace_layer ace_print-margin-layer"; + this.$printMarginEl = dom.createElement("div"); + this.$printMarginEl.className = "ace_print-margin"; + containerEl.appendChild(this.$printMarginEl); + this.content.insertBefore(containerEl, this.content.firstChild); + } + + var style = this.$printMarginEl.style; + style.left = ((this.characterWidth * this.$printMarginColumn) + this.$padding) + "px"; + style.visibility = this.$showPrintMargin ? "visible" : "hidden"; + + if (this.session && this.session.$wrap == -1) + this.adjustWrapLimit(); + }; + this.getContainerElement = function() { + return this.container; + }; + this.getMouseEventTarget = function() { + return this.content; + }; + this.getTextAreaContainer = function() { + return this.container; + }; + this.$moveTextAreaToCursor = function() { + if (!this.$keepTextAreaAtCursor) + return; + var config = this.layerConfig; + var posTop = this.$cursorLayer.$pixelPos.top; + var posLeft = this.$cursorLayer.$pixelPos.left; + posTop -= config.offset; + + var style = this.textarea.style; + var h = this.lineHeight; + if (posTop < 0 || posTop > config.height - h) { + style.top = style.left = "0"; + return; + } + + var w = this.characterWidth; + if (this.$composition) { + var val = this.textarea.value.replace(/^\x01+/, ""); + w *= (this.session.$getStringScreenWidth(val)[0]+2); + h += 2; + } + posLeft -= this.scrollLeft; + if (posLeft > this.$size.scrollerWidth - w) + posLeft = this.$size.scrollerWidth - w; + + posLeft += this.gutterWidth; + style.height = h + "px"; + style.width = w + "px"; + style.left = Math.min(posLeft, this.$size.scrollerWidth - w) + "px"; + style.top = Math.min(posTop, this.$size.height - h) + "px"; + }; + this.getFirstVisibleRow = function() { + return this.layerConfig.firstRow; + }; + this.getFirstFullyVisibleRow = function() { + return this.layerConfig.firstRow + (this.layerConfig.offset === 0 ? 0 : 1); + }; + this.getLastFullyVisibleRow = function() { + var flint = Math.floor((this.layerConfig.height + this.layerConfig.offset) / this.layerConfig.lineHeight); + return this.layerConfig.firstRow - 1 + flint; + }; + this.getLastVisibleRow = function() { + return this.layerConfig.lastRow; + }; + + this.$padding = null; + this.setPadding = function(padding) { + this.$padding = padding; + this.$textLayer.setPadding(padding); + this.$cursorLayer.setPadding(padding); + this.$markerFront.setPadding(padding); + this.$markerBack.setPadding(padding); + this.$loop.schedule(this.CHANGE_FULL); + this.$updatePrintMargin(); + }; + + this.setScrollMargin = function(top, bottom, left, right) { + var sm = this.scrollMargin; + sm.top = top|0; + sm.bottom = bottom|0; + sm.right = right|0; + sm.left = left|0; + sm.v = sm.top + sm.bottom; + sm.h = sm.left + sm.right; + if (sm.top && this.scrollTop <= 0 && this.session) + this.session.setScrollTop(-sm.top); + this.updateFull(); + }; + this.getHScrollBarAlwaysVisible = function() { + return this.$hScrollBarAlwaysVisible; + }; + this.setHScrollBarAlwaysVisible = function(alwaysVisible) { + this.setOption("hScrollBarAlwaysVisible", alwaysVisible); + }; + this.getVScrollBarAlwaysVisible = function() { + return this.$vScrollBarAlwaysVisible; + }; + this.setVScrollBarAlwaysVisible = function(alwaysVisible) { + this.setOption("vScrollBarAlwaysVisible", alwaysVisible); + }; + + this.$updateScrollBarV = function() { + var scrollHeight = this.layerConfig.maxHeight; + var scrollerHeight = this.$size.scrollerHeight; + if (!this.$maxLines && this.$scrollPastEnd) { + scrollHeight -= (scrollerHeight - this.lineHeight) * this.$scrollPastEnd; + if (this.scrollTop > scrollHeight - scrollerHeight) { + scrollHeight = this.scrollTop + scrollerHeight; + this.scrollBarV.scrollTop = null; + } + } + this.scrollBarV.setScrollHeight(scrollHeight + this.scrollMargin.v); + this.scrollBarV.setScrollTop(this.scrollTop + this.scrollMargin.top); + }; + this.$updateScrollBarH = function() { + this.scrollBarH.setScrollWidth(this.layerConfig.width + 2 * this.$padding + this.scrollMargin.h); + this.scrollBarH.setScrollLeft(this.scrollLeft + this.scrollMargin.left); + }; + + this.$frozen = false; + this.freeze = function() { + this.$frozen = true; + }; + + this.unfreeze = function() { + this.$frozen = false; + }; + + this.$renderChanges = function(changes, force) { + if (this.$changes) { + changes |= this.$changes; + this.$changes = 0; + } + if ((!this.session || !this.container.offsetWidth || this.$frozen) || (!changes && !force)) { + this.$changes |= changes; + return; + } + if (this.$size.$dirty) { + this.$changes |= changes; + return this.onResize(true); + } + if (!this.lineHeight) { + this.$textLayer.checkForSizeChanges(); + } + + this._signal("beforeRender"); + var config = this.layerConfig; + if (changes & this.CHANGE_FULL || + changes & this.CHANGE_SIZE || + changes & this.CHANGE_TEXT || + changes & this.CHANGE_LINES || + changes & this.CHANGE_SCROLL || + changes & this.CHANGE_H_SCROLL + ) { + changes |= this.$computeLayerConfig(); + if (config.firstRow != this.layerConfig.firstRow && config.firstRowScreen == this.layerConfig.firstRowScreen) { + var st = this.scrollTop + (config.firstRow - this.layerConfig.firstRow) * this.lineHeight; + if (st > 0) { + this.scrollTop = st; + changes = changes | this.CHANGE_SCROLL; + changes |= this.$computeLayerConfig(); + } + } + config = this.layerConfig; + this.$updateScrollBarV(); + if (changes & this.CHANGE_H_SCROLL) + this.$updateScrollBarH(); + this.$gutterLayer.element.style.marginTop = (-config.offset) + "px"; + this.content.style.marginTop = (-config.offset) + "px"; + this.content.style.width = config.width + 2 * this.$padding + "px"; + this.content.style.height = config.minHeight + "px"; + } + if (changes & this.CHANGE_H_SCROLL) { + this.content.style.marginLeft = -this.scrollLeft + "px"; + this.scroller.className = this.scrollLeft <= 0 ? "ace_scroller" : "ace_scroller ace_scroll-left"; + } + if (changes & this.CHANGE_FULL) { + this.$textLayer.update(config); + if (this.$showGutter) + this.$gutterLayer.update(config); + this.$markerBack.update(config); + this.$markerFront.update(config); + this.$cursorLayer.update(config); + this.$moveTextAreaToCursor(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + this._signal("afterRender"); + return; + } + if (changes & this.CHANGE_SCROLL) { + if (changes & this.CHANGE_TEXT || changes & this.CHANGE_LINES) + this.$textLayer.update(config); + else + this.$textLayer.scrollLines(config); + + if (this.$showGutter) + this.$gutterLayer.update(config); + this.$markerBack.update(config); + this.$markerFront.update(config); + this.$cursorLayer.update(config); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + this.$moveTextAreaToCursor(); + this._signal("afterRender"); + return; + } + + if (changes & this.CHANGE_TEXT) { + this.$textLayer.update(config); + if (this.$showGutter) + this.$gutterLayer.update(config); + } + else if (changes & this.CHANGE_LINES) { + if (this.$updateLines() || (changes & this.CHANGE_GUTTER) && this.$showGutter) + this.$gutterLayer.update(config); + } + else if (changes & this.CHANGE_TEXT || changes & this.CHANGE_GUTTER) { + if (this.$showGutter) + this.$gutterLayer.update(config); + } + + if (changes & this.CHANGE_CURSOR) { + this.$cursorLayer.update(config); + this.$moveTextAreaToCursor(); + this.$highlightGutterLine && this.$updateGutterLineHighlight(); + } + + if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_FRONT)) { + this.$markerFront.update(config); + } + + if (changes & (this.CHANGE_MARKER | this.CHANGE_MARKER_BACK)) { + this.$markerBack.update(config); + } + + this._signal("afterRender"); + }; + + + this.$autosize = function() { + var height = this.session.getScreenLength() * this.lineHeight; + var maxHeight = this.$maxLines * this.lineHeight; + var desiredHeight = Math.max( + (this.$minLines||1) * this.lineHeight, + Math.min(maxHeight, height) + ) + this.scrollMargin.v + (this.$extraHeight || 0); + var vScroll = height > maxHeight; + + if (desiredHeight != this.desiredHeight || + this.$size.height != this.desiredHeight || vScroll != this.$vScroll) { + if (vScroll != this.$vScroll) { + this.$vScroll = vScroll; + this.scrollBarV.setVisible(vScroll); + } + + var w = this.container.clientWidth; + this.container.style.height = desiredHeight + "px"; + this.$updateCachedSize(true, this.$gutterWidth, w, desiredHeight); + this.desiredHeight = desiredHeight; + + this._signal("autosize"); + } + }; + + this.$computeLayerConfig = function() { + if (this.$maxLines && this.lineHeight > 1) + this.$autosize(); + + var session = this.session; + var size = this.$size; + + var hideScrollbars = size.height <= 2 * this.lineHeight; + var screenLines = this.session.getScreenLength(); + var maxHeight = screenLines * this.lineHeight; + + var offset = this.scrollTop % this.lineHeight; + var minHeight = size.scrollerHeight + this.lineHeight; + + var longestLine = this.$getLongestLine(); + + var horizScroll = !hideScrollbars && (this.$hScrollBarAlwaysVisible || + size.scrollerWidth - longestLine - 2 * this.$padding < 0); + + var hScrollChanged = this.$horizScroll !== horizScroll; + if (hScrollChanged) { + this.$horizScroll = horizScroll; + this.scrollBarH.setVisible(horizScroll); + } + + var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd + ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd + : 0; + maxHeight += scrollPastEnd; + + this.session.setScrollTop(Math.max(-this.scrollMargin.top, + Math.min(this.scrollTop, maxHeight - size.scrollerHeight + this.scrollMargin.bottom))); + + this.session.setScrollLeft(Math.max(-this.scrollMargin.left, Math.min(this.scrollLeft, + longestLine + 2 * this.$padding - size.scrollerWidth + this.scrollMargin.right))); + + var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible || + size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop); + var vScrollChanged = this.$vScroll !== vScroll; + if (vScrollChanged) { + this.$vScroll = vScroll; + this.scrollBarV.setVisible(vScroll); + } + + var lineCount = Math.ceil(minHeight / this.lineHeight) - 1; + var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight)); + var lastRow = firstRow + lineCount; + var firstRowScreen, firstRowHeight; + var lineHeight = this.lineHeight; + firstRow = session.screenToDocumentRow(firstRow, 0); + var foldLine = session.getFoldLine(firstRow); + if (foldLine) { + firstRow = foldLine.start.row; + } + + firstRowScreen = session.documentToScreenRow(firstRow, 0); + firstRowHeight = session.getRowLength(firstRow) * lineHeight; + + lastRow = Math.min(session.screenToDocumentRow(lastRow, 0), session.getLength() - 1); + minHeight = size.scrollerHeight + session.getRowLength(lastRow) * lineHeight + + firstRowHeight; + + offset = this.scrollTop - firstRowScreen * lineHeight; + + var changes = 0; + if (this.layerConfig.width != longestLine) + changes = this.CHANGE_H_SCROLL; + if (hScrollChanged || vScrollChanged) { + changes = this.$updateCachedSize(true, this.gutterWidth, size.width, size.height); + this._signal("scrollbarVisibilityChanged"); + if (vScrollChanged) + longestLine = this.$getLongestLine(); + } + + this.layerConfig = { + width : longestLine, + padding : this.$padding, + firstRow : firstRow, + firstRowScreen: firstRowScreen, + lastRow : lastRow, + lineHeight : lineHeight, + characterWidth : this.characterWidth, + minHeight : minHeight, + maxHeight : maxHeight, + offset : offset, + gutterOffset : Math.max(0, Math.ceil((offset + size.height - size.scrollerHeight) / lineHeight)), + height : this.$size.scrollerHeight + }; + + return changes; + }; + + this.$updateLines = function() { + var firstRow = this.$changedLines.firstRow; + var lastRow = this.$changedLines.lastRow; + this.$changedLines = null; + + var layerConfig = this.layerConfig; + + if (firstRow > layerConfig.lastRow + 1) { return; } + if (lastRow < layerConfig.firstRow) { return; } + if (lastRow === Infinity) { + if (this.$showGutter) + this.$gutterLayer.update(layerConfig); + this.$textLayer.update(layerConfig); + return; + } + this.$textLayer.updateLines(layerConfig, firstRow, lastRow); + return true; + }; + + this.$getLongestLine = function() { + var charCount = this.session.getScreenWidth(); + if (this.showInvisibles && !this.session.$useWrapMode) + charCount += 1; + + return Math.max(this.$size.scrollerWidth - 2 * this.$padding, Math.round(charCount * this.characterWidth)); + }; + this.updateFrontMarkers = function() { + this.$markerFront.setMarkers(this.session.getMarkers(true)); + this.$loop.schedule(this.CHANGE_MARKER_FRONT); + }; + this.updateBackMarkers = function() { + this.$markerBack.setMarkers(this.session.getMarkers()); + this.$loop.schedule(this.CHANGE_MARKER_BACK); + }; + this.addGutterDecoration = function(row, className){ + this.$gutterLayer.addGutterDecoration(row, className); + }; + this.removeGutterDecoration = function(row, className){ + this.$gutterLayer.removeGutterDecoration(row, className); + }; + this.updateBreakpoints = function(rows) { + this.$loop.schedule(this.CHANGE_GUTTER); + }; + this.setAnnotations = function(annotations) { + this.$gutterLayer.setAnnotations(annotations); + this.$loop.schedule(this.CHANGE_GUTTER); + }; + this.updateCursor = function() { + this.$loop.schedule(this.CHANGE_CURSOR); + }; + this.hideCursor = function() { + this.$cursorLayer.hideCursor(); + }; + this.showCursor = function() { + this.$cursorLayer.showCursor(); + }; + + this.scrollSelectionIntoView = function(anchor, lead, offset) { + this.scrollCursorIntoView(anchor, offset); + this.scrollCursorIntoView(lead, offset); + }; + this.scrollCursorIntoView = function(cursor, offset, $viewMargin) { + if (this.$size.scrollerHeight === 0) + return; + + var pos = this.$cursorLayer.getPixelPosition(cursor); + + var left = pos.left; + var top = pos.top; + + var topMargin = $viewMargin && $viewMargin.top || 0; + var bottomMargin = $viewMargin && $viewMargin.bottom || 0; + + var scrollTop = this.$scrollAnimation ? this.session.getScrollTop() : this.scrollTop; + + if (scrollTop + topMargin > top) { + if (offset) + top -= offset * this.$size.scrollerHeight; + if (top === 0) + top = -this.scrollMargin.top; + this.session.setScrollTop(top); + } else if (scrollTop + this.$size.scrollerHeight - bottomMargin < top + this.lineHeight) { + if (offset) + top += offset * this.$size.scrollerHeight; + this.session.setScrollTop(top + this.lineHeight - this.$size.scrollerHeight); + } + + var scrollLeft = this.scrollLeft; + + if (scrollLeft > left) { + if (left < this.$padding + 2 * this.layerConfig.characterWidth) + left = -this.scrollMargin.left; + this.session.setScrollLeft(left); + } else if (scrollLeft + this.$size.scrollerWidth < left + this.characterWidth) { + this.session.setScrollLeft(Math.round(left + this.characterWidth - this.$size.scrollerWidth)); + } else if (scrollLeft <= this.$padding && left - scrollLeft < this.characterWidth) { + this.session.setScrollLeft(0); + } + }; + this.getScrollTop = function() { + return this.session.getScrollTop(); + }; + this.getScrollLeft = function() { + return this.session.getScrollLeft(); + }; + this.getScrollTopRow = function() { + return this.scrollTop / this.lineHeight; + }; + this.getScrollBottomRow = function() { + return Math.max(0, Math.floor((this.scrollTop + this.$size.scrollerHeight) / this.lineHeight) - 1); + }; + this.scrollToRow = function(row) { + this.session.setScrollTop(row * this.lineHeight); + }; + + this.alignCursor = function(cursor, alignment) { + if (typeof cursor == "number") + cursor = {row: cursor, column: 0}; + + var pos = this.$cursorLayer.getPixelPosition(cursor); + var h = this.$size.scrollerHeight - this.lineHeight; + var offset = pos.top - h * (alignment || 0); + + this.session.setScrollTop(offset); + return offset; + }; + + this.STEPS = 8; + this.$calcSteps = function(fromValue, toValue){ + var i = 0; + var l = this.STEPS; + var steps = []; + + var func = function(t, x_min, dx) { + return dx * (Math.pow(t - 1, 3) + 1) + x_min; + }; + + for (i = 0; i < l; ++i) + steps.push(func(i / this.STEPS, fromValue, toValue - fromValue)); + + return steps; + }; + this.scrollToLine = function(line, center, animate, callback) { + var pos = this.$cursorLayer.getPixelPosition({row: line, column: 0}); + var offset = pos.top; + if (center) + offset -= this.$size.scrollerHeight / 2; + + var initialScroll = this.scrollTop; + this.session.setScrollTop(offset); + if (animate !== false) + this.animateScrolling(initialScroll, callback); + }; + + this.animateScrolling = function(fromValue, callback) { + var toValue = this.scrollTop; + if (!this.$animatedScroll) + return; + var _self = this; + + if (fromValue == toValue) + return; + + if (this.$scrollAnimation) { + var oldSteps = this.$scrollAnimation.steps; + if (oldSteps.length) { + fromValue = oldSteps[0]; + if (fromValue == toValue) + return; + } + } + + var steps = _self.$calcSteps(fromValue, toValue); + this.$scrollAnimation = {from: fromValue, to: toValue, steps: steps}; + + clearInterval(this.$timer); + + _self.session.setScrollTop(steps.shift()); + _self.session.$scrollTop = toValue; + this.$timer = setInterval(function() { + if (steps.length) { + _self.session.setScrollTop(steps.shift()); + _self.session.$scrollTop = toValue; + } else if (toValue != null) { + _self.session.$scrollTop = -1; + _self.session.setScrollTop(toValue); + toValue = null; + } else { + _self.$timer = clearInterval(_self.$timer); + _self.$scrollAnimation = null; + callback && callback(); + } + }, 10); + }; + this.scrollToY = function(scrollTop) { + if (this.scrollTop !== scrollTop) { + this.$loop.schedule(this.CHANGE_SCROLL); + this.scrollTop = scrollTop; + } + }; + this.scrollToX = function(scrollLeft) { + if (this.scrollLeft !== scrollLeft) + this.scrollLeft = scrollLeft; + this.$loop.schedule(this.CHANGE_H_SCROLL); + }; + this.scrollTo = function(x, y) { + this.session.setScrollTop(y); + this.session.setScrollLeft(y); + }; + this.scrollBy = function(deltaX, deltaY) { + deltaY && this.session.setScrollTop(this.session.getScrollTop() + deltaY); + deltaX && this.session.setScrollLeft(this.session.getScrollLeft() + deltaX); + }; + this.isScrollableBy = function(deltaX, deltaY) { + if (deltaY < 0 && this.session.getScrollTop() >= 1 - this.scrollMargin.top) + return true; + if (deltaY > 0 && this.session.getScrollTop() + this.$size.scrollerHeight + - this.layerConfig.maxHeight < -1 + this.scrollMargin.bottom) + return true; + if (deltaX < 0 && this.session.getScrollLeft() >= 1 - this.scrollMargin.left) + return true; + if (deltaX > 0 && this.session.getScrollLeft() + this.$size.scrollerWidth + - this.layerConfig.width < -1 + this.scrollMargin.right) + return true; + }; + + this.pixelToScreenCoordinates = function(x, y) { + var canvasPos = this.scroller.getBoundingClientRect(); + + var offset = (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth; + var row = Math.floor((y + this.scrollTop - canvasPos.top) / this.lineHeight); + var col = Math.round(offset); + + return {row: row, column: col, side: offset - col > 0 ? 1 : -1}; + }; + + this.screenToTextCoordinates = function(x, y) { + var canvasPos = this.scroller.getBoundingClientRect(); + + var col = Math.round( + (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth + ); + + var row = (y + this.scrollTop - canvasPos.top) / this.lineHeight; + + return this.session.screenToDocumentPosition(row, Math.max(col, 0)); + }; + this.textToScreenCoordinates = function(row, column) { + var canvasPos = this.scroller.getBoundingClientRect(); + var pos = this.session.documentToScreenPosition(row, column); + + var x = this.$padding + Math.round(pos.column * this.characterWidth); + var y = pos.row * this.lineHeight; + + return { + pageX: canvasPos.left + x - this.scrollLeft, + pageY: canvasPos.top + y - this.scrollTop + }; + }; + this.visualizeFocus = function() { + dom.addCssClass(this.container, "ace_focus"); + }; + this.visualizeBlur = function() { + dom.removeCssClass(this.container, "ace_focus"); + }; + this.showComposition = function(position) { + if (!this.$composition) + this.$composition = { + keepTextAreaAtCursor: this.$keepTextAreaAtCursor, + cssText: this.textarea.style.cssText + }; + + this.$keepTextAreaAtCursor = true; + dom.addCssClass(this.textarea, "ace_composition"); + this.textarea.style.cssText = ""; + this.$moveTextAreaToCursor(); + }; + this.setCompositionText = function(text) { + this.$moveTextAreaToCursor(); + }; + this.hideComposition = function() { + if (!this.$composition) + return; + + dom.removeCssClass(this.textarea, "ace_composition"); + this.$keepTextAreaAtCursor = this.$composition.keepTextAreaAtCursor; + this.textarea.style.cssText = this.$composition.cssText; + this.$composition = null; + }; + this.setTheme = function(theme, cb) { + var _self = this; + this.$themeId = theme; + _self._dispatchEvent('themeChange',{theme:theme}); + + if (!theme || typeof theme == "string") { + var moduleName = theme || this.$options.theme.initialValue; + config.loadModule(["theme", moduleName], afterLoad); + } else { + afterLoad(theme); + } + + function afterLoad(module) { + if (_self.$themeId != theme) + return cb && cb(); + if (!module.cssClass) + return; + dom.importCssString( + module.cssText, + module.cssClass, + _self.container.ownerDocument + ); + + if (_self.theme) + dom.removeCssClass(_self.container, _self.theme.cssClass); + + var padding = "padding" in module ? module.padding + : "padding" in (_self.theme || {}) ? 4 : _self.$padding; + if (_self.$padding && padding != _self.$padding) + _self.setPadding(padding); + _self.$theme = module.cssClass; + + _self.theme = module; + dom.addCssClass(_self.container, module.cssClass); + dom.setCssClass(_self.container, "ace_dark", module.isDark); + if (_self.$size) { + _self.$size.width = 0; + _self.$updateSizeAsync(); + } + + _self._dispatchEvent('themeLoaded', {theme:module}); + cb && cb(); + } + }; + this.getTheme = function() { + return this.$themeId; + }; + this.setStyle = function(style, include) { + dom.setCssClass(this.container, style, include !== false); + }; + this.unsetStyle = function(style) { + dom.removeCssClass(this.container, style); + }; + + this.setCursorStyle = function(style) { + if (this.scroller.style.cursor != style) + this.scroller.style.cursor = style; + }; + this.setMouseCursor = function(cursorStyle) { + this.scroller.style.cursor = cursorStyle; + }; + this.destroy = function() { + this.$textLayer.destroy(); + this.$cursorLayer.destroy(); + }; + +}).call(VirtualRenderer.prototype); + + +config.defineOptions(VirtualRenderer.prototype, "renderer", { + animatedScroll: {initialValue: false}, + showInvisibles: { + set: function(value) { + if (this.$textLayer.setShowInvisibles(value)) + this.$loop.schedule(this.CHANGE_TEXT); + }, + initialValue: false + }, + showPrintMargin: { + set: function() { this.$updatePrintMargin(); }, + initialValue: true + }, + printMarginColumn: { + set: function() { this.$updatePrintMargin(); }, + initialValue: 80 + }, + printMargin: { + set: function(val) { + if (typeof val == "number") + this.$printMarginColumn = val; + this.$showPrintMargin = !!val; + this.$updatePrintMargin(); + }, + get: function() { + return this.$showPrintMargin && this.$printMarginColumn; + } + }, + showGutter: { + set: function(show){ + this.$gutter.style.display = show ? "block" : "none"; + this.$loop.schedule(this.CHANGE_FULL); + this.onGutterResize(); + }, + initialValue: true + }, + fadeFoldWidgets: { + set: function(show) { + dom.setCssClass(this.$gutter, "ace_fade-fold-widgets", show); + }, + initialValue: false + }, + showFoldWidgets: { + set: function(show) {this.$gutterLayer.setShowFoldWidgets(show)}, + initialValue: true + }, + showLineNumbers: { + set: function(show) { + this.$gutterLayer.setShowLineNumbers(show); + this.$loop.schedule(this.CHANGE_GUTTER); + }, + initialValue: true + }, + displayIndentGuides: { + set: function(show) { + if (this.$textLayer.setDisplayIndentGuides(show)) + this.$loop.schedule(this.CHANGE_TEXT); + }, + initialValue: true + }, + highlightGutterLine: { + set: function(shouldHighlight) { + if (!this.$gutterLineHighlight) { + this.$gutterLineHighlight = dom.createElement("div"); + this.$gutterLineHighlight.className = "ace_gutter-active-line"; + this.$gutter.appendChild(this.$gutterLineHighlight); + return; + } + + this.$gutterLineHighlight.style.display = shouldHighlight ? "" : "none"; + if (this.$cursorLayer.$pixelPos) + this.$updateGutterLineHighlight(); + }, + initialValue: false, + value: true + }, + hScrollBarAlwaysVisible: { + set: function(val) { + if (!this.$hScrollBarAlwaysVisible || !this.$horizScroll) + this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: false + }, + vScrollBarAlwaysVisible: { + set: function(val) { + if (!this.$vScrollBarAlwaysVisible || !this.$vScroll) + this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: false + }, + fontSize: { + set: function(size) { + if (typeof size == "number") + size = size + "px"; + this.container.style.fontSize = size; + this.updateFontSize(); + }, + initialValue: 12 + }, + fontFamily: { + set: function(name) { + this.container.style.fontFamily = name; + this.updateFontSize(); + } + }, + maxLines: { + set: function(val) { + this.updateFull(); + } + }, + minLines: { + set: function(val) { + this.updateFull(); + } + }, + scrollPastEnd: { + set: function(val) { + val = +val || 0; + if (this.$scrollPastEnd == val) + return; + this.$scrollPastEnd = val; + this.$loop.schedule(this.CHANGE_SCROLL); + }, + initialValue: 0, + handlesSet: true + }, + fixedWidthGutter: { + set: function(val) { + this.$gutterLayer.$fixedWidth = !!val; + this.$loop.schedule(this.CHANGE_GUTTER); + } + }, + theme: { + set: function(val) { this.setTheme(val) }, + get: function() { return this.$themeId || this.theme; }, + initialValue: "./theme/textmate", + handlesSet: true + } +}); + +exports.VirtualRenderer = VirtualRenderer; +}); + +define("ace/worker/worker_client",["require","exports","module","ace/lib/oop","ace/lib/net","ace/lib/event_emitter","ace/config"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var net = require("../lib/net"); +var EventEmitter = require("../lib/event_emitter").EventEmitter; +var config = require("../config"); + +var WorkerClient = function(topLevelNamespaces, mod, classname, workerUrl) { + this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this); + this.changeListener = this.changeListener.bind(this); + this.onMessage = this.onMessage.bind(this); + if (require.nameToUrl && !require.toUrl) + require.toUrl = require.nameToUrl; + + if (config.get("packaged") || !require.toUrl) { + workerUrl = workerUrl || config.moduleUrl(mod, "worker"); + } else { + var normalizePath = this.$normalizePath; + workerUrl = workerUrl || normalizePath(require.toUrl("ace/worker/worker.js", null, "_")); + + var tlns = {}; + topLevelNamespaces.forEach(function(ns) { + tlns[ns] = normalizePath(require.toUrl(ns, null, "_").replace(/(\.js)?(\?.*)?$/, "")); + }); + } + + try { + this.$worker = new Worker(workerUrl); + } catch(e) { + if (e instanceof window.DOMException) { + var blob = this.$workerBlob(workerUrl); + var URL = window.URL || window.webkitURL; + var blobURL = URL.createObjectURL(blob); + + this.$worker = new Worker(blobURL); + URL.revokeObjectURL(blobURL); + } else { + throw e; + } + } + this.$worker.postMessage({ + init : true, + tlns : tlns, + module : mod, + classname : classname + }); + + this.callbackId = 1; + this.callbacks = {}; + + this.$worker.onmessage = this.onMessage; +}; + +(function(){ + + oop.implement(this, EventEmitter); + + this.onMessage = function(e) { + var msg = e.data; + switch(msg.type) { + case "event": + this._signal(msg.name, {data: msg.data}); + break; + case "call": + var callback = this.callbacks[msg.id]; + if (callback) { + callback(msg.data); + delete this.callbacks[msg.id]; + } + break; + case "error": + this.reportError(msg.data); + break; + case "log": + window.console && console.log && console.log.apply(console, msg.data); + break; + } + }; + + this.reportError = function(err) { + window.console && console.error && console.error(err); + }; + + this.$normalizePath = function(path) { + return net.qualifyURL(path); + }; + + this.terminate = function() { + this._signal("terminate", {}); + this.deltaQueue = null; + this.$worker.terminate(); + this.$worker = null; + if (this.$doc) + this.$doc.off("change", this.changeListener); + this.$doc = null; + }; + + this.send = function(cmd, args) { + this.$worker.postMessage({command: cmd, args: args}); + }; + + this.call = function(cmd, args, callback) { + if (callback) { + var id = this.callbackId++; + this.callbacks[id] = callback; + args.push(id); + } + this.send(cmd, args); + }; + + this.emit = function(event, data) { + try { + this.$worker.postMessage({event: event, data: {data: data.data}}); + } + catch(ex) { + console.error(ex.stack); + } + }; + + this.attachToDocument = function(doc) { + if(this.$doc) + this.terminate(); + + this.$doc = doc; + this.call("setValue", [doc.getValue()]); + doc.on("change", this.changeListener); + }; + + this.changeListener = function(e) { + if (!this.deltaQueue) { + this.deltaQueue = [e.data]; + setTimeout(this.$sendDeltaQueue, 0); + } else + this.deltaQueue.push(e.data); + }; + + this.$sendDeltaQueue = function() { + var q = this.deltaQueue; + if (!q) return; + this.deltaQueue = null; + if (q.length > 20 && q.length > this.$doc.getLength() >> 1) { + this.call("setValue", [this.$doc.getValue()]); + } else + this.emit("change", {data: q}); + }; + + this.$workerBlob = function(workerUrl) { + var script = "importScripts('" + net.qualifyURL(workerUrl) + "');"; + try { + return new Blob([script], {"type": "application/javascript"}); + } catch (e) { // Backwards-compatibility + var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder; + var blobBuilder = new BlobBuilder(); + blobBuilder.append(script); + return blobBuilder.getBlob("application/javascript"); + } + }; + +}).call(WorkerClient.prototype); + + +var UIWorkerClient = function(topLevelNamespaces, mod, classname) { + this.$sendDeltaQueue = this.$sendDeltaQueue.bind(this); + this.changeListener = this.changeListener.bind(this); + this.callbackId = 1; + this.callbacks = {}; + this.messageBuffer = []; + + var main = null; + var emitSync = false; + var sender = Object.create(EventEmitter); + var _self = this; + + this.$worker = {}; + this.$worker.terminate = function() {}; + this.$worker.postMessage = function(e) { + _self.messageBuffer.push(e); + if (main) { + if (emitSync) + setTimeout(processNext); + else + processNext(); + } + }; + this.setEmitSync = function(val) { emitSync = val }; + + var processNext = function() { + var msg = _self.messageBuffer.shift(); + if (msg.command) + main[msg.command].apply(main, msg.args); + else if (msg.event) + sender._signal(msg.event, msg.data); + }; + + sender.postMessage = function(msg) { + _self.onMessage({data: msg}); + }; + sender.callback = function(data, callbackId) { + this.postMessage({type: "call", id: callbackId, data: data}); + }; + sender.emit = function(name, data) { + this.postMessage({type: "event", name: name, data: data}); + }; + + config.loadModule(["worker", mod], function(Main) { + main = new Main[classname](sender); + while (_self.messageBuffer.length) + processNext(); + }); +}; + +UIWorkerClient.prototype = WorkerClient.prototype; + +exports.UIWorkerClient = UIWorkerClient; +exports.WorkerClient = WorkerClient; + +}); + +define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"], function(require, exports, module) { +"use strict"; + +var Range = require("./range").Range; +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var oop = require("./lib/oop"); + +var PlaceHolder = function(session, length, pos, others, mainClass, othersClass) { + var _self = this; + this.length = length; + this.session = session; + this.doc = session.getDocument(); + this.mainClass = mainClass; + this.othersClass = othersClass; + this.$onUpdate = this.onUpdate.bind(this); + this.doc.on("change", this.$onUpdate); + this.$others = others; + + this.$onCursorChange = function() { + setTimeout(function() { + _self.onCursorChange(); + }); + }; + + this.$pos = pos; + var undoStack = session.getUndoManager().$undoStack || session.getUndoManager().$undostack || {length: -1}; + this.$undoStackDepth = undoStack.length; + this.setup(); + + session.selection.on("changeCursor", this.$onCursorChange); +}; + +(function() { + + oop.implement(this, EventEmitter); + this.setup = function() { + var _self = this; + var doc = this.doc; + var session = this.session; + var pos = this.$pos; + + this.selectionBefore = session.selection.toJSON(); + if (session.selection.inMultiSelectMode) + session.selection.toSingleRange(); + + this.pos = doc.createAnchor(pos.row, pos.column); + this.markerId = session.addMarker(new Range(pos.row, pos.column, pos.row, pos.column + this.length), this.mainClass, null, false); + this.pos.on("change", function(event) { + session.removeMarker(_self.markerId); + _self.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.mainClass, null, false); + }); + this.others = []; + this.$others.forEach(function(other) { + var anchor = doc.createAnchor(other.row, other.column); + _self.others.push(anchor); + }); + session.setUndoSelect(false); + }; + this.showOtherMarkers = function() { + if(this.othersActive) return; + var session = this.session; + var _self = this; + this.othersActive = true; + this.others.forEach(function(anchor) { + anchor.markerId = session.addMarker(new Range(anchor.row, anchor.column, anchor.row, anchor.column+_self.length), _self.othersClass, null, false); + anchor.on("change", function(event) { + session.removeMarker(anchor.markerId); + anchor.markerId = session.addMarker(new Range(event.value.row, event.value.column, event.value.row, event.value.column+_self.length), _self.othersClass, null, false); + }); + }); + }; + this.hideOtherMarkers = function() { + if(!this.othersActive) return; + this.othersActive = false; + for (var i = 0; i < this.others.length; i++) { + this.session.removeMarker(this.others[i].markerId); + } + }; + this.onUpdate = function(event) { + var delta = event.data; + var range = delta.range; + if(range.start.row !== range.end.row) return; + if(range.start.row !== this.pos.row) return; + if (this.$updating) return; + this.$updating = true; + var lengthDiff = delta.action === "insertText" ? range.end.column - range.start.column : range.start.column - range.end.column; + + if(range.start.column >= this.pos.column && range.start.column <= this.pos.column + this.length + 1) { + var distanceFromStart = range.start.column - this.pos.column; + this.length += lengthDiff; + if(!this.session.$fromUndo) { + if(delta.action === "insertText") { + for (var i = this.others.length - 1; i >= 0; i--) { + var otherPos = this.others[i]; + var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; + if(otherPos.row === range.start.row && range.start.column < otherPos.column) + newPos.column += lengthDiff; + this.doc.insert(newPos, delta.text); + } + } else if(delta.action === "removeText") { + for (var i = this.others.length - 1; i >= 0; i--) { + var otherPos = this.others[i]; + var newPos = {row: otherPos.row, column: otherPos.column + distanceFromStart}; + if(otherPos.row === range.start.row && range.start.column < otherPos.column) + newPos.column += lengthDiff; + this.doc.remove(new Range(newPos.row, newPos.column, newPos.row, newPos.column - lengthDiff)); + } + } + if(range.start.column === this.pos.column && delta.action === "insertText") { + setTimeout(function() { + this.pos.setPosition(this.pos.row, this.pos.column - lengthDiff); + for (var i = 0; i < this.others.length; i++) { + var other = this.others[i]; + var newPos = {row: other.row, column: other.column - lengthDiff}; + if(other.row === range.start.row && range.start.column < other.column) + newPos.column += lengthDiff; + other.setPosition(newPos.row, newPos.column); + } + }.bind(this), 0); + } + else if(range.start.column === this.pos.column && delta.action === "removeText") { + setTimeout(function() { + for (var i = 0; i < this.others.length; i++) { + var other = this.others[i]; + if(other.row === range.start.row && range.start.column < other.column) { + other.setPosition(other.row, other.column - lengthDiff); + } + } + }.bind(this), 0); + } + } + this.pos._emit("change", {value: this.pos}); + for (var i = 0; i < this.others.length; i++) { + this.others[i]._emit("change", {value: this.others[i]}); + } + } + this.$updating = false; + }; + + this.onCursorChange = function(event) { + if (this.$updating || !this.session) return; + var pos = this.session.selection.getCursor(); + if (pos.row === this.pos.row && pos.column >= this.pos.column && pos.column <= this.pos.column + this.length) { + this.showOtherMarkers(); + this._emit("cursorEnter", event); + } else { + this.hideOtherMarkers(); + this._emit("cursorLeave", event); + } + }; + this.detach = function() { + this.session.removeMarker(this.markerId); + this.hideOtherMarkers(); + this.doc.removeEventListener("change", this.$onUpdate); + this.session.selection.removeEventListener("changeCursor", this.$onCursorChange); + this.pos.detach(); + for (var i = 0; i < this.others.length; i++) { + this.others[i].detach(); + } + this.session.setUndoSelect(true); + this.session = null; + }; + this.cancel = function() { + if(this.$undoStackDepth === -1) + throw Error("Canceling placeholders only supported with undo manager attached to session."); + var undoManager = this.session.getUndoManager(); + var undosRequired = (undoManager.$undoStack || undoManager.$undostack).length - this.$undoStackDepth; + for (var i = 0; i < undosRequired; i++) { + undoManager.undo(true); + } + if (this.selectionBefore) + this.session.selection.fromJSON(this.selectionBefore); + }; +}).call(PlaceHolder.prototype); + + +exports.PlaceHolder = PlaceHolder; +}); + +define("ace/mouse/multi_select_handler",["require","exports","module","ace/lib/event","ace/lib/useragent"], function(require, exports, module) { + +var event = require("../lib/event"); +var useragent = require("../lib/useragent"); +function isSamePoint(p1, p2) { + return p1.row == p2.row && p1.column == p2.column; +} + +function onMouseDown(e) { + var ev = e.domEvent; + var alt = ev.altKey; + var shift = ev.shiftKey; + var ctrl = ev.ctrlKey; + var accel = e.getAccelKey(); + var button = e.getButton(); + + if (ctrl && useragent.isMac) + button = ev.button; + + if (e.editor.inMultiSelectMode && button == 2) { + e.editor.textInput.onContextMenu(e.domEvent); + return; + } + + if (!ctrl && !alt && !accel) { + if (button === 0 && e.editor.inMultiSelectMode) + e.editor.exitMultiSelectMode(); + return; + } + + if (button !== 0) + return; + + var editor = e.editor; + var selection = editor.selection; + var isMultiSelect = editor.inMultiSelectMode; + var pos = e.getDocumentPosition(); + var cursor = selection.getCursor(); + var inSelection = e.inSelection() || (selection.isEmpty() && isSamePoint(pos, cursor)); + + var mouseX = e.x, mouseY = e.y; + var onMouseSelection = function(e) { + mouseX = e.clientX; + mouseY = e.clientY; + }; + + var session = editor.session; + var screenAnchor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); + var screenCursor = screenAnchor; + + var selectionMode; + if (editor.$mouseHandler.$enableJumpToDef) { + if (ctrl && alt || accel && alt) + selectionMode = "add"; + else if (alt) + selectionMode = "block"; + } else { + if (accel && !alt) { + selectionMode = "add"; + if (!isMultiSelect && shift) + return; + } else if (alt) { + selectionMode = "block"; + } + } + + if (selectionMode && useragent.isMac && ev.ctrlKey) { + editor.$mouseHandler.cancelContextMenu(); + } + + if (selectionMode == "add") { + if (!isMultiSelect && inSelection) + return; // dragging + + if (!isMultiSelect) { + var range = selection.toOrientedRange(); + editor.addSelectionMarker(range); + } + + var oldRange = selection.rangeList.rangeAtPoint(pos); + + + editor.$blockScrolling++; + editor.inVirtualSelectionMode = true; + + if (shift) { + oldRange = null; + range = selection.ranges[0]; + editor.removeSelectionMarker(range); + } + editor.once("mouseup", function() { + var tmpSel = selection.toOrientedRange(); + + if (oldRange && tmpSel.isEmpty() && isSamePoint(oldRange.cursor, tmpSel.cursor)) + selection.substractPoint(tmpSel.cursor); + else { + if (shift) { + selection.substractPoint(range.cursor); + } else if (range) { + editor.removeSelectionMarker(range); + selection.addRange(range); + } + selection.addRange(tmpSel); + } + editor.$blockScrolling--; + editor.inVirtualSelectionMode = false; + }); + + } else if (selectionMode == "block") { + e.stop(); + editor.inVirtualSelectionMode = true; + var initialRange; + var rectSel = []; + var blockSelect = function() { + var newCursor = editor.renderer.pixelToScreenCoordinates(mouseX, mouseY); + var cursor = session.screenToDocumentPosition(newCursor.row, newCursor.column); + + if (isSamePoint(screenCursor, newCursor) && isSamePoint(cursor, selection.lead)) + return; + screenCursor = newCursor; + + editor.$blockScrolling++; + editor.selection.moveToPosition(cursor); + editor.renderer.scrollCursorIntoView(); + + editor.removeSelectionMarkers(rectSel); + rectSel = selection.rectangularRangeBlock(screenCursor, screenAnchor); + if (editor.$mouseHandler.$clickSelection && rectSel.length == 1 && rectSel[0].isEmpty()) + rectSel[0] = editor.$mouseHandler.$clickSelection.clone(); + rectSel.forEach(editor.addSelectionMarker, editor); + editor.updateSelectionMarkers(); + editor.$blockScrolling--; + }; + editor.$blockScrolling++; + if (isMultiSelect && !accel) { + selection.toSingleRange(); + } else if (!isMultiSelect && accel) { + initialRange = selection.toOrientedRange(); + editor.addSelectionMarker(initialRange); + } + + if (shift) + screenAnchor = session.documentToScreenPosition(selection.lead); + else + selection.moveToPosition(pos); + editor.$blockScrolling--; + + screenCursor = {row: -1, column: -1}; + + var onMouseSelectionEnd = function(e) { + clearInterval(timerId); + editor.removeSelectionMarkers(rectSel); + if (!rectSel.length) + rectSel = [selection.toOrientedRange()]; + editor.$blockScrolling++; + if (initialRange) { + editor.removeSelectionMarker(initialRange); + selection.toSingleRange(initialRange); + } + for (var i = 0; i < rectSel.length; i++) + selection.addRange(rectSel[i]); + editor.inVirtualSelectionMode = false; + editor.$mouseHandler.$clickSelection = null; + editor.$blockScrolling--; + }; + + var onSelectionInterval = blockSelect; + + event.capture(editor.container, onMouseSelection, onMouseSelectionEnd); + var timerId = setInterval(function() {onSelectionInterval();}, 20); + + return e.preventDefault(); + } +} + + +exports.onMouseDown = onMouseDown; + +}); + +define("ace/commands/multi_select_commands",["require","exports","module","ace/keyboard/hash_handler"], function(require, exports, module) { +exports.defaultCommands = [{ + name: "addCursorAbove", + exec: function(editor) { editor.selectMoreLines(-1); }, + bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"}, + scrollIntoView: "cursor", + readonly: true +}, { + name: "addCursorBelow", + exec: function(editor) { editor.selectMoreLines(1); }, + bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"}, + scrollIntoView: "cursor", + readonly: true +}, { + name: "addCursorAboveSkipCurrent", + exec: function(editor) { editor.selectMoreLines(-1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"}, + scrollIntoView: "cursor", + readonly: true +}, { + name: "addCursorBelowSkipCurrent", + exec: function(editor) { editor.selectMoreLines(1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"}, + scrollIntoView: "cursor", + readonly: true +}, { + name: "selectMoreBefore", + exec: function(editor) { editor.selectMore(-1); }, + bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"}, + scrollIntoView: "cursor", + readonly: true +}, { + name: "selectMoreAfter", + exec: function(editor) { editor.selectMore(1); }, + bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"}, + scrollIntoView: "cursor", + readonly: true +}, { + name: "selectNextBefore", + exec: function(editor) { editor.selectMore(-1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"}, + scrollIntoView: "cursor", + readonly: true +}, { + name: "selectNextAfter", + exec: function(editor) { editor.selectMore(1, true); }, + bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"}, + scrollIntoView: "cursor", + readonly: true +}, { + name: "splitIntoLines", + exec: function(editor) { editor.multiSelect.splitIntoLines(); }, + bindKey: {win: "Ctrl-Alt-L", mac: "Ctrl-Alt-L"}, + readonly: true +}, { + name: "alignCursors", + exec: function(editor) { editor.alignCursors(); }, + bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"}, + scrollIntoView: "cursor" +}, { + name: "findAll", + exec: function(editor) { editor.findAll(); }, + bindKey: {win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G"}, + scrollIntoView: "cursor", + readonly: true +}]; +exports.multiSelectCommands = [{ + name: "singleSelection", + bindKey: "esc", + exec: function(editor) { editor.exitMultiSelectMode(); }, + scrollIntoView: "cursor", + readonly: true, + isAvailable: function(editor) {return editor && editor.inMultiSelectMode} +}]; + +var HashHandler = require("../keyboard/hash_handler").HashHandler; +exports.keyboardHandler = new HashHandler(exports.multiSelectCommands); + +}); + +define("ace/multi_select",["require","exports","module","ace/range_list","ace/range","ace/selection","ace/mouse/multi_select_handler","ace/lib/event","ace/lib/lang","ace/commands/multi_select_commands","ace/search","ace/edit_session","ace/editor","ace/config"], function(require, exports, module) { + +var RangeList = require("./range_list").RangeList; +var Range = require("./range").Range; +var Selection = require("./selection").Selection; +var onMouseDown = require("./mouse/multi_select_handler").onMouseDown; +var event = require("./lib/event"); +var lang = require("./lib/lang"); +var commands = require("./commands/multi_select_commands"); +exports.commands = commands.defaultCommands.concat(commands.multiSelectCommands); +var Search = require("./search").Search; +var search = new Search(); + +function find(session, needle, dir) { + search.$options.wrap = true; + search.$options.needle = needle; + search.$options.backwards = dir == -1; + return search.find(session); +} +var EditSession = require("./edit_session").EditSession; +(function() { + this.getSelectionMarkers = function() { + return this.$selectionMarkers; + }; +}).call(EditSession.prototype); +(function() { + this.ranges = null; + this.rangeList = null; + this.addRange = function(range, $blockChangeEvents) { + if (!range) + return; + + if (!this.inMultiSelectMode && this.rangeCount === 0) { + var oldRange = this.toOrientedRange(); + this.rangeList.add(oldRange); + this.rangeList.add(range); + if (this.rangeList.ranges.length != 2) { + this.rangeList.removeAll(); + return $blockChangeEvents || this.fromOrientedRange(range); + } + this.rangeList.removeAll(); + this.rangeList.add(oldRange); + this.$onAddRange(oldRange); + } + + if (!range.cursor) + range.cursor = range.end; + + var removed = this.rangeList.add(range); + + this.$onAddRange(range); + + if (removed.length) + this.$onRemoveRange(removed); + + if (this.rangeCount > 1 && !this.inMultiSelectMode) { + this._signal("multiSelect"); + this.inMultiSelectMode = true; + this.session.$undoSelect = false; + this.rangeList.attach(this.session); + } + + return $blockChangeEvents || this.fromOrientedRange(range); + }; + + this.toSingleRange = function(range) { + range = range || this.ranges[0]; + var removed = this.rangeList.removeAll(); + if (removed.length) + this.$onRemoveRange(removed); + + range && this.fromOrientedRange(range); + }; + this.substractPoint = function(pos) { + var removed = this.rangeList.substractPoint(pos); + if (removed) { + this.$onRemoveRange(removed); + return removed[0]; + } + }; + this.mergeOverlappingRanges = function() { + var removed = this.rangeList.merge(); + if (removed.length) + this.$onRemoveRange(removed); + else if(this.ranges[0]) + this.fromOrientedRange(this.ranges[0]); + }; + + this.$onAddRange = function(range) { + this.rangeCount = this.rangeList.ranges.length; + this.ranges.unshift(range); + this._signal("addRange", {range: range}); + }; + + this.$onRemoveRange = function(removed) { + this.rangeCount = this.rangeList.ranges.length; + if (this.rangeCount == 1 && this.inMultiSelectMode) { + var lastRange = this.rangeList.ranges.pop(); + removed.push(lastRange); + this.rangeCount = 0; + } + + for (var i = removed.length; i--; ) { + var index = this.ranges.indexOf(removed[i]); + this.ranges.splice(index, 1); + } + + this._signal("removeRange", {ranges: removed}); + + if (this.rangeCount === 0 && this.inMultiSelectMode) { + this.inMultiSelectMode = false; + this._signal("singleSelect"); + this.session.$undoSelect = true; + this.rangeList.detach(this.session); + } + + lastRange = lastRange || this.ranges[0]; + if (lastRange && !lastRange.isEqual(this.getRange())) + this.fromOrientedRange(lastRange); + }; + this.$initRangeList = function() { + if (this.rangeList) + return; + + this.rangeList = new RangeList(); + this.ranges = []; + this.rangeCount = 0; + }; + this.getAllRanges = function() { + return this.rangeCount ? this.rangeList.ranges.concat() : [this.getRange()]; + }; + + this.splitIntoLines = function () { + if (this.rangeCount > 1) { + var ranges = this.rangeList.ranges; + var lastRange = ranges[ranges.length - 1]; + var range = Range.fromPoints(ranges[0].start, lastRange.end); + + this.toSingleRange(); + this.setSelectionRange(range, lastRange.cursor == lastRange.start); + } else { + var range = this.getRange(); + var isBackwards = this.isBackwards(); + var startRow = range.start.row; + var endRow = range.end.row; + if (startRow == endRow) { + if (isBackwards) + var start = range.end, end = range.start; + else + var start = range.start, end = range.end; + + this.addRange(Range.fromPoints(end, end)); + this.addRange(Range.fromPoints(start, start)); + return; + } + + var rectSel = []; + var r = this.getLineRange(startRow, true); + r.start.column = range.start.column; + rectSel.push(r); + + for (var i = startRow + 1; i < endRow; i++) + rectSel.push(this.getLineRange(i, true)); + + r = this.getLineRange(endRow, true); + r.end.column = range.end.column; + rectSel.push(r); + + rectSel.forEach(this.addRange, this); + } + }; + this.toggleBlockSelection = function () { + if (this.rangeCount > 1) { + var ranges = this.rangeList.ranges; + var lastRange = ranges[ranges.length - 1]; + var range = Range.fromPoints(ranges[0].start, lastRange.end); + + this.toSingleRange(); + this.setSelectionRange(range, lastRange.cursor == lastRange.start); + } else { + var cursor = this.session.documentToScreenPosition(this.selectionLead); + var anchor = this.session.documentToScreenPosition(this.selectionAnchor); + + var rectSel = this.rectangularRangeBlock(cursor, anchor); + rectSel.forEach(this.addRange, this); + } + }; + this.rectangularRangeBlock = function(screenCursor, screenAnchor, includeEmptyLines) { + var rectSel = []; + + var xBackwards = screenCursor.column < screenAnchor.column; + if (xBackwards) { + var startColumn = screenCursor.column; + var endColumn = screenAnchor.column; + } else { + var startColumn = screenAnchor.column; + var endColumn = screenCursor.column; + } + + var yBackwards = screenCursor.row < screenAnchor.row; + if (yBackwards) { + var startRow = screenCursor.row; + var endRow = screenAnchor.row; + } else { + var startRow = screenAnchor.row; + var endRow = screenCursor.row; + } + + if (startColumn < 0) + startColumn = 0; + if (startRow < 0) + startRow = 0; + + if (startRow == endRow) + includeEmptyLines = true; + + for (var row = startRow; row <= endRow; row++) { + var range = Range.fromPoints( + this.session.screenToDocumentPosition(row, startColumn), + this.session.screenToDocumentPosition(row, endColumn) + ); + if (range.isEmpty()) { + if (docEnd && isSamePoint(range.end, docEnd)) + break; + var docEnd = range.end; + } + range.cursor = xBackwards ? range.start : range.end; + rectSel.push(range); + } + + if (yBackwards) + rectSel.reverse(); + + if (!includeEmptyLines) { + var end = rectSel.length - 1; + while (rectSel[end].isEmpty() && end > 0) + end--; + if (end > 0) { + var start = 0; + while (rectSel[start].isEmpty()) + start++; + } + for (var i = end; i >= start; i--) { + if (rectSel[i].isEmpty()) + rectSel.splice(i, 1); + } + } + + return rectSel; + }; +}).call(Selection.prototype); +var Editor = require("./editor").Editor; +(function() { + this.updateSelectionMarkers = function() { + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + this.addSelectionMarker = function(orientedRange) { + if (!orientedRange.cursor) + orientedRange.cursor = orientedRange.end; + + var style = this.getSelectionStyle(); + orientedRange.marker = this.session.addMarker(orientedRange, "ace_selection", style); + + this.session.$selectionMarkers.push(orientedRange); + this.session.selectionMarkerCount = this.session.$selectionMarkers.length; + return orientedRange; + }; + this.removeSelectionMarker = function(range) { + if (!range.marker) + return; + this.session.removeMarker(range.marker); + var index = this.session.$selectionMarkers.indexOf(range); + if (index != -1) + this.session.$selectionMarkers.splice(index, 1); + this.session.selectionMarkerCount = this.session.$selectionMarkers.length; + }; + + this.removeSelectionMarkers = function(ranges) { + var markerList = this.session.$selectionMarkers; + for (var i = ranges.length; i--; ) { + var range = ranges[i]; + if (!range.marker) + continue; + this.session.removeMarker(range.marker); + var index = markerList.indexOf(range); + if (index != -1) + markerList.splice(index, 1); + } + this.session.selectionMarkerCount = markerList.length; + }; + + this.$onAddRange = function(e) { + this.addSelectionMarker(e.range); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onRemoveRange = function(e) { + this.removeSelectionMarkers(e.ranges); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onMultiSelect = function(e) { + if (this.inMultiSelectMode) + return; + this.inMultiSelectMode = true; + + this.setStyle("ace_multiselect"); + this.keyBinding.addKeyboardHandler(commands.keyboardHandler); + this.commands.setDefaultHandler("exec", this.$onMultiSelectExec); + + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + }; + + this.$onSingleSelect = function(e) { + if (this.session.multiSelect.inVirtualMode) + return; + this.inMultiSelectMode = false; + + this.unsetStyle("ace_multiselect"); + this.keyBinding.removeKeyboardHandler(commands.keyboardHandler); + + this.commands.removeDefaultHandler("exec", this.$onMultiSelectExec); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + this._emit("changeSelection"); + }; + + this.$onMultiSelectExec = function(e) { + var command = e.command; + var editor = e.editor; + if (!editor.multiSelect) + return; + if (!command.multiSelectAction) { + var result = command.exec(editor, e.args || {}); + editor.multiSelect.addRange(editor.multiSelect.toOrientedRange()); + editor.multiSelect.mergeOverlappingRanges(); + } else if (command.multiSelectAction == "forEach") { + result = editor.forEachSelection(command, e.args); + } else if (command.multiSelectAction == "forEachLine") { + result = editor.forEachSelection(command, e.args, true); + } else if (command.multiSelectAction == "single") { + editor.exitMultiSelectMode(); + result = command.exec(editor, e.args || {}); + } else { + result = command.multiSelectAction(editor, e.args || {}); + } + return result; + }; + this.forEachSelection = function(cmd, args, options) { + if (this.inVirtualSelectionMode) + return; + var keepOrder = options && options.keepOrder; + var $byLines = options == true || options && options.$byLines + var session = this.session; + var selection = this.selection; + var rangeList = selection.rangeList; + var ranges = (keepOrder ? selection : rangeList).ranges; + var result; + + if (!ranges.length) + return cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {}); + + var reg = selection._eventRegistry; + selection._eventRegistry = {}; + + var tmpSel = new Selection(session); + this.inVirtualSelectionMode = true; + for (var i = ranges.length; i--;) { + if ($byLines) { + while (i > 0 && ranges[i].start.row == ranges[i - 1].end.row) + i--; + } + tmpSel.fromOrientedRange(ranges[i]); + tmpSel.index = i; + this.selection = session.selection = tmpSel; + var cmdResult = cmd.exec ? cmd.exec(this, args || {}) : cmd(this, args || {}); + if (!result && cmdResult !== undefined) + result = cmdResult; + tmpSel.toOrientedRange(ranges[i]); + } + tmpSel.detach(); + + this.selection = session.selection = selection; + this.inVirtualSelectionMode = false; + selection._eventRegistry = reg; + selection.mergeOverlappingRanges(); + + var anim = this.renderer.$scrollAnimation; + this.onCursorChange(); + this.onSelectionChange(); + if (anim && anim.from == anim.to) + this.renderer.animateScrolling(anim.from); + + return result; + }; + this.exitMultiSelectMode = function() { + if (!this.inMultiSelectMode || this.inVirtualSelectionMode) + return; + this.multiSelect.toSingleRange(); + }; + + this.getSelectedText = function() { + var text = ""; + if (this.inMultiSelectMode && !this.inVirtualSelectionMode) { + var ranges = this.multiSelect.rangeList.ranges; + var buf = []; + for (var i = 0; i < ranges.length; i++) { + buf.push(this.session.getTextRange(ranges[i])); + } + var nl = this.session.getDocument().getNewLineCharacter(); + text = buf.join(nl); + if (text.length == (buf.length - 1) * nl.length) + text = ""; + } else if (!this.selection.isEmpty()) { + text = this.session.getTextRange(this.getSelectionRange()); + } + return text; + }; + + this.$checkMultiselectChange = function(e, anchor) { + if (this.inMultiSelectMode && !this.inVirtualSelectionMode) { + var range = this.multiSelect.ranges[0]; + if (this.multiSelect.isEmpty() && anchor == this.multiSelect.anchor) + return; + var pos = anchor == this.multiSelect.anchor + ? range.cursor == range.start ? range.end : range.start + : range.cursor; + if (pos.row != anchor.row + || this.session.$clipPositionToDocument(pos.row, pos.column).column != anchor.column) + this.multiSelect.toSingleRange(this.multiSelect.toOrientedRange()); + } + }; + this.findAll = function(needle, options, additive) { + options = options || {}; + options.needle = needle || options.needle; + if (options.needle == undefined) { + var range = this.selection.isEmpty() + ? this.selection.getWordRange() + : this.selection.getRange(); + options.needle = this.session.getTextRange(range); + } + this.$search.set(options); + + var ranges = this.$search.findAll(this.session); + if (!ranges.length) + return 0; + + this.$blockScrolling += 1; + var selection = this.multiSelect; + + if (!additive) + selection.toSingleRange(ranges[0]); + + for (var i = ranges.length; i--; ) + selection.addRange(ranges[i], true); + if (range && selection.rangeList.rangeAtPoint(range.start)) + selection.addRange(range, true); + + this.$blockScrolling -= 1; + + return ranges.length; + }; + this.selectMoreLines = function(dir, skip) { + var range = this.selection.toOrientedRange(); + var isBackwards = range.cursor == range.end; + + var screenLead = this.session.documentToScreenPosition(range.cursor); + if (this.selection.$desiredColumn) + screenLead.column = this.selection.$desiredColumn; + + var lead = this.session.screenToDocumentPosition(screenLead.row + dir, screenLead.column); + + if (!range.isEmpty()) { + var screenAnchor = this.session.documentToScreenPosition(isBackwards ? range.end : range.start); + var anchor = this.session.screenToDocumentPosition(screenAnchor.row + dir, screenAnchor.column); + } else { + var anchor = lead; + } + + if (isBackwards) { + var newRange = Range.fromPoints(lead, anchor); + newRange.cursor = newRange.start; + } else { + var newRange = Range.fromPoints(anchor, lead); + newRange.cursor = newRange.end; + } + + newRange.desiredColumn = screenLead.column; + if (!this.selection.inMultiSelectMode) { + this.selection.addRange(range); + } else { + if (skip) + var toRemove = range.cursor; + } + + this.selection.addRange(newRange); + if (toRemove) + this.selection.substractPoint(toRemove); + }; + this.transposeSelections = function(dir) { + var session = this.session; + var sel = session.multiSelect; + var all = sel.ranges; + + for (var i = all.length; i--; ) { + var range = all[i]; + if (range.isEmpty()) { + var tmp = session.getWordRange(range.start.row, range.start.column); + range.start.row = tmp.start.row; + range.start.column = tmp.start.column; + range.end.row = tmp.end.row; + range.end.column = tmp.end.column; + } + } + sel.mergeOverlappingRanges(); + + var words = []; + for (var i = all.length; i--; ) { + var range = all[i]; + words.unshift(session.getTextRange(range)); + } + + if (dir < 0) + words.unshift(words.pop()); + else + words.push(words.shift()); + + for (var i = all.length; i--; ) { + var range = all[i]; + var tmp = range.clone(); + session.replace(range, words[i]); + range.start.row = tmp.start.row; + range.start.column = tmp.start.column; + } + }; + this.selectMore = function(dir, skip, stopAtFirst) { + var session = this.session; + var sel = session.multiSelect; + + var range = sel.toOrientedRange(); + if (range.isEmpty()) { + range = session.getWordRange(range.start.row, range.start.column); + range.cursor = dir == -1 ? range.start : range.end; + this.multiSelect.addRange(range); + if (stopAtFirst) + return; + } + var needle = session.getTextRange(range); + + var newRange = find(session, needle, dir); + if (newRange) { + newRange.cursor = dir == -1 ? newRange.start : newRange.end; + this.$blockScrolling += 1; + this.session.unfold(newRange); + this.multiSelect.addRange(newRange); + this.$blockScrolling -= 1; + this.renderer.scrollCursorIntoView(null, 0.5); + } + if (skip) + this.multiSelect.substractPoint(range.cursor); + }; + this.alignCursors = function() { + var session = this.session; + var sel = session.multiSelect; + var ranges = sel.ranges; + var row = -1; + var sameRowRanges = ranges.filter(function(r) { + if (r.cursor.row == row) + return true; + row = r.cursor.row; + }); + + if (!ranges.length || sameRowRanges.length == ranges.length - 1) { + var range = this.selection.getRange(); + var fr = range.start.row, lr = range.end.row; + var guessRange = fr == lr; + if (guessRange) { + var max = this.session.getLength(); + var line; + do { + line = this.session.getLine(lr); + } while (/[=:]/.test(line) && ++lr < max); + do { + line = this.session.getLine(fr); + } while (/[=:]/.test(line) && --fr > 0); + + if (fr < 0) fr = 0; + if (lr >= max) lr = max - 1; + } + var lines = this.session.doc.removeLines(fr, lr); + lines = this.$reAlignText(lines, guessRange); + this.session.doc.insert({row: fr, column: 0}, lines.join("\n") + "\n"); + if (!guessRange) { + range.start.column = 0; + range.end.column = lines[lines.length - 1].length; + } + this.selection.setRange(range); + } else { + sameRowRanges.forEach(function(r) { + sel.substractPoint(r.cursor); + }); + + var maxCol = 0; + var minSpace = Infinity; + var spaceOffsets = ranges.map(function(r) { + var p = r.cursor; + var line = session.getLine(p.row); + var spaceOffset = line.substr(p.column).search(/\S/g); + if (spaceOffset == -1) + spaceOffset = 0; + + if (p.column > maxCol) + maxCol = p.column; + if (spaceOffset < minSpace) + minSpace = spaceOffset; + return spaceOffset; + }); + ranges.forEach(function(r, i) { + var p = r.cursor; + var l = maxCol - p.column; + var d = spaceOffsets[i] - minSpace; + if (l > d) + session.insert(p, lang.stringRepeat(" ", l - d)); + else + session.remove(new Range(p.row, p.column, p.row, p.column - l + d)); + + r.start.column = r.end.column = maxCol; + r.start.row = r.end.row = p.row; + r.cursor = r.end; + }); + sel.fromOrientedRange(ranges[0]); + this.renderer.updateCursor(); + this.renderer.updateBackMarkers(); + } + }; + + this.$reAlignText = function(lines, forceLeft) { + var isLeftAligned = true, isRightAligned = true; + var startW, textW, endW; + + return lines.map(function(line) { + var m = line.match(/(\s*)(.*?)(\s*)([=:].*)/); + if (!m) + return [line]; + + if (startW == null) { + startW = m[1].length; + textW = m[2].length; + endW = m[3].length; + return m; + } + + if (startW + textW + endW != m[1].length + m[2].length + m[3].length) + isRightAligned = false; + if (startW != m[1].length) + isLeftAligned = false; + + if (startW > m[1].length) + startW = m[1].length; + if (textW < m[2].length) + textW = m[2].length; + if (endW > m[3].length) + endW = m[3].length; + + return m; + }).map(forceLeft ? alignLeft : + isLeftAligned ? isRightAligned ? alignRight : alignLeft : unAlign); + + function spaces(n) { + return lang.stringRepeat(" ", n); + } + + function alignLeft(m) { + return !m[2] ? m[0] : spaces(startW) + m[2] + + spaces(textW - m[2].length + endW) + + m[4].replace(/^([=:])\s+/, "$1 "); + } + function alignRight(m) { + return !m[2] ? m[0] : spaces(startW + textW - m[2].length) + m[2] + + spaces(endW, " ") + + m[4].replace(/^([=:])\s+/, "$1 "); + } + function unAlign(m) { + return !m[2] ? m[0] : spaces(startW) + m[2] + + spaces(endW) + + m[4].replace(/^([=:])\s+/, "$1 "); + } + }; +}).call(Editor.prototype); + + +function isSamePoint(p1, p2) { + return p1.row == p2.row && p1.column == p2.column; +} +exports.onSessionChange = function(e) { + var session = e.session; + if (session && !session.multiSelect) { + session.$selectionMarkers = []; + session.selection.$initRangeList(); + session.multiSelect = session.selection; + } + this.multiSelect = session && session.multiSelect; + + var oldSession = e.oldSession; + if (oldSession) { + oldSession.multiSelect.off("addRange", this.$onAddRange); + oldSession.multiSelect.off("removeRange", this.$onRemoveRange); + oldSession.multiSelect.off("multiSelect", this.$onMultiSelect); + oldSession.multiSelect.off("singleSelect", this.$onSingleSelect); + oldSession.multiSelect.lead.off("change", this.$checkMultiselectChange); + oldSession.multiSelect.anchor.off("change", this.$checkMultiselectChange); + } + + if (session) { + session.multiSelect.on("addRange", this.$onAddRange); + session.multiSelect.on("removeRange", this.$onRemoveRange); + session.multiSelect.on("multiSelect", this.$onMultiSelect); + session.multiSelect.on("singleSelect", this.$onSingleSelect); + session.multiSelect.lead.on("change", this.$checkMultiselectChange); + session.multiSelect.anchor.on("change", this.$checkMultiselectChange); + } + + if (session && this.inMultiSelectMode != session.selection.inMultiSelectMode) { + if (session.selection.inMultiSelectMode) + this.$onMultiSelect(); + else + this.$onSingleSelect(); + } +}; +function MultiSelect(editor) { + if (editor.$multiselectOnSessionChange) + return; + editor.$onAddRange = editor.$onAddRange.bind(editor); + editor.$onRemoveRange = editor.$onRemoveRange.bind(editor); + editor.$onMultiSelect = editor.$onMultiSelect.bind(editor); + editor.$onSingleSelect = editor.$onSingleSelect.bind(editor); + editor.$multiselectOnSessionChange = exports.onSessionChange.bind(editor); + editor.$checkMultiselectChange = editor.$checkMultiselectChange.bind(editor); + + editor.$multiselectOnSessionChange(editor); + editor.on("changeSession", editor.$multiselectOnSessionChange); + + editor.on("mousedown", onMouseDown); + editor.commands.addCommands(commands.defaultCommands); + + addAltCursorListeners(editor); +} + +function addAltCursorListeners(editor){ + var el = editor.textInput.getElement(); + var altCursor = false; + event.addListener(el, "keydown", function(e) { + if (e.keyCode == 18 && !(e.ctrlKey || e.shiftKey || e.metaKey)) { + if (!altCursor) { + editor.renderer.setMouseCursor("crosshair"); + altCursor = true; + } + } else if (altCursor) { + reset(); + } + }); + + event.addListener(el, "keyup", reset); + event.addListener(el, "blur", reset); + function reset(e) { + if (altCursor) { + editor.renderer.setMouseCursor(""); + altCursor = false; + } + } +} + +exports.MultiSelect = MultiSelect; + + +require("./config").defineOptions(Editor.prototype, "editor", { + enableMultiselect: { + set: function(val) { + MultiSelect(this); + if (val) { + this.on("changeSession", this.$multiselectOnSessionChange); + this.on("mousedown", onMouseDown); + } else { + this.off("changeSession", this.$multiselectOnSessionChange); + this.off("mousedown", onMouseDown); + } + }, + value: true + } +}); + + + +}); + +define("ace/mode/folding/fold_mode",["require","exports","module","ace/range"], function(require, exports, module) { +"use strict"; + +var Range = require("../../range").Range; + +var FoldMode = exports.FoldMode = function() {}; + +(function() { + + this.foldingStartMarker = null; + this.foldingStopMarker = null; + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + if (this.foldingStartMarker.test(line)) + return "start"; + if (foldStyle == "markbeginend" + && this.foldingStopMarker + && this.foldingStopMarker.test(line)) + return "end"; + return ""; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + return null; + }; + + this.indentationBlock = function(session, row, column) { + var re = /\S/; + var line = session.getLine(row); + var startLevel = line.search(re); + if (startLevel == -1) + return; + + var startColumn = column || line.length; + var maxRow = session.getLength(); + var startRow = row; + var endRow = row; + + while (++row < maxRow) { + var level = session.getLine(row).search(re); + + if (level == -1) + continue; + + if (level <= startLevel) + break; + + endRow = row; + } + + if (endRow > startRow) { + var endColumn = session.getLine(endRow).length; + return new Range(startRow, startColumn, endRow, endColumn); + } + }; + + this.openingBracketBlock = function(session, bracket, row, column, typeRe) { + var start = {row: row, column: column + 1}; + var end = session.$findClosingBracket(bracket, start, typeRe); + if (!end) + return; + + var fw = session.foldWidgets[end.row]; + if (fw == null) + fw = session.getFoldWidget(end.row); + + if (fw == "start" && end.row > start.row) { + end.row --; + end.column = session.getLine(end.row).length; + } + return Range.fromPoints(start, end); + }; + + this.closingBracketBlock = function(session, bracket, row, column, typeRe) { + var end = {row: row, column: column}; + var start = session.$findOpeningBracket(bracket, end); + + if (!start) + return; + + start.column++; + end.column--; + + return Range.fromPoints(start, end); + }; +}).call(FoldMode.prototype); + +}); + +define("ace/theme/textmate",["require","exports","module","ace/lib/dom"], function(require, exports, module) { +"use strict"; + +exports.isDark = false; +exports.cssClass = "ace-tm"; +exports.cssText = ".ace-tm .ace_gutter {\ +background: #f0f0f0;\ +color: #333;\ +}\ +.ace-tm .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8;\ +}\ +.ace-tm .ace_fold {\ +background-color: #6B72E6;\ +}\ +.ace-tm {\ +background-color: #FFFFFF;\ +color: black;\ +}\ +.ace-tm .ace_cursor {\ +color: black;\ +}\ +.ace-tm .ace_invisible {\ +color: rgb(191, 191, 191);\ +}\ +.ace-tm .ace_storage,\ +.ace-tm .ace_keyword {\ +color: blue;\ +}\ +.ace-tm .ace_constant {\ +color: rgb(197, 6, 11);\ +}\ +.ace-tm .ace_constant.ace_buildin {\ +color: rgb(88, 72, 246);\ +}\ +.ace-tm .ace_constant.ace_language {\ +color: rgb(88, 92, 246);\ +}\ +.ace-tm .ace_constant.ace_library {\ +color: rgb(6, 150, 14);\ +}\ +.ace-tm .ace_invalid {\ +background-color: rgba(255, 0, 0, 0.1);\ +color: red;\ +}\ +.ace-tm .ace_support.ace_function {\ +color: rgb(60, 76, 114);\ +}\ +.ace-tm .ace_support.ace_constant {\ +color: rgb(6, 150, 14);\ +}\ +.ace-tm .ace_support.ace_type,\ +.ace-tm .ace_support.ace_class {\ +color: rgb(109, 121, 222);\ +}\ +.ace-tm .ace_keyword.ace_operator {\ +color: rgb(104, 118, 135);\ +}\ +.ace-tm .ace_string {\ +color: rgb(3, 106, 7);\ +}\ +.ace-tm .ace_comment {\ +color: rgb(76, 136, 107);\ +}\ +.ace-tm .ace_comment.ace_doc {\ +color: rgb(0, 102, 255);\ +}\ +.ace-tm .ace_comment.ace_doc.ace_tag {\ +color: rgb(128, 159, 191);\ +}\ +.ace-tm .ace_constant.ace_numeric {\ +color: rgb(0, 0, 205);\ +}\ +.ace-tm .ace_variable {\ +color: rgb(49, 132, 149);\ +}\ +.ace-tm .ace_xml-pe {\ +color: rgb(104, 104, 91);\ +}\ +.ace-tm .ace_entity.ace_name.ace_function {\ +color: #0000A2;\ +}\ +.ace-tm .ace_heading {\ +color: rgb(12, 7, 255);\ +}\ +.ace-tm .ace_list {\ +color:rgb(185, 6, 144);\ +}\ +.ace-tm .ace_meta.ace_tag {\ +color:rgb(0, 22, 142);\ +}\ +.ace-tm .ace_string.ace_regex {\ +color: rgb(255, 0, 0)\ +}\ +.ace-tm .ace_marker-layer .ace_selection {\ +background: rgb(181, 213, 255);\ +}\ +.ace-tm.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px white;\ +border-radius: 2px;\ +}\ +.ace-tm .ace_marker-layer .ace_step {\ +background: rgb(252, 255, 0);\ +}\ +.ace-tm .ace_marker-layer .ace_stack {\ +background: rgb(164, 229, 101);\ +}\ +.ace-tm .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgb(192, 192, 192);\ +}\ +.ace-tm .ace_marker-layer .ace_active-line {\ +background: rgba(0, 0, 0, 0.07);\ +}\ +.ace-tm .ace_gutter-active-line {\ +background-color : #dcdcdc;\ +}\ +.ace-tm .ace_marker-layer .ace_selected-word {\ +background: rgb(250, 250, 255);\ +border: 1px solid rgb(200, 200, 250);\ +}\ +.ace-tm .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ +}\ +"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); + +define("ace/line_widgets",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/range"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var dom = require("./lib/dom"); +var Range = require("./range").Range; + + +function LineWidgets(session) { + this.session = session; + this.session.widgetManager = this; + this.session.getRowLength = this.getRowLength; + this.session.$getWidgetScreenLength = this.$getWidgetScreenLength; + this.updateOnChange = this.updateOnChange.bind(this); + this.renderWidgets = this.renderWidgets.bind(this); + this.measureWidgets = this.measureWidgets.bind(this); + this.session._changedWidgets = []; + this.$onChangeEditor = this.$onChangeEditor.bind(this); + + this.session.on("change", this.updateOnChange); + this.session.on("changeEditor", this.$onChangeEditor); +} + +(function() { + this.getRowLength = function(row) { + var h; + if (this.lineWidgets) + h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0; + else + h = 0; + if (!this.$useWrapMode || !this.$wrapData[row]) { + return 1 + h; + } else { + return this.$wrapData[row].length + 1 + h; + } + }; + + this.$getWidgetScreenLength = function() { + var screenRows = 0; + this.lineWidgets.forEach(function(w){ + if (w && w.rowCount) + screenRows +=w.rowCount; + }); + return screenRows; + }; + + this.$onChangeEditor = function(e) { + this.attach(e.editor); + }; + + this.attach = function(editor) { + if (editor && editor.widgetManager && editor.widgetManager != this) + editor.widgetManager.detach(); + + if (this.editor == editor) + return; + + this.detach(); + this.editor = editor; + + if (editor) { + editor.widgetManager = this; + editor.renderer.on("beforeRender", this.measureWidgets); + editor.renderer.on("afterRender", this.renderWidgets); + } + }; + this.detach = function(e) { + var editor = this.editor; + if (!editor) + return; + + this.editor = null; + editor.widgetManager = null; + + editor.renderer.off("beforeRender", this.measureWidgets); + editor.renderer.off("afterRender", this.renderWidgets); + var lineWidgets = this.session.lineWidgets; + lineWidgets && lineWidgets.forEach(function(w) { + if (w && w.el && w.el.parentNode) { + w._inDocument = false; + w.el.parentNode.removeChild(w.el); + } + }); + }; + + this.updateOnChange = function(e) { + var lineWidgets = this.session.lineWidgets; + if (!lineWidgets) return; + + var delta = e.data; + var range = delta.range; + var startRow = range.start.row; + var len = range.end.row - startRow; + + if (len === 0) { + } else if (delta.action == "removeText" || delta.action == "removeLines") { + var removed = lineWidgets.splice(startRow + 1, len); + removed.forEach(function(w) { + w && this.removeLineWidget(w); + }, this); + this.$updateRows(); + } else { + var args = new Array(len); + args.unshift(startRow, 0); + lineWidgets.splice.apply(lineWidgets, args); + this.$updateRows(); + } + }; + + this.$updateRows = function() { + var lineWidgets = this.session.lineWidgets; + if (!lineWidgets) return; + var noWidgets = true; + lineWidgets.forEach(function(w, i) { + if (w) { + noWidgets = false; + w.row = i; + } + }); + if (noWidgets) + this.session.lineWidgets = null; + }; + + this.addLineWidget = function(w) { + if (!this.session.lineWidgets) + this.session.lineWidgets = new Array(this.session.getLength()); + + this.session.lineWidgets[w.row] = w; + + var renderer = this.editor.renderer; + if (w.html && !w.el) { + w.el = dom.createElement("div"); + w.el.innerHTML = w.html; + } + if (w.el) { + dom.addCssClass(w.el, "ace_lineWidgetContainer"); + w.el.style.position = "absolute"; + w.el.style.zIndex = 5; + renderer.container.appendChild(w.el); + w._inDocument = true; + } + + if (!w.coverGutter) { + w.el.style.zIndex = 3; + } + if (!w.pixelHeight) { + w.pixelHeight = w.el.offsetHeight; + } + if (w.rowCount == null) + w.rowCount = w.pixelHeight / renderer.layerConfig.lineHeight; + + this.session._emit("changeFold", {data:{start:{row: w.row}}}); + + this.$updateRows(); + this.renderWidgets(null, renderer); + return w; + }; + + this.removeLineWidget = function(w) { + w._inDocument = false; + if (w.el && w.el.parentNode) + w.el.parentNode.removeChild(w.el); + if (w.editor && w.editor.destroy) try { + w.editor.destroy(); + } catch(e){} + if (this.session.lineWidgets) + this.session.lineWidgets[w.row] = undefined; + this.session._emit("changeFold", {data:{start:{row: w.row}}}); + this.$updateRows(); + }; + + this.onWidgetChanged = function(w) { + this.session._changedWidgets.push(w); + this.editor && this.editor.renderer.updateFull(); + }; + + this.measureWidgets = function(e, renderer) { + var changedWidgets = this.session._changedWidgets; + var config = renderer.layerConfig; + + if (!changedWidgets || !changedWidgets.length) return; + var min = Infinity; + for (var i = 0; i < changedWidgets.length; i++) { + var w = changedWidgets[i]; + if (!w._inDocument) { + w._inDocument = true; + renderer.container.appendChild(w.el); + } + + w.h = w.el.offsetHeight; + + if (!w.fixedWidth) { + w.w = w.el.offsetWidth; + w.screenWidth = Math.ceil(w.w / config.characterWidth); + } + + var rowCount = w.h / config.lineHeight; + if (w.coverLine) { + rowCount -= this.session.getRowLineCount(w.row); + if (rowCount < 0) + rowCount = 0; + } + if (w.rowCount != rowCount) { + w.rowCount = rowCount; + if (w.row < min) + min = w.row; + } + } + if (min != Infinity) { + this.session._emit("changeFold", {data:{start:{row: min}}}); + this.session.lineWidgetWidth = null; + } + this.session._changedWidgets = []; + }; + + this.renderWidgets = function(e, renderer) { + var config = renderer.layerConfig; + var lineWidgets = this.session.lineWidgets; + if (!lineWidgets) + return; + var first = Math.min(this.firstRow, config.firstRow); + var last = Math.max(this.lastRow, config.lastRow, lineWidgets.length); + + while (first > 0 && !lineWidgets[first]) + first--; + + this.firstRow = config.firstRow; + this.lastRow = config.lastRow; + + renderer.$cursorLayer.config = config; + for (var i = first; i <= last; i++) { + var w = lineWidgets[i]; + if (!w || !w.el) continue; + + if (!w._inDocument) { + w._inDocument = true; + renderer.container.appendChild(w.el); + } + var top = renderer.$cursorLayer.getPixelPosition({row: i, column:0}, true).top; + if (!w.coverLine) + top += config.lineHeight * this.session.getRowLineCount(w.row); + w.el.style.top = top - config.offset + "px"; + + var left = w.coverGutter ? 0 : renderer.gutterWidth; + if (!w.fixedWidth) + left -= renderer.scrollLeft; + w.el.style.left = left + "px"; + + if (w.fixedWidth) { + w.el.style.right = renderer.scrollBar.getWidth() + "px"; + } else { + w.el.style.right = ""; + } + } + }; + +}).call(LineWidgets.prototype); + + +exports.LineWidgets = LineWidgets; + +}); + +define("ace/ext/error_marker",["require","exports","module","ace/line_widgets","ace/lib/dom","ace/range"], function(require, exports, module) { +"use strict"; +var LineWidgets = require("../line_widgets").LineWidgets; +var dom = require("../lib/dom"); +var Range = require("../range").Range; + +function binarySearch(array, needle, comparator) { + var first = 0; + var last = array.length - 1; + + while (first <= last) { + var mid = (first + last) >> 1; + var c = comparator(needle, array[mid]); + if (c > 0) + first = mid + 1; + else if (c < 0) + last = mid - 1; + else + return mid; + } + return -(first + 1); +} + +function findAnnotations(session, row, dir) { + var annotations = session.getAnnotations().sort(Range.comparePoints); + if (!annotations.length) + return; + + var i = binarySearch(annotations, {row: row, column: -1}, Range.comparePoints); + if (i < 0) + i = -i - 1; + + if (i >= annotations.length) + i = dir > 0 ? 0 : annotations.length - 1; + else if (i === 0 && dir < 0) + i = annotations.length - 1; + + var annotation = annotations[i]; + if (!annotation || !dir) + return; + + if (annotation.row === row) { + do { + annotation = annotations[i += dir]; + } while (annotation && annotation.row === row); + if (!annotation) + return annotations.slice(); + } + + + var matched = []; + row = annotation.row; + do { + matched[dir < 0 ? "unshift" : "push"](annotation); + annotation = annotations[i += dir]; + } while (annotation && annotation.row == row); + return matched.length && matched; +} + +exports.showErrorMarker = function(editor, dir) { + var session = editor.session; + if (!session.widgetManager) { + session.widgetManager = new LineWidgets(session); + session.widgetManager.attach(editor); + } + + var pos = editor.getCursorPosition(); + var row = pos.row; + var oldWidget = session.lineWidgets && session.lineWidgets[row]; + if (oldWidget) { + oldWidget.destroy(); + } else { + row -= dir; + } + var annotations = findAnnotations(session, row, dir); + var gutterAnno; + if (annotations) { + var annotation = annotations[0]; + pos.column = (annotation.pos && typeof annotation.column != "number" + ? annotation.pos.sc + : annotation.column) || 0; + pos.row = annotation.row; + gutterAnno = editor.renderer.$gutterLayer.$annotations[pos.row]; + } else if (oldWidget) { + return; + } else { + gutterAnno = { + text: ["Looks good!"], + className: "ace_ok" + }; + } + editor.session.unfold(pos.row); + editor.selection.moveToPosition(pos); + + var w = { + row: pos.row, + fixedWidth: true, + coverGutter: true, + el: dom.createElement("div") + }; + var el = w.el.appendChild(dom.createElement("div")); + var arrow = w.el.appendChild(dom.createElement("div")); + arrow.className = "error_widget_arrow " + gutterAnno.className; + + var left = editor.renderer.$cursorLayer + .getPixelPosition(pos).left; + arrow.style.left = left + editor.renderer.gutterWidth - 5 + "px"; + + w.el.className = "error_widget_wrapper"; + el.className = "error_widget " + gutterAnno.className; + el.innerHTML = gutterAnno.text.join("
"); + + el.appendChild(dom.createElement("div")); + + var kb = function(_, hashId, keyString) { + if (hashId === 0 && (keyString === "esc" || keyString === "return")) { + w.destroy(); + return {command: "null"}; + } + }; + + w.destroy = function() { + if (editor.$mouseHandler.isMousePressed) + return; + editor.keyBinding.removeKeyboardHandler(kb); + session.widgetManager.removeLineWidget(w); + editor.off("changeSelection", w.destroy); + editor.off("changeSession", w.destroy); + editor.off("mouseup", w.destroy); + editor.off("change", w.destroy); + }; + + editor.keyBinding.addKeyboardHandler(kb); + editor.on("changeSelection", w.destroy); + editor.on("changeSession", w.destroy); + editor.on("mouseup", w.destroy); + editor.on("change", w.destroy); + + editor.session.widgetManager.addLineWidget(w); + + w.el.onmousedown = editor.focus.bind(editor); + + editor.renderer.scrollCursorIntoView(null, 0.5, {bottom: w.el.offsetHeight}); +}; + + +dom.importCssString("\ + .error_widget_wrapper {\ + background: inherit;\ + color: inherit;\ + border:none\ + }\ + .error_widget {\ + border-top: solid 2px;\ + border-bottom: solid 2px;\ + margin: 5px 0;\ + padding: 10px 40px;\ + white-space: pre-wrap;\ + }\ + .error_widget.ace_error, .error_widget_arrow.ace_error{\ + border-color: #ff5a5a\ + }\ + .error_widget.ace_warning, .error_widget_arrow.ace_warning{\ + border-color: #F1D817\ + }\ + .error_widget.ace_info, .error_widget_arrow.ace_info{\ + border-color: #5a5a5a\ + }\ + .error_widget.ace_ok, .error_widget_arrow.ace_ok{\ + border-color: #5aaa5a\ + }\ + .error_widget_arrow {\ + position: absolute;\ + border: solid 5px;\ + border-top-color: transparent!important;\ + border-right-color: transparent!important;\ + border-left-color: transparent!important;\ + top: -5px;\ + }\ +", ""); + +}); + +define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"], function(require, exports, module) { +"use strict"; + +require("./lib/fixoldbrowsers"); + +var dom = require("./lib/dom"); +var event = require("./lib/event"); + +var Editor = require("./editor").Editor; +var EditSession = require("./edit_session").EditSession; +var UndoManager = require("./undomanager").UndoManager; +var Renderer = require("./virtual_renderer").VirtualRenderer; +require("./worker/worker_client"); +require("./keyboard/hash_handler"); +require("./placeholder"); +require("./multi_select"); +require("./mode/folding/fold_mode"); +require("./theme/textmate"); +require("./ext/error_marker"); + +exports.config = require("./config"); +exports.require = require; +exports.edit = function(el) { + if (typeof(el) == "string") { + var _id = el; + el = document.getElementById(_id); + if (!el) + throw new Error("ace.edit can't find div #" + _id); + } + + if (el && el.env && el.env.editor instanceof Editor) + return el.env.editor; + + var value = ""; + if (el && /input|textarea/i.test(el.tagName)) { + var oldNode = el; + value = oldNode.value; + el = dom.createElement("pre"); + oldNode.parentNode.replaceChild(el, oldNode); + } else { + value = dom.getInnerText(el); + el.innerHTML = ''; + } + + var doc = exports.createEditSession(value); + + var editor = new Editor(new Renderer(el)); + editor.setSession(doc); + + var env = { + document: doc, + editor: editor, + onResize: editor.resize.bind(editor, null) + }; + if (oldNode) env.textarea = oldNode; + event.addListener(window, "resize", env.onResize); + editor.on("destroy", function() { + event.removeListener(window, "resize", env.onResize); + env.editor.container.env = null; // prevent memory leak on old ie + }); + editor.container.env = editor.env = env; + return editor; +}; +exports.createEditSession = function(text, mode) { + var doc = new EditSession(text, mode); + doc.setUndoManager(new UndoManager()); + return doc; +} +exports.EditSession = EditSession; +exports.UndoManager = UndoManager; +}); + (function() { + window.require(["ace/ace"], function(a) { + a && a.config.init(true); + if (!window.ace) + window.ace = a; + for (var key in a) if (a.hasOwnProperty(key)) + window.ace[key] = a[key]; + }); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-beautify.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-beautify.js new file mode 100644 index 00000000..8e0b25d5 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-beautify.js @@ -0,0 +1,334 @@ +define("ace/ext/beautify/php_rules",["require","exports","module","ace/token_iterator"], function(require, exports, module) { +"use strict"; +var TokenIterator = require("ace/token_iterator").TokenIterator; +exports.newLines = [{ + type: 'support.php_tag', + value: '' +}, { + type: 'paren.lparen', + value: '{', + indent: true +}, { + type: 'paren.rparen', + breakBefore: true, + value: '}', + indent: false +}, { + type: 'paren.rparen', + breakBefore: true, + value: '})', + indent: false, + dontBreak: true +}, { + type: 'comment' +}, { + type: 'text', + value: ';' +}, { + type: 'text', + value: ':', + context: 'php' +}, { + type: 'keyword', + value: 'case', + indent: true, + dontBreak: true +}, { + type: 'keyword', + value: 'default', + indent: true, + dontBreak: true +}, { + type: 'keyword', + value: 'break', + indent: false, + dontBreak: true +}, { + type: 'punctuation.doctype.end', + value: '>' +}, { + type: 'meta.tag.punctuation.end', + value: '>' +}, { + type: 'meta.tag.punctuation.begin', + value: '<', + blockTag: true, + indent: true, + dontBreak: true +}, { + type: 'meta.tag.punctuation.begin', + value: '' ){ + context = 'php'; + } + else if( token.type == 'support.php_tag' && token.value == '?>' ){ + context = 'html'; + } + else if( token.type == 'meta.tag.name.style' && context != 'css' ){ + context = 'css'; + } + else if( token.type == 'meta.tag.name.style' && context == 'css' ){ + context = 'html'; + } + else if( token.type == 'meta.tag.name.script' && context != 'js' ){ + context = 'js'; + } + else if( token.type == 'meta.tag.name.script' && context == 'js' ){ + context = 'html'; + } + + nextToken = iterator.stepForward(); + if (nextToken && nextToken.type.indexOf('meta.tag.name') == 0) { + nextTag = nextToken.value; + } + if ( lastToken.type == 'support.php_tag' && lastToken.value == '' ) { + dontBreak = false; + } + lastTag = tag; + + lastToken = token; + + token = nextToken; + + if (token===null) { + break; + } + } + + return code; +}; + + + +}); + +define("ace/ext/beautify",["require","exports","module","ace/token_iterator","ace/ext/beautify/php_rules"], function(require, exports, module) { +"use strict"; +var TokenIterator = require("ace/token_iterator").TokenIterator; + +var phpTransform = require("./beautify/php_rules").transform; + +exports.beautify = function(session) { + var iterator = new TokenIterator(session, 0, 0); + var token = iterator.getCurrentToken(); + + var context = session.$modeId.split("/").pop(); + + var code = phpTransform(iterator, context); + session.doc.setValue(code); +}; + +exports.commands = [{ + name: "beautify", + exec: function(editor) { + exports.beautify(editor.session); + }, + bindKey: "Ctrl-Shift-B" +}] + +}); + (function() { + window.require(["ace/ext/beautify"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-chromevox.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-chromevox.js new file mode 100644 index 00000000..74e04943 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-chromevox.js @@ -0,0 +1,541 @@ +define("ace/ext/chromevox",["require","exports","module","ace/editor","ace/config"], function(require, exports, module) { +var cvoxAce = {}; +cvoxAce.SpeechProperty; +cvoxAce.Cursor; +cvoxAce.Token; +cvoxAce.Annotation; +var CONSTANT_PROP = { + 'rate': 0.8, + 'pitch': 0.4, + 'volume': 0.9 +}; +var DEFAULT_PROP = { + 'rate': 1, + 'pitch': 0.5, + 'volume': 0.9 +}; +var ENTITY_PROP = { + 'rate': 0.8, + 'pitch': 0.8, + 'volume': 0.9 +}; +var KEYWORD_PROP = { + 'rate': 0.8, + 'pitch': 0.3, + 'volume': 0.9 +}; +var STORAGE_PROP = { + 'rate': 0.8, + 'pitch': 0.7, + 'volume': 0.9 +}; +var VARIABLE_PROP = { + 'rate': 0.8, + 'pitch': 0.8, + 'volume': 0.9 +}; +var DELETED_PROP = { + 'punctuationEcho': 'none', + 'relativePitch': -0.6 +}; +var ERROR_EARCON = 'ALERT_NONMODAL'; +var MODE_SWITCH_EARCON = 'ALERT_MODAL'; +var NO_MATCH_EARCON = 'INVALID_KEYPRESS'; +var INSERT_MODE_STATE = 'insertMode'; +var COMMAND_MODE_STATE = 'start'; + +var REPLACE_LIST = [ + { + substr: ';', + newSubstr: ' semicolon ' + }, + { + substr: ':', + newSubstr: ' colon ' + } +]; +var Command = { + SPEAK_ANNOT: 'annots', + SPEAK_ALL_ANNOTS: 'all_annots', + TOGGLE_LOCATION: 'toggle_location', + SPEAK_MODE: 'mode', + SPEAK_ROW_COL: 'row_col', + TOGGLE_DISPLACEMENT: 'toggle_displacement', + FOCUS_TEXT: 'focus_text' +}; +var KEY_PREFIX = 'CONTROL + SHIFT '; +cvoxAce.editor = null; +var lastCursor = null; +var annotTable = {}; +var shouldSpeakRowLocation = false; +var shouldSpeakDisplacement = false; +var changed = false; +var vimState = null; +var keyCodeToShortcutMap = {}; +var cmdToShortcutMap = {}; +var getKeyShortcutString = function(keyCode) { + return KEY_PREFIX + String.fromCharCode(keyCode); +}; +var isVimMode = function() { + var keyboardHandler = cvoxAce.editor.keyBinding.getKeyboardHandler(); + return keyboardHandler.$id === 'ace/keyboard/vim'; +}; +var getCurrentToken = function(cursor) { + return cvoxAce.editor.getSession().getTokenAt(cursor.row, cursor.column + 1); +}; +var getCurrentLine = function(cursor) { + return cvoxAce.editor.getSession().getLine(cursor.row); +}; +var onRowChange = function(currCursor) { + if (annotTable[currCursor.row]) { + cvox.Api.playEarcon(ERROR_EARCON); + } + if (shouldSpeakRowLocation) { + cvox.Api.stop(); + speakChar(currCursor); + speakTokenQueue(getCurrentToken(currCursor)); + speakLine(currCursor.row, 1); + } else { + speakLine(currCursor.row, 0); + } +}; +var isWord = function(cursor) { + var line = getCurrentLine(cursor); + var lineSuffix = line.substr(cursor.column - 1); + if (cursor.column === 0) { + lineSuffix = ' ' + line; + } + var firstWordRegExp = /^\W(\w+)/; + var words = firstWordRegExp.exec(lineSuffix); + return words !== null; +}; +var rules = { + 'constant': { + prop: CONSTANT_PROP + }, + 'entity': { + prop: ENTITY_PROP + }, + 'keyword': { + prop: KEYWORD_PROP + }, + 'storage': { + prop: STORAGE_PROP + }, + 'variable': { + prop: VARIABLE_PROP + }, + 'meta': { + prop: DEFAULT_PROP, + replace: [ + { + substr: '', + newSubstr: ' close tag ' + }, + { + substr: '<', + newSubstr: ' tag start ' + }, + { + substr: '>', + newSubstr: ' tag end ' + } + ] + } +}; +var DEFAULT_RULE = { + prop: DEFAULT_RULE +}; +var expand = function(value, replaceRules) { + var newValue = value; + for (var i = 0; i < replaceRules.length; i++) { + var replaceRule = replaceRules[i]; + var regexp = new RegExp(replaceRule.substr, 'g'); + newValue = newValue.replace(regexp, replaceRule.newSubstr); + } + return newValue; +}; +var mergeTokens = function(tokens, start, end) { + var newToken = {}; + newToken.value = ''; + newToken.type = tokens[start].type; + for (var j = start; j < end; j++) { + newToken.value += tokens[j].value; + } + return newToken; +}; +var mergeLikeTokens = function(tokens) { + if (tokens.length <= 1) { + return tokens; + } + var newTokens = []; + var lastLikeIndex = 0; + for (var i = 1; i < tokens.length; i++) { + var lastLikeToken = tokens[lastLikeIndex]; + var currToken = tokens[i]; + if (getTokenRule(lastLikeToken) !== getTokenRule(currToken)) { + newTokens.push(mergeTokens(tokens, lastLikeIndex, i)); + lastLikeIndex = i; + } + } + newTokens.push(mergeTokens(tokens, lastLikeIndex, tokens.length)); + return newTokens; +}; +var isRowWhiteSpace = function(row) { + var line = cvoxAce.editor.getSession().getLine(row); + var whiteSpaceRegexp = /^\s*$/; + return whiteSpaceRegexp.exec(line) !== null; +}; +var speakLine = function(row, queue) { + var tokens = cvoxAce.editor.getSession().getTokens(row); + if (tokens.length === 0 || isRowWhiteSpace(row)) { + cvox.Api.playEarcon('EDITABLE_TEXT'); + return; + } + tokens = mergeLikeTokens(tokens); + var firstToken = tokens[0]; + tokens = tokens.filter(function(token) { + return token !== firstToken; + }); + speakToken_(firstToken, queue); + tokens.forEach(speakTokenQueue); +}; +var speakTokenFlush = function(token) { + speakToken_(token, 0); +}; +var speakTokenQueue = function(token) { + speakToken_(token, 1); +}; +var getTokenRule = function(token) { + if (!token || !token.type) { + return; + } + var split = token.type.split('.'); + if (split.length === 0) { + return; + } + var type = split[0]; + var rule = rules[type]; + if (!rule) { + return DEFAULT_RULE; + } + return rule; +}; +var speakToken_ = function(token, queue) { + var rule = getTokenRule(token); + var value = expand(token.value, REPLACE_LIST); + if (rule.replace) { + value = expand(value, rule.replace); + } + cvox.Api.speak(value, queue, rule.prop); +}; +var speakChar = function(cursor) { + var line = getCurrentLine(cursor); + cvox.Api.speak(line[cursor.column], 1); +}; +var speakDisplacement = function(lastCursor, currCursor) { + var line = getCurrentLine(currCursor); + var displace = line.substring(lastCursor.column, currCursor.column); + displace = displace.replace(/ /g, ' space '); + cvox.Api.speak(displace); +}; +var speakCharOrWordOrLine = function(lastCursor, currCursor) { + if (Math.abs(lastCursor.column - currCursor.column) !== 1) { + var currLineLength = getCurrentLine(currCursor).length; + if (currCursor.column === 0 || currCursor.column === currLineLength) { + speakLine(currCursor.row, 0); + return; + } + if (isWord(currCursor)) { + cvox.Api.stop(); + speakTokenQueue(getCurrentToken(currCursor)); + return; + } + } + speakChar(currCursor); +}; +var onColumnChange = function(lastCursor, currCursor) { + if (!cvoxAce.editor.selection.isEmpty()) { + speakDisplacement(lastCursor, currCursor); + cvox.Api.speak('selected', 1); + } + else if (shouldSpeakDisplacement) { + speakDisplacement(lastCursor, currCursor); + } else { + speakCharOrWordOrLine(lastCursor, currCursor); + } +}; +var onCursorChange = function(evt) { + if (changed) { + changed = false; + return; + } + var currCursor = cvoxAce.editor.selection.getCursor(); + if (currCursor.row !== lastCursor.row) { + onRowChange(currCursor); + } else { + onColumnChange(lastCursor, currCursor); + } + lastCursor = currCursor; +}; +var onSelectionChange = function(evt) { + if (cvoxAce.editor.selection.isEmpty()) { + cvox.Api.speak('unselected'); + } +}; +var onChange = function(evt) { + var data = evt.data; + switch (data.action) { + case 'removeText': + cvox.Api.speak(data.text, 0, DELETED_PROP); + changed = true; + break; + case 'insertText': + cvox.Api.speak(data.text, 0); + changed = true; + break; + } +}; +var isNewAnnotation = function(annot) { + var row = annot.row; + var col = annot.column; + return !annotTable[row] || !annotTable[row][col]; +}; +var populateAnnotations = function(annotations) { + annotTable = {}; + for (var i = 0; i < annotations.length; i++) { + var annotation = annotations[i]; + var row = annotation.row; + var col = annotation.column; + if (!annotTable[row]) { + annotTable[row] = {}; + } + annotTable[row][col] = annotation; + } +}; +var onAnnotationChange = function(evt) { + var annotations = cvoxAce.editor.getSession().getAnnotations(); + var newAnnotations = annotations.filter(isNewAnnotation); + if (newAnnotations.length > 0) { + cvox.Api.playEarcon(ERROR_EARCON); + } + populateAnnotations(annotations); +}; +var speakAnnot = function(annot) { + var annotText = annot.type + ' ' + annot.text + ' on ' + + rowColToString(annot.row, annot.column); + annotText = annotText.replace(';', 'semicolon'); + cvox.Api.speak(annotText, 1); +}; +var speakAnnotsByRow = function(row) { + var annots = annotTable[row]; + for (var col in annots) { + speakAnnot(annots[col]); + } +}; +var rowColToString = function(row, col) { + return 'row ' + (row + 1) + ' column ' + (col + 1); +}; +var speakCurrRowAndCol = function() { + cvox.Api.speak(rowColToString(lastCursor.row, lastCursor.column)); +}; +var speakAllAnnots = function() { + for (var row in annotTable) { + speakAnnotsByRow(row); + } +}; +var speakMode = function() { + if (!isVimMode()) { + return; + } + switch (cvoxAce.editor.keyBinding.$data.state) { + case INSERT_MODE_STATE: + cvox.Api.speak('Insert mode'); + break; + case COMMAND_MODE_STATE: + cvox.Api.speak('Command mode'); + break; + } +}; +var toggleSpeakRowLocation = function() { + shouldSpeakRowLocation = !shouldSpeakRowLocation; + if (shouldSpeakRowLocation) { + cvox.Api.speak('Speak location on row change enabled.'); + } else { + cvox.Api.speak('Speak location on row change disabled.'); + } +}; +var toggleSpeakDisplacement = function() { + shouldSpeakDisplacement = !shouldSpeakDisplacement; + if (shouldSpeakDisplacement) { + cvox.Api.speak('Speak displacement on column changes.'); + } else { + cvox.Api.speak('Speak current character or word on column changes.'); + } +}; +var onKeyDown = function(evt) { + if (evt.ctrlKey && evt.shiftKey) { + var shortcut = keyCodeToShortcutMap[evt.keyCode]; + if (shortcut) { + shortcut.func(); + } + } +}; +var onChangeStatus = function(evt, editor) { + if (!isVimMode()) { + return; + } + var state = editor.keyBinding.$data.state; + if (state === vimState) { + return; + } + switch (state) { + case INSERT_MODE_STATE: + cvox.Api.playEarcon(MODE_SWITCH_EARCON); + cvox.Api.setKeyEcho(true); + break; + case COMMAND_MODE_STATE: + cvox.Api.playEarcon(MODE_SWITCH_EARCON); + cvox.Api.setKeyEcho(false); + break; + } + vimState = state; +}; +var contextMenuHandler = function(evt) { + var cmd = evt.detail['customCommand']; + var shortcut = cmdToShortcutMap[cmd]; + if (shortcut) { + shortcut.func(); + cvoxAce.editor.focus(); + } +}; +var initContextMenu = function() { + var ACTIONS = SHORTCUTS.map(function(shortcut) { + return { + desc: shortcut.desc + getKeyShortcutString(shortcut.keyCode), + cmd: shortcut.cmd + }; + }); + var body = document.querySelector('body'); + body.setAttribute('contextMenuActions', JSON.stringify(ACTIONS)); + body.addEventListener('ATCustomEvent', contextMenuHandler, true); +}; +var onFindSearchbox = function(evt) { + if (evt.match) { + speakLine(lastCursor.row, 0); + } else { + cvox.Api.playEarcon(NO_MATCH_EARCON); + } +}; +var focus = function() { + cvoxAce.editor.focus(); +}; +var SHORTCUTS = [ + { + keyCode: 49, + func: function() { + speakAnnotsByRow(lastCursor.row); + }, + cmd: Command.SPEAK_ANNOT, + desc: 'Speak annotations on line' + }, + { + keyCode: 50, + func: speakAllAnnots, + cmd: Command.SPEAK_ALL_ANNOTS, + desc: 'Speak all annotations' + }, + { + keyCode: 51, + func: speakMode, + cmd: Command.SPEAK_MODE, + desc: 'Speak Vim mode' + }, + { + keyCode: 52, + func: toggleSpeakRowLocation, + cmd: Command.TOGGLE_LOCATION, + desc: 'Toggle speak row location' + }, + { + keyCode: 53, + func: speakCurrRowAndCol, + cmd: Command.SPEAK_ROW_COL, + desc: 'Speak row and column' + }, + { + keyCode: 54, + func: toggleSpeakDisplacement, + cmd: Command.TOGGLE_DISPLACEMENT, + desc: 'Toggle speak displacement' + }, + { + keyCode: 55, + func: focus, + cmd: Command.FOCUS_TEXT, + desc: 'Focus text' + } +]; +var onFocus = function() { + cvoxAce.editor = editor; + editor.getSession().selection.on('changeCursor', onCursorChange); + editor.getSession().selection.on('changeSelection', onSelectionChange); + editor.getSession().on('change', onChange); + editor.getSession().on('changeAnnotation', onAnnotationChange); + editor.on('changeStatus', onChangeStatus); + editor.on('findSearchBox', onFindSearchbox); + editor.container.addEventListener('keydown', onKeyDown); + + lastCursor = editor.selection.getCursor(); +}; +var init = function(editor) { + onFocus(); + SHORTCUTS.forEach(function(shortcut) { + keyCodeToShortcutMap[shortcut.keyCode] = shortcut; + cmdToShortcutMap[shortcut.cmd] = shortcut; + }); + + editor.on('focus', onFocus); + if (isVimMode()) { + cvox.Api.setKeyEcho(false); + } + initContextMenu(); +}; +function cvoxApiExists() { + return (typeof(cvox) !== 'undefined') && cvox && cvox.Api; +} +var tries = 0; +var MAX_TRIES = 15; +function watchForCvoxLoad(editor) { + if (cvoxApiExists()) { + init(editor); + } else { + tries++; + if (tries >= MAX_TRIES) { + return; + } + window.setTimeout(watchForCvoxLoad, 500, editor); + } +} + +var Editor = require('../editor').Editor; +require('../config').defineOptions(Editor.prototype, 'editor', { + enableChromevoxEnhancements: { + set: function(val) { + if (val) { + watchForCvoxLoad(this); + } + }, + value: true // turn it on by default or check for window.cvox + } +}); + +}); + (function() { + window.require(["ace/ext/chromevox"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-elastic_tabstops_lite.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-elastic_tabstops_lite.js new file mode 100644 index 00000000..a4faeac8 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-elastic_tabstops_lite.js @@ -0,0 +1,275 @@ +define("ace/ext/elastic_tabstops_lite",["require","exports","module","ace/editor","ace/config"], function(require, exports, module) { +"use strict"; + +var ElasticTabstopsLite = function(editor) { + this.$editor = editor; + var self = this; + var changedRows = []; + var recordChanges = false; + this.onAfterExec = function() { + recordChanges = false; + self.processRows(changedRows); + changedRows = []; + }; + this.onExec = function() { + recordChanges = true; + }; + this.onChange = function(e) { + var range = e.data.range + if (recordChanges) { + if (changedRows.indexOf(range.start.row) == -1) + changedRows.push(range.start.row); + if (range.end.row != range.start.row) + changedRows.push(range.end.row); + } + }; +}; + +(function() { + this.processRows = function(rows) { + this.$inChange = true; + var checkedRows = []; + + for (var r = 0, rowCount = rows.length; r < rowCount; r++) { + var row = rows[r]; + + if (checkedRows.indexOf(row) > -1) + continue; + + var cellWidthObj = this.$findCellWidthsForBlock(row); + var cellWidths = this.$setBlockCellWidthsToMax(cellWidthObj.cellWidths); + var rowIndex = cellWidthObj.firstRow; + + for (var w = 0, l = cellWidths.length; w < l; w++) { + var widths = cellWidths[w]; + checkedRows.push(rowIndex); + this.$adjustRow(rowIndex, widths); + rowIndex++; + } + } + this.$inChange = false; + }; + + this.$findCellWidthsForBlock = function(row) { + var cellWidths = [], widths; + var rowIter = row; + while (rowIter >= 0) { + widths = this.$cellWidthsForRow(rowIter); + if (widths.length == 0) + break; + + cellWidths.unshift(widths); + rowIter--; + } + var firstRow = rowIter + 1; + rowIter = row; + var numRows = this.$editor.session.getLength(); + + while (rowIter < numRows - 1) { + rowIter++; + + widths = this.$cellWidthsForRow(rowIter); + if (widths.length == 0) + break; + + cellWidths.push(widths); + } + + return { cellWidths: cellWidths, firstRow: firstRow }; + }; + + this.$cellWidthsForRow = function(row) { + var selectionColumns = this.$selectionColumnsForRow(row); + + var tabs = [-1].concat(this.$tabsForRow(row)); + var widths = tabs.map(function(el) { return 0; } ).slice(1); + var line = this.$editor.session.getLine(row); + + for (var i = 0, len = tabs.length - 1; i < len; i++) { + var leftEdge = tabs[i]+1; + var rightEdge = tabs[i+1]; + + var rightmostSelection = this.$rightmostSelectionInCell(selectionColumns, rightEdge); + var cell = line.substring(leftEdge, rightEdge); + widths[i] = Math.max(cell.replace(/\s+$/g,'').length, rightmostSelection - leftEdge); + } + + return widths; + }; + + this.$selectionColumnsForRow = function(row) { + var selections = [], cursor = this.$editor.getCursorPosition(); + if (this.$editor.session.getSelection().isEmpty()) { + if (row == cursor.row) + selections.push(cursor.column); + } + + return selections; + }; + + this.$setBlockCellWidthsToMax = function(cellWidths) { + var startingNewBlock = true, blockStartRow, blockEndRow, maxWidth; + var columnInfo = this.$izip_longest(cellWidths); + + for (var c = 0, l = columnInfo.length; c < l; c++) { + var column = columnInfo[c]; + if (!column.push) { + console.error(column); + continue; + } + column.push(NaN); + + for (var r = 0, s = column.length; r < s; r++) { + var width = column[r]; + if (startingNewBlock) { + blockStartRow = r; + maxWidth = 0; + startingNewBlock = false; + } + if (isNaN(width)) { + blockEndRow = r; + + for (var j = blockStartRow; j < blockEndRow; j++) { + cellWidths[j][c] = maxWidth; + } + startingNewBlock = true; + } + + maxWidth = Math.max(maxWidth, width); + } + } + + return cellWidths; + }; + + this.$rightmostSelectionInCell = function(selectionColumns, cellRightEdge) { + var rightmost = 0; + + if (selectionColumns.length) { + var lengths = []; + for (var s = 0, length = selectionColumns.length; s < length; s++) { + if (selectionColumns[s] <= cellRightEdge) + lengths.push(s); + else + lengths.push(0); + } + rightmost = Math.max.apply(Math, lengths); + } + + return rightmost; + }; + + this.$tabsForRow = function(row) { + var rowTabs = [], line = this.$editor.session.getLine(row), + re = /\t/g, match; + + while ((match = re.exec(line)) != null) { + rowTabs.push(match.index); + } + + return rowTabs; + }; + + this.$adjustRow = function(row, widths) { + var rowTabs = this.$tabsForRow(row); + + if (rowTabs.length == 0) + return; + + var bias = 0, location = -1; + var expandedSet = this.$izip(widths, rowTabs); + + for (var i = 0, l = expandedSet.length; i < l; i++) { + var w = expandedSet[i][0], it = expandedSet[i][1]; + location += 1 + w; + it += bias; + var difference = location - it; + + if (difference == 0) + continue; + + var partialLine = this.$editor.session.getLine(row).substr(0, it ); + var strippedPartialLine = partialLine.replace(/\s*$/g, ""); + var ispaces = partialLine.length - strippedPartialLine.length; + + if (difference > 0) { + this.$editor.session.getDocument().insertInLine({row: row, column: it + 1}, Array(difference + 1).join(" ") + "\t"); + this.$editor.session.getDocument().removeInLine(row, it, it + 1); + + bias += difference; + } + + if (difference < 0 && ispaces >= -difference) { + this.$editor.session.getDocument().removeInLine(row, it + difference, it); + bias += difference; + } + } + }; + this.$izip_longest = function(iterables) { + if (!iterables[0]) + return []; + var longest = iterables[0].length; + var iterablesLength = iterables.length; + + for (var i = 1; i < iterablesLength; i++) { + var iLength = iterables[i].length; + if (iLength > longest) + longest = iLength; + } + + var expandedSet = []; + + for (var l = 0; l < longest; l++) { + var set = []; + for (var i = 0; i < iterablesLength; i++) { + if (iterables[i][l] === "") + set.push(NaN); + else + set.push(iterables[i][l]); + } + + expandedSet.push(set); + } + + + return expandedSet; + }; + this.$izip = function(widths, tabs) { + var size = widths.length >= tabs.length ? tabs.length : widths.length; + + var expandedSet = []; + for (var i = 0; i < size; i++) { + var set = [ widths[i], tabs[i] ]; + expandedSet.push(set); + } + return expandedSet; + }; + +}).call(ElasticTabstopsLite.prototype); + +exports.ElasticTabstopsLite = ElasticTabstopsLite; + +var Editor = require("../editor").Editor; +require("../config").defineOptions(Editor.prototype, "editor", { + useElasticTabstops: { + set: function(val) { + if (val) { + if (!this.elasticTabstops) + this.elasticTabstops = new ElasticTabstopsLite(this); + this.commands.on("afterExec", this.elasticTabstops.onAfterExec); + this.commands.on("exec", this.elasticTabstops.onExec); + this.on("change", this.elasticTabstops.onChange); + } else if (this.elasticTabstops) { + this.commands.removeListener("afterExec", this.elasticTabstops.onAfterExec); + this.commands.removeListener("exec", this.elasticTabstops.onExec); + this.removeListener("change", this.elasticTabstops.onChange); + } + } + } +}); + +}); + (function() { + window.require(["ace/ext/elastic_tabstops_lite"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-emmet.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-emmet.js new file mode 100644 index 00000000..390c2668 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-emmet.js @@ -0,0 +1,1190 @@ +define("ace/snippets",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/lib/lang","ace/range","ace/anchor","ace/keyboard/hash_handler","ace/tokenizer","ace/lib/dom","ace/editor"], function(require, exports, module) { +"use strict"; +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var lang = require("./lib/lang"); +var Range = require("./range").Range; +var Anchor = require("./anchor").Anchor; +var HashHandler = require("./keyboard/hash_handler").HashHandler; +var Tokenizer = require("./tokenizer").Tokenizer; +var comparePoints = Range.comparePoints; + +var SnippetManager = function() { + this.snippetMap = {}; + this.snippetNameMap = {}; +}; + +(function() { + oop.implement(this, EventEmitter); + + this.getTokenizer = function() { + function TabstopToken(str, _, stack) { + str = str.substr(1); + if (/^\d+$/.test(str) && !stack.inFormatString) + return [{tabstopId: parseInt(str, 10)}]; + return [{text: str}]; + } + function escape(ch) { + return "(?:[^\\\\" + ch + "]|\\\\.)"; + } + SnippetManager.$tokenizer = new Tokenizer({ + start: [ + {regex: /:/, onMatch: function(val, state, stack) { + if (stack.length && stack[0].expectIf) { + stack[0].expectIf = false; + stack[0].elseBranch = stack[0]; + return [stack[0]]; + } + return ":"; + }}, + {regex: /\\./, onMatch: function(val, state, stack) { + var ch = val[1]; + if (ch == "}" && stack.length) { + val = ch; + }else if ("`$\\".indexOf(ch) != -1) { + val = ch; + } else if (stack.inFormatString) { + if (ch == "n") + val = "\n"; + else if (ch == "t") + val = "\n"; + else if ("ulULE".indexOf(ch) != -1) { + val = {changeCase: ch, local: ch > "a"}; + } + } + + return [val]; + }}, + {regex: /}/, onMatch: function(val, state, stack) { + return [stack.length ? stack.shift() : val]; + }}, + {regex: /\$(?:\d+|\w+)/, onMatch: TabstopToken}, + {regex: /\$\{[\dA-Z_a-z]+/, onMatch: function(str, state, stack) { + var t = TabstopToken(str.substr(1), state, stack); + stack.unshift(t[0]); + return t; + }, next: "snippetVar"}, + {regex: /\n/, token: "newline", merge: false} + ], + snippetVar: [ + {regex: "\\|" + escape("\\|") + "*\\|", onMatch: function(val, state, stack) { + stack[0].choices = val.slice(1, -1).split(","); + }, next: "start"}, + {regex: "/(" + escape("/") + "+)/(?:(" + escape("/") + "*)/)(\\w*):?", + onMatch: function(val, state, stack) { + var ts = stack[0]; + ts.fmtString = val; + + val = this.splitRegex.exec(val); + ts.guard = val[1]; + ts.fmt = val[2]; + ts.flag = val[3]; + return ""; + }, next: "start"}, + {regex: "`" + escape("`") + "*`", onMatch: function(val, state, stack) { + stack[0].code = val.splice(1, -1); + return ""; + }, next: "start"}, + {regex: "\\?", onMatch: function(val, state, stack) { + if (stack[0]) + stack[0].expectIf = true; + }, next: "start"}, + {regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "start"} + ], + formatString: [ + {regex: "/(" + escape("/") + "+)/", token: "regex"}, + {regex: "", onMatch: function(val, state, stack) { + stack.inFormatString = true; + }, next: "start"} + ] + }); + SnippetManager.prototype.getTokenizer = function() { + return SnippetManager.$tokenizer; + }; + return SnippetManager.$tokenizer; + }; + + this.tokenizeTmSnippet = function(str, startState) { + return this.getTokenizer().getLineTokens(str, startState).tokens.map(function(x) { + return x.value || x; + }); + }; + + this.$getDefaultValue = function(editor, name) { + if (/^[A-Z]\d+$/.test(name)) { + var i = name.substr(1); + return (this.variables[name[0] + "__"] || {})[i]; + } + if (/^\d+$/.test(name)) { + return (this.variables.__ || {})[name]; + } + name = name.replace(/^TM_/, ""); + + if (!editor) + return; + var s = editor.session; + switch(name) { + case "CURRENT_WORD": + var r = s.getWordRange(); + case "SELECTION": + case "SELECTED_TEXT": + return s.getTextRange(r); + case "CURRENT_LINE": + return s.getLine(editor.getCursorPosition().row); + case "PREV_LINE": // not possible in textmate + return s.getLine(editor.getCursorPosition().row - 1); + case "LINE_INDEX": + return editor.getCursorPosition().column; + case "LINE_NUMBER": + return editor.getCursorPosition().row + 1; + case "SOFT_TABS": + return s.getUseSoftTabs() ? "YES" : "NO"; + case "TAB_SIZE": + return s.getTabSize(); + case "FILENAME": + case "FILEPATH": + return ""; + case "FULLNAME": + return "Ace"; + } + }; + this.variables = {}; + this.getVariableValue = function(editor, varName) { + if (this.variables.hasOwnProperty(varName)) + return this.variables[varName](editor, varName) || ""; + return this.$getDefaultValue(editor, varName) || ""; + }; + this.tmStrFormat = function(str, ch, editor) { + var flag = ch.flag || ""; + var re = ch.guard; + re = new RegExp(re, flag.replace(/[^gi]/, "")); + var fmtTokens = this.tokenizeTmSnippet(ch.fmt, "formatString"); + var _self = this; + var formatted = str.replace(re, function() { + _self.variables.__ = arguments; + var fmtParts = _self.resolveVariables(fmtTokens, editor); + var gChangeCase = "E"; + for (var i = 0; i < fmtParts.length; i++) { + var ch = fmtParts[i]; + if (typeof ch == "object") { + fmtParts[i] = ""; + if (ch.changeCase && ch.local) { + var next = fmtParts[i + 1]; + if (next && typeof next == "string") { + if (ch.changeCase == "u") + fmtParts[i] = next[0].toUpperCase(); + else + fmtParts[i] = next[0].toLowerCase(); + fmtParts[i + 1] = next.substr(1); + } + } else if (ch.changeCase) { + gChangeCase = ch.changeCase; + } + } else if (gChangeCase == "U") { + fmtParts[i] = ch.toUpperCase(); + } else if (gChangeCase == "L") { + fmtParts[i] = ch.toLowerCase(); + } + } + return fmtParts.join(""); + }); + this.variables.__ = null; + return formatted; + }; + + this.resolveVariables = function(snippet, editor) { + var result = []; + for (var i = 0; i < snippet.length; i++) { + var ch = snippet[i]; + if (typeof ch == "string") { + result.push(ch); + } else if (typeof ch != "object") { + continue; + } else if (ch.skip) { + gotoNext(ch); + } else if (ch.processed < i) { + continue; + } else if (ch.text) { + var value = this.getVariableValue(editor, ch.text); + if (value && ch.fmtString) + value = this.tmStrFormat(value, ch); + ch.processed = i; + if (ch.expectIf == null) { + if (value) { + result.push(value); + gotoNext(ch); + } + } else { + if (value) { + ch.skip = ch.elseBranch; + } else + gotoNext(ch); + } + } else if (ch.tabstopId != null) { + result.push(ch); + } else if (ch.changeCase != null) { + result.push(ch); + } + } + function gotoNext(ch) { + var i1 = snippet.indexOf(ch, i + 1); + if (i1 != -1) + i = i1; + } + return result; + }; + + this.insertSnippetForSelection = function(editor, snippetText) { + var cursor = editor.getCursorPosition(); + var line = editor.session.getLine(cursor.row); + var tabString = editor.session.getTabString(); + var indentString = line.match(/^\s*/)[0]; + + if (cursor.column < indentString.length) + indentString = indentString.slice(0, cursor.column); + + var tokens = this.tokenizeTmSnippet(snippetText); + tokens = this.resolveVariables(tokens, editor); + tokens = tokens.map(function(x) { + if (x == "\n") + return x + indentString; + if (typeof x == "string") + return x.replace(/\t/g, tabString); + return x; + }); + var tabstops = []; + tokens.forEach(function(p, i) { + if (typeof p != "object") + return; + var id = p.tabstopId; + var ts = tabstops[id]; + if (!ts) { + ts = tabstops[id] = []; + ts.index = id; + ts.value = ""; + } + if (ts.indexOf(p) !== -1) + return; + ts.push(p); + var i1 = tokens.indexOf(p, i + 1); + if (i1 === -1) + return; + + var value = tokens.slice(i + 1, i1); + var isNested = value.some(function(t) {return typeof t === "object"}); + if (isNested && !ts.value) { + ts.value = value; + } else if (value.length && (!ts.value || typeof ts.value !== "string")) { + ts.value = value.join(""); + } + }); + tabstops.forEach(function(ts) {ts.length = 0}); + var expanding = {}; + function copyValue(val) { + var copy = []; + for (var i = 0; i < val.length; i++) { + var p = val[i]; + if (typeof p == "object") { + if (expanding[p.tabstopId]) + continue; + var j = val.lastIndexOf(p, i - 1); + p = copy[j] || {tabstopId: p.tabstopId}; + } + copy[i] = p; + } + return copy; + } + for (var i = 0; i < tokens.length; i++) { + var p = tokens[i]; + if (typeof p != "object") + continue; + var id = p.tabstopId; + var i1 = tokens.indexOf(p, i + 1); + if (expanding[id]) { + if (expanding[id] === p) + expanding[id] = null; + continue; + } + + var ts = tabstops[id]; + var arg = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value); + arg.unshift(i + 1, Math.max(0, i1 - i)); + arg.push(p); + expanding[id] = p; + tokens.splice.apply(tokens, arg); + + if (ts.indexOf(p) === -1) + ts.push(p); + } + var row = 0, column = 0; + var text = ""; + tokens.forEach(function(t) { + if (typeof t === "string") { + if (t[0] === "\n"){ + column = t.length - 1; + row ++; + } else + column += t.length; + text += t; + } else { + if (!t.start) + t.start = {row: row, column: column}; + else + t.end = {row: row, column: column}; + } + }); + var range = editor.getSelectionRange(); + var end = editor.session.replace(range, text); + + var tabstopManager = new TabstopManager(editor); + var selectionId = editor.inVirtualSelectionMode && editor.selection.index; + tabstopManager.addTabstops(tabstops, range.start, end, selectionId); + }; + + this.insertSnippet = function(editor, snippetText) { + var self = this; + if (editor.inVirtualSelectionMode) + return self.insertSnippetForSelection(editor, snippetText); + + editor.forEachSelection(function() { + self.insertSnippetForSelection(editor, snippetText); + }, null, {keepOrder: true}); + + if (editor.tabstopManager) + editor.tabstopManager.tabNext(); + }; + + this.$getScope = function(editor) { + var scope = editor.session.$mode.$id || ""; + scope = scope.split("/").pop(); + if (scope === "html" || scope === "php") { + if (scope === "php" && !editor.session.$mode.inlinePhp) + scope = "html"; + var c = editor.getCursorPosition(); + var state = editor.session.getState(c.row); + if (typeof state === "object") { + state = state[0]; + } + if (state.substring) { + if (state.substring(0, 3) == "js-") + scope = "javascript"; + else if (state.substring(0, 4) == "css-") + scope = "css"; + else if (state.substring(0, 4) == "php-") + scope = "php"; + } + } + + return scope; + }; + + this.getActiveScopes = function(editor) { + var scope = this.$getScope(editor); + var scopes = [scope]; + var snippetMap = this.snippetMap; + if (snippetMap[scope] && snippetMap[scope].includeScopes) { + scopes.push.apply(scopes, snippetMap[scope].includeScopes); + } + scopes.push("_"); + return scopes; + }; + + this.expandWithTab = function(editor, options) { + var self = this; + var result = editor.forEachSelection(function() { + return self.expandSnippetForSelection(editor, options); + }, null, {keepOrder: true}); + if (result && editor.tabstopManager) + editor.tabstopManager.tabNext(); + return result; + }; + + this.expandSnippetForSelection = function(editor, options) { + var cursor = editor.getCursorPosition(); + var line = editor.session.getLine(cursor.row); + var before = line.substring(0, cursor.column); + var after = line.substr(cursor.column); + + var snippetMap = this.snippetMap; + var snippet; + this.getActiveScopes(editor).some(function(scope) { + var snippets = snippetMap[scope]; + if (snippets) + snippet = this.findMatchingSnippet(snippets, before, after); + return !!snippet; + }, this); + if (!snippet) + return false; + if (options && options.dryRun) + return true; + editor.session.doc.removeInLine(cursor.row, + cursor.column - snippet.replaceBefore.length, + cursor.column + snippet.replaceAfter.length + ); + + this.variables.M__ = snippet.matchBefore; + this.variables.T__ = snippet.matchAfter; + this.insertSnippetForSelection(editor, snippet.content); + + this.variables.M__ = this.variables.T__ = null; + return true; + }; + + this.findMatchingSnippet = function(snippetList, before, after) { + for (var i = snippetList.length; i--;) { + var s = snippetList[i]; + if (s.startRe && !s.startRe.test(before)) + continue; + if (s.endRe && !s.endRe.test(after)) + continue; + if (!s.startRe && !s.endRe) + continue; + + s.matchBefore = s.startRe ? s.startRe.exec(before) : [""]; + s.matchAfter = s.endRe ? s.endRe.exec(after) : [""]; + s.replaceBefore = s.triggerRe ? s.triggerRe.exec(before)[0] : ""; + s.replaceAfter = s.endTriggerRe ? s.endTriggerRe.exec(after)[0] : ""; + return s; + } + }; + + this.snippetMap = {}; + this.snippetNameMap = {}; + this.register = function(snippets, scope) { + var snippetMap = this.snippetMap; + var snippetNameMap = this.snippetNameMap; + var self = this; + + if (!snippets) + snippets = []; + + function wrapRegexp(src) { + if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src)) + src = "(?:" + src + ")"; + + return src || ""; + } + function guardedRegexp(re, guard, opening) { + re = wrapRegexp(re); + guard = wrapRegexp(guard); + if (opening) { + re = guard + re; + if (re && re[re.length - 1] != "$") + re = re + "$"; + } else { + re = re + guard; + if (re && re[0] != "^") + re = "^" + re; + } + return new RegExp(re); + } + + function addSnippet(s) { + if (!s.scope) + s.scope = scope || "_"; + scope = s.scope; + if (!snippetMap[scope]) { + snippetMap[scope] = []; + snippetNameMap[scope] = {}; + } + + var map = snippetNameMap[scope]; + if (s.name) { + var old = map[s.name]; + if (old) + self.unregister(old); + map[s.name] = s; + } + snippetMap[scope].push(s); + + if (s.tabTrigger && !s.trigger) { + if (!s.guard && /^\w/.test(s.tabTrigger)) + s.guard = "\\b"; + s.trigger = lang.escapeRegExp(s.tabTrigger); + } + + s.startRe = guardedRegexp(s.trigger, s.guard, true); + s.triggerRe = new RegExp(s.trigger, "", true); + + s.endRe = guardedRegexp(s.endTrigger, s.endGuard, true); + s.endTriggerRe = new RegExp(s.endTrigger, "", true); + } + + if (snippets && snippets.content) + addSnippet(snippets); + else if (Array.isArray(snippets)) + snippets.forEach(addSnippet); + + this._signal("registerSnippets", {scope: scope}); + }; + this.unregister = function(snippets, scope) { + var snippetMap = this.snippetMap; + var snippetNameMap = this.snippetNameMap; + + function removeSnippet(s) { + var nameMap = snippetNameMap[s.scope||scope]; + if (nameMap && nameMap[s.name]) { + delete nameMap[s.name]; + var map = snippetMap[s.scope||scope]; + var i = map && map.indexOf(s); + if (i >= 0) + map.splice(i, 1); + } + } + if (snippets.content) + removeSnippet(snippets); + else if (Array.isArray(snippets)) + snippets.forEach(removeSnippet); + }; + this.parseSnippetFile = function(str) { + str = str.replace(/\r/g, ""); + var list = [], snippet = {}; + var re = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm; + var m; + while (m = re.exec(str)) { + if (m[1]) { + try { + snippet = JSON.parse(m[1]); + list.push(snippet); + } catch (e) {} + } if (m[4]) { + snippet.content = m[4].replace(/^\t/gm, ""); + list.push(snippet); + snippet = {}; + } else { + var key = m[2], val = m[3]; + if (key == "regex") { + var guardRe = /\/((?:[^\/\\]|\\.)*)|$/g; + snippet.guard = guardRe.exec(val)[1]; + snippet.trigger = guardRe.exec(val)[1]; + snippet.endTrigger = guardRe.exec(val)[1]; + snippet.endGuard = guardRe.exec(val)[1]; + } else if (key == "snippet") { + snippet.tabTrigger = val.match(/^\S*/)[0]; + if (!snippet.name) + snippet.name = val; + } else { + snippet[key] = val; + } + } + } + return list; + }; + this.getSnippetByName = function(name, editor) { + var snippetMap = this.snippetNameMap; + var snippet; + this.getActiveScopes(editor).some(function(scope) { + var snippets = snippetMap[scope]; + if (snippets) + snippet = snippets[name]; + return !!snippet; + }, this); + return snippet; + }; + +}).call(SnippetManager.prototype); + + +var TabstopManager = function(editor) { + if (editor.tabstopManager) + return editor.tabstopManager; + editor.tabstopManager = this; + this.$onChange = this.onChange.bind(this); + this.$onChangeSelection = lang.delayedCall(this.onChangeSelection.bind(this)).schedule; + this.$onChangeSession = this.onChangeSession.bind(this); + this.$onAfterExec = this.onAfterExec.bind(this); + this.attach(editor); +}; +(function() { + this.attach = function(editor) { + this.index = 0; + this.ranges = []; + this.tabstops = []; + this.$openTabstops = null; + this.selectedTabstop = null; + + this.editor = editor; + this.editor.on("change", this.$onChange); + this.editor.on("changeSelection", this.$onChangeSelection); + this.editor.on("changeSession", this.$onChangeSession); + this.editor.commands.on("afterExec", this.$onAfterExec); + this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); + }; + this.detach = function() { + this.tabstops.forEach(this.removeTabstopMarkers, this); + this.ranges = null; + this.tabstops = null; + this.selectedTabstop = null; + this.editor.removeListener("change", this.$onChange); + this.editor.removeListener("changeSelection", this.$onChangeSelection); + this.editor.removeListener("changeSession", this.$onChangeSession); + this.editor.commands.removeListener("afterExec", this.$onAfterExec); + this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler); + this.editor.tabstopManager = null; + this.editor = null; + }; + + this.onChange = function(e) { + var changeRange = e.data.range; + var isRemove = e.data.action[0] == "r"; + var start = changeRange.start; + var end = changeRange.end; + var startRow = start.row; + var endRow = end.row; + var lineDif = endRow - startRow; + var colDiff = end.column - start.column; + + if (isRemove) { + lineDif = -lineDif; + colDiff = -colDiff; + } + if (!this.$inChange && isRemove) { + var ts = this.selectedTabstop; + var changedOutside = ts && !ts.some(function(r) { + return comparePoints(r.start, start) <= 0 && comparePoints(r.end, end) >= 0; + }); + if (changedOutside) + return this.detach(); + } + var ranges = this.ranges; + for (var i = 0; i < ranges.length; i++) { + var r = ranges[i]; + if (r.end.row < start.row) + continue; + + if (isRemove && comparePoints(start, r.start) < 0 && comparePoints(end, r.end) > 0) { + this.removeRange(r); + i--; + continue; + } + + if (r.start.row == startRow && r.start.column > start.column) + r.start.column += colDiff; + if (r.end.row == startRow && r.end.column >= start.column) + r.end.column += colDiff; + if (r.start.row >= startRow) + r.start.row += lineDif; + if (r.end.row >= startRow) + r.end.row += lineDif; + + if (comparePoints(r.start, r.end) > 0) + this.removeRange(r); + } + if (!ranges.length) + this.detach(); + }; + this.updateLinkedFields = function() { + var ts = this.selectedTabstop; + if (!ts || !ts.hasLinkedRanges) + return; + this.$inChange = true; + var session = this.editor.session; + var text = session.getTextRange(ts.firstNonLinked); + for (var i = ts.length; i--;) { + var range = ts[i]; + if (!range.linked) + continue; + var fmt = exports.snippetManager.tmStrFormat(text, range.original); + session.replace(range, fmt); + } + this.$inChange = false; + }; + this.onAfterExec = function(e) { + if (e.command && !e.command.readOnly) + this.updateLinkedFields(); + }; + this.onChangeSelection = function() { + if (!this.editor) + return; + var lead = this.editor.selection.lead; + var anchor = this.editor.selection.anchor; + var isEmpty = this.editor.selection.isEmpty(); + for (var i = this.ranges.length; i--;) { + if (this.ranges[i].linked) + continue; + var containsLead = this.ranges[i].contains(lead.row, lead.column); + var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column); + if (containsLead && containsAnchor) + return; + } + this.detach(); + }; + this.onChangeSession = function() { + this.detach(); + }; + this.tabNext = function(dir) { + var max = this.tabstops.length; + var index = this.index + (dir || 1); + index = Math.min(Math.max(index, 1), max); + if (index == max) + index = 0; + this.selectTabstop(index); + if (index === 0) + this.detach(); + }; + this.selectTabstop = function(index) { + this.$openTabstops = null; + var ts = this.tabstops[this.index]; + if (ts) + this.addTabstopMarkers(ts); + this.index = index; + ts = this.tabstops[this.index]; + if (!ts || !ts.length) + return; + + this.selectedTabstop = ts; + if (!this.editor.inVirtualSelectionMode) { + var sel = this.editor.multiSelect; + sel.toSingleRange(ts.firstNonLinked.clone()); + for (var i = ts.length; i--;) { + if (ts.hasLinkedRanges && ts[i].linked) + continue; + sel.addRange(ts[i].clone(), true); + } + if (sel.ranges[0]) + sel.addRange(sel.ranges[0].clone()); + } else { + this.editor.selection.setRange(ts.firstNonLinked); + } + + this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); + }; + this.addTabstops = function(tabstops, start, end) { + if (!this.$openTabstops) + this.$openTabstops = []; + if (!tabstops[0]) { + var p = Range.fromPoints(end, end); + moveRelative(p.start, start); + moveRelative(p.end, start); + tabstops[0] = [p]; + tabstops[0].index = 0; + } + + var i = this.index; + var arg = [i + 1, 0]; + var ranges = this.ranges; + tabstops.forEach(function(ts, index) { + var dest = this.$openTabstops[index] || ts; + + for (var i = ts.length; i--;) { + var p = ts[i]; + var range = Range.fromPoints(p.start, p.end || p.start); + movePoint(range.start, start); + movePoint(range.end, start); + range.original = p; + range.tabstop = dest; + ranges.push(range); + if (dest != ts) + dest.unshift(range); + else + dest[i] = range; + if (p.fmtString) { + range.linked = true; + dest.hasLinkedRanges = true; + } else if (!dest.firstNonLinked) + dest.firstNonLinked = range; + } + if (!dest.firstNonLinked) + dest.hasLinkedRanges = false; + if (dest === ts) { + arg.push(dest); + this.$openTabstops[index] = dest; + } + this.addTabstopMarkers(dest); + }, this); + + if (arg.length > 2) { + if (this.tabstops.length) + arg.push(arg.splice(2, 1)[0]); + this.tabstops.splice.apply(this.tabstops, arg); + } + }; + + this.addTabstopMarkers = function(ts) { + var session = this.editor.session; + ts.forEach(function(range) { + if (!range.markerId) + range.markerId = session.addMarker(range, "ace_snippet-marker", "text"); + }); + }; + this.removeTabstopMarkers = function(ts) { + var session = this.editor.session; + ts.forEach(function(range) { + session.removeMarker(range.markerId); + range.markerId = null; + }); + }; + this.removeRange = function(range) { + var i = range.tabstop.indexOf(range); + range.tabstop.splice(i, 1); + i = this.ranges.indexOf(range); + this.ranges.splice(i, 1); + this.editor.session.removeMarker(range.markerId); + if (!range.tabstop.length) { + i = this.tabstops.indexOf(range.tabstop); + if (i != -1) + this.tabstops.splice(i, 1); + if (!this.tabstops.length) + this.detach(); + } + }; + + this.keyboardHandler = new HashHandler(); + this.keyboardHandler.bindKeys({ + "Tab": function(ed) { + if (exports.snippetManager && exports.snippetManager.expandWithTab(ed)) { + return; + } + + ed.tabstopManager.tabNext(1); + }, + "Shift-Tab": function(ed) { + ed.tabstopManager.tabNext(-1); + }, + "Esc": function(ed) { + ed.tabstopManager.detach(); + }, + "Return": function(ed) { + return false; + } + }); +}).call(TabstopManager.prototype); + + + +var changeTracker = {}; +changeTracker.onChange = Anchor.prototype.onChange; +changeTracker.setPosition = function(row, column) { + this.pos.row = row; + this.pos.column = column; +}; +changeTracker.update = function(pos, delta, $insertRight) { + this.$insertRight = $insertRight; + this.pos = pos; + this.onChange(delta); +}; + +var movePoint = function(point, diff) { + if (point.row == 0) + point.column += diff.column; + point.row += diff.row; +}; + +var moveRelative = function(point, start) { + if (point.row == start.row) + point.column -= start.column; + point.row -= start.row; +}; + + +require("./lib/dom").importCssString("\ +.ace_snippet-marker {\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + background: rgba(194, 193, 208, 0.09);\ + border: 1px dotted rgba(211, 208, 235, 0.62);\ + position: absolute;\ +}"); + +exports.snippetManager = new SnippetManager(); + + +var Editor = require("./editor").Editor; +(function() { + this.insertSnippet = function(content, options) { + return exports.snippetManager.insertSnippet(this, content, options); + }; + this.expandSnippet = function(options) { + return exports.snippetManager.expandWithTab(this, options); + }; +}).call(Editor.prototype); + +}); + +define("ace/ext/emmet",["require","exports","module","ace/keyboard/hash_handler","ace/editor","ace/snippets","ace/range","resources","resources","range","tabStops","resources","utils","actions","ace/config","ace/config"], function(require, exports, module) { +"use strict"; +var HashHandler = require("ace/keyboard/hash_handler").HashHandler; +var Editor = require("ace/editor").Editor; +var snippetManager = require("ace/snippets").snippetManager; +var Range = require("ace/range").Range; +var emmet, emmetPath; +function AceEmmetEditor() {} + +AceEmmetEditor.prototype = { + setupContext: function(editor) { + this.ace = editor; + this.indentation = editor.session.getTabString(); + if (!emmet) + emmet = window.emmet; + emmet.require("resources").setVariable("indentation", this.indentation); + this.$syntax = null; + this.$syntax = this.getSyntax(); + }, + getSelectionRange: function() { + var range = this.ace.getSelectionRange(); + var doc = this.ace.session.doc; + return { + start: doc.positionToIndex(range.start), + end: doc.positionToIndex(range.end) + }; + }, + createSelection: function(start, end) { + var doc = this.ace.session.doc; + this.ace.selection.setRange({ + start: doc.indexToPosition(start), + end: doc.indexToPosition(end) + }); + }, + getCurrentLineRange: function() { + var ace = this.ace; + var row = ace.getCursorPosition().row; + var lineLength = ace.session.getLine(row).length; + var index = ace.session.doc.positionToIndex({row: row, column: 0}); + return { + start: index, + end: index + lineLength + }; + }, + getCaretPos: function(){ + var pos = this.ace.getCursorPosition(); + return this.ace.session.doc.positionToIndex(pos); + }, + setCaretPos: function(index){ + var pos = this.ace.session.doc.indexToPosition(index); + this.ace.selection.moveToPosition(pos); + }, + getCurrentLine: function() { + var row = this.ace.getCursorPosition().row; + return this.ace.session.getLine(row); + }, + replaceContent: function(value, start, end, noIndent) { + if (end == null) + end = start == null ? this.getContent().length : start; + if (start == null) + start = 0; + + var editor = this.ace; + var doc = editor.session.doc; + var range = Range.fromPoints(doc.indexToPosition(start), doc.indexToPosition(end)); + editor.session.remove(range); + + range.end = range.start; + + value = this.$updateTabstops(value); + snippetManager.insertSnippet(editor, value); + }, + getContent: function(){ + return this.ace.getValue(); + }, + getSyntax: function() { + if (this.$syntax) + return this.$syntax; + var syntax = this.ace.session.$modeId.split("/").pop(); + if (syntax == "html" || syntax == "php") { + var cursor = this.ace.getCursorPosition(); + var state = this.ace.session.getState(cursor.row); + if (typeof state != "string") + state = state[0]; + if (state) { + state = state.split("-"); + if (state.length > 1) + syntax = state[0]; + else if (syntax == "php") + syntax = "html"; + } + } + return syntax; + }, + getProfileName: function() { + switch(this.getSyntax()) { + case "css": return "css"; + case "xml": + case "xsl": + return "xml"; + case "html": + var profile = emmet.require("resources").getVariable("profile"); + if (!profile) + profile = this.ace.session.getLines(0,2).join("").search(/]+XHTML/i) != -1 ? "xhtml": "html"; + return profile; + } + return "xhtml"; + }, + prompt: function(title) { + return prompt(title); + }, + getSelection: function() { + return this.ace.session.getTextRange(); + }, + getFilePath: function() { + return ""; + }, + $updateTabstops: function(value) { + var base = 1000; + var zeroBase = 0; + var lastZero = null; + var range = emmet.require('range'); + var ts = emmet.require('tabStops'); + var settings = emmet.require('resources').getVocabulary("user"); + var tabstopOptions = { + tabstop: function(data) { + var group = parseInt(data.group, 10); + var isZero = group === 0; + if (isZero) + group = ++zeroBase; + else + group += base; + + var placeholder = data.placeholder; + if (placeholder) { + placeholder = ts.processText(placeholder, tabstopOptions); + } + + var result = '${' + group + (placeholder ? ':' + placeholder : '') + '}'; + + if (isZero) { + lastZero = range.create(data.start, result); + } + + return result; + }, + escape: function(ch) { + if (ch == '$') return '\\$'; + if (ch == '\\') return '\\\\'; + return ch; + } + }; + + value = ts.processText(value, tabstopOptions); + + if (settings.variables['insert_final_tabstop'] && !/\$\{0\}$/.test(value)) { + value += '${0}'; + } else if (lastZero) { + value = emmet.require('utils').replaceSubstring(value, '${0}', lastZero); + } + + return value; + } +}; + + +var keymap = { + expand_abbreviation: {"mac": "ctrl+alt+e", "win": "alt+e"}, + match_pair_outward: {"mac": "ctrl+d", "win": "ctrl+,"}, + match_pair_inward: {"mac": "ctrl+j", "win": "ctrl+shift+0"}, + matching_pair: {"mac": "ctrl+alt+j", "win": "alt+j"}, + next_edit_point: "alt+right", + prev_edit_point: "alt+left", + toggle_comment: {"mac": "command+/", "win": "ctrl+/"}, + split_join_tag: {"mac": "shift+command+'", "win": "shift+ctrl+`"}, + remove_tag: {"mac": "command+'", "win": "shift+ctrl+;"}, + evaluate_math_expression: {"mac": "shift+command+y", "win": "shift+ctrl+y"}, + increment_number_by_1: "ctrl+up", + decrement_number_by_1: "ctrl+down", + increment_number_by_01: "alt+up", + decrement_number_by_01: "alt+down", + increment_number_by_10: {"mac": "alt+command+up", "win": "shift+alt+up"}, + decrement_number_by_10: {"mac": "alt+command+down", "win": "shift+alt+down"}, + select_next_item: {"mac": "shift+command+.", "win": "shift+ctrl+."}, + select_previous_item: {"mac": "shift+command+,", "win": "shift+ctrl+,"}, + reflect_css_value: {"mac": "shift+command+r", "win": "shift+ctrl+r"}, + + encode_decode_data_url: {"mac": "shift+ctrl+d", "win": "ctrl+'"}, + expand_abbreviation_with_tab: "Tab", + wrap_with_abbreviation: {"mac": "shift+ctrl+a", "win": "shift+ctrl+a"} +}; + +var editorProxy = new AceEmmetEditor(); +exports.commands = new HashHandler(); +exports.runEmmetCommand = function(editor) { + try { + editorProxy.setupContext(editor); + if (editorProxy.getSyntax() == "php") + return false; + var actions = emmet.require("actions"); + + if (this.action == "expand_abbreviation_with_tab") { + if (!editor.selection.isEmpty()) + return false; + } + + if (this.action == "wrap_with_abbreviation") { + return setTimeout(function() { + actions.run("wrap_with_abbreviation", editorProxy); + }, 0); + } + + var pos = editor.selection.lead; + var token = editor.session.getTokenAt(pos.row, pos.column); + if (token && /\btag\b/.test(token.type)) + return false; + + var result = actions.run(this.action, editorProxy); + } catch(e) { + editor._signal("changeStatus", typeof e == "string" ? e : e.message); + console.log(e); + result = false; + } + return result; +}; + +for (var command in keymap) { + exports.commands.addCommand({ + name: "emmet:" + command, + action: command, + bindKey: keymap[command], + exec: exports.runEmmetCommand, + multiSelectAction: "forEach" + }); +} + +exports.updateCommands = function(editor, enabled) { + if (enabled) { + editor.keyBinding.addKeyboardHandler(exports.commands); + } else { + editor.keyBinding.removeKeyboardHandler(exports.commands); + } +}; + +exports.isSupportedMode = function(modeId) { + return modeId && /css|less|scss|sass|stylus|html|php|twig|ejs/.test(modeId); +}; + +var onChangeMode = function(e, target) { + var editor = target; + if (!editor) + return; + var enabled = exports.isSupportedMode(editor.session.$modeId); + if (e.enableEmmet === false) + enabled = false; + if (enabled) { + if (typeof emmetPath == "string") { + require("ace/config").loadModule(emmetPath, function() { + emmetPath = null; + }); + } + } + exports.updateCommands(editor, enabled); +}; + +exports.AceEmmetEditor = AceEmmetEditor; +require("ace/config").defineOptions(Editor.prototype, "editor", { + enableEmmet: { + set: function(val) { + this[val ? "on" : "removeListener"]("changeMode", onChangeMode); + onChangeMode({enableEmmet: !!val}, this); + }, + value: true + } +}); + +exports.setCore = function(e) { + if (typeof e == "string") + emmetPath = e; + else + emmet = e; +}; +}); + (function() { + window.require(["ace/ext/emmet"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-error_marker.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-error_marker.js new file mode 100644 index 00000000..31ac11d8 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-error_marker.js @@ -0,0 +1,6 @@ + +; + (function() { + window.require(["ace/ext/error_marker"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-keybinding_menu.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-keybinding_menu.js new file mode 100644 index 00000000..895e9be6 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-keybinding_menu.js @@ -0,0 +1,170 @@ +define("ace/ext/menu_tools/overlay_page",["require","exports","module","ace/lib/dom"], function(require, exports, module) { +'use strict'; +var dom = require("../../lib/dom"); +var cssText = "#ace_settingsmenu, #kbshortcutmenu {\ +background-color: #F7F7F7;\ +color: black;\ +box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);\ +padding: 1em 0.5em 2em 1em;\ +overflow: auto;\ +position: absolute;\ +margin: 0;\ +bottom: 0;\ +right: 0;\ +top: 0;\ +z-index: 9991;\ +cursor: default;\ +}\ +.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {\ +box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);\ +background-color: rgba(255, 255, 255, 0.6);\ +color: black;\ +}\ +.ace_optionsMenuEntry:hover {\ +background-color: rgba(100, 100, 100, 0.1);\ +-webkit-transition: all 0.5s;\ +transition: all 0.3s\ +}\ +.ace_closeButton {\ +background: rgba(245, 146, 146, 0.5);\ +border: 1px solid #F48A8A;\ +border-radius: 50%;\ +padding: 7px;\ +position: absolute;\ +right: -8px;\ +top: -8px;\ +z-index: 1000;\ +}\ +.ace_closeButton{\ +background: rgba(245, 146, 146, 0.9);\ +}\ +.ace_optionsMenuKey {\ +color: darkslateblue;\ +font-weight: bold;\ +}\ +.ace_optionsMenuCommand {\ +color: darkcyan;\ +font-weight: normal;\ +}"; +dom.importCssString(cssText); +module.exports.overlayPage = function overlayPage(editor, contentElement, top, right, bottom, left) { + top = top ? 'top: ' + top + ';' : ''; + bottom = bottom ? 'bottom: ' + bottom + ';' : ''; + right = right ? 'right: ' + right + ';' : ''; + left = left ? 'left: ' + left + ';' : ''; + + var closer = document.createElement('div'); + var contentContainer = document.createElement('div'); + + function documentEscListener(e) { + if (e.keyCode === 27) { + closer.click(); + } + } + + closer.style.cssText = 'margin: 0; padding: 0; ' + + 'position: fixed; top:0; bottom:0; left:0; right:0;' + + 'z-index: 9990; ' + + 'background-color: rgba(0, 0, 0, 0.3);'; + closer.addEventListener('click', function() { + document.removeEventListener('keydown', documentEscListener); + closer.parentNode.removeChild(closer); + editor.focus(); + closer = null; + }); + document.addEventListener('keydown', documentEscListener); + + contentContainer.style.cssText = top + right + bottom + left; + contentContainer.addEventListener('click', function(e) { + e.stopPropagation(); + }); + + var wrapper = dom.createElement("div"); + wrapper.style.position = "relative"; + + var closeButton = dom.createElement("div"); + closeButton.className = "ace_closeButton"; + closeButton.addEventListener('click', function() { + closer.click(); + }); + + wrapper.appendChild(closeButton); + contentContainer.appendChild(wrapper); + + contentContainer.appendChild(contentElement); + closer.appendChild(contentContainer); + document.body.appendChild(closer); + editor.blur(); +}; + +}); + +define("ace/ext/menu_tools/get_editor_keyboard_shortcuts",["require","exports","module","ace/lib/keys"], function(require, exports, module) { +"use strict"; +var keys = require("../../lib/keys"); +module.exports.getEditorKeybordShortcuts = function(editor) { + var KEY_MODS = keys.KEY_MODS; + var keybindings = []; + var commandMap = {}; + editor.keyBinding.$handlers.forEach(function(handler) { + var ckb = handler.commandKeyBinding; + for (var i in ckb) { + var key = i.replace(/(^|-)\w/g, function(x) { return x.toUpperCase(); }); + var commands = ckb[i]; + if (!Array.isArray(commands)) + commands = [commands]; + commands.forEach(function(command) { + if (typeof command != "string") + command = command.name + if (commandMap[command]) { + commandMap[command].key += "|" + key; + } else { + commandMap[command] = {key: key, command: command}; + keybindings.push(commandMap[command]); + } + }); + } + }); + return keybindings; +}; + +}); + +define("ace/ext/keybinding_menu",["require","exports","module","ace/editor","ace/ext/menu_tools/overlay_page","ace/ext/menu_tools/get_editor_keyboard_shortcuts"], function(require, exports, module) { + "use strict"; + var Editor = require("ace/editor").Editor; + function showKeyboardShortcuts (editor) { + if(!document.getElementById('kbshortcutmenu')) { + var overlayPage = require('./menu_tools/overlay_page').overlayPage; + var getEditorKeybordShortcuts = require('./menu_tools/get_editor_keyboard_shortcuts').getEditorKeybordShortcuts; + var kb = getEditorKeybordShortcuts(editor); + var el = document.createElement('div'); + var commands = kb.reduce(function(previous, current) { + return previous + '
' + + current.command + ' : ' + + '' + current.key + '
'; + }, ''); + + el.id = 'kbshortcutmenu'; + el.innerHTML = '

Keyboard Shortcuts

' + commands + '
'; + overlayPage(editor, el, '0', '0', '0', null); + } + }; + module.exports.init = function(editor) { + Editor.prototype.showKeyboardShortcuts = function() { + showKeyboardShortcuts(this); + }; + editor.commands.addCommands([{ + name: "showKeyboardShortcuts", + bindKey: {win: "Ctrl-Alt-h", mac: "Command-Alt-h"}, + exec: function(editor, line) { + editor.showKeyboardShortcuts(); + } + }]); + }; + +}); + (function() { + window.require(["ace/ext/keybinding_menu"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-language_tools.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-language_tools.js new file mode 100644 index 00000000..011c6b37 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-language_tools.js @@ -0,0 +1,1936 @@ +define("ace/snippets",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/lib/lang","ace/range","ace/anchor","ace/keyboard/hash_handler","ace/tokenizer","ace/lib/dom","ace/editor"], function(require, exports, module) { +"use strict"; +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var lang = require("./lib/lang"); +var Range = require("./range").Range; +var Anchor = require("./anchor").Anchor; +var HashHandler = require("./keyboard/hash_handler").HashHandler; +var Tokenizer = require("./tokenizer").Tokenizer; +var comparePoints = Range.comparePoints; + +var SnippetManager = function() { + this.snippetMap = {}; + this.snippetNameMap = {}; +}; + +(function() { + oop.implement(this, EventEmitter); + + this.getTokenizer = function() { + function TabstopToken(str, _, stack) { + str = str.substr(1); + if (/^\d+$/.test(str) && !stack.inFormatString) + return [{tabstopId: parseInt(str, 10)}]; + return [{text: str}]; + } + function escape(ch) { + return "(?:[^\\\\" + ch + "]|\\\\.)"; + } + SnippetManager.$tokenizer = new Tokenizer({ + start: [ + {regex: /:/, onMatch: function(val, state, stack) { + if (stack.length && stack[0].expectIf) { + stack[0].expectIf = false; + stack[0].elseBranch = stack[0]; + return [stack[0]]; + } + return ":"; + }}, + {regex: /\\./, onMatch: function(val, state, stack) { + var ch = val[1]; + if (ch == "}" && stack.length) { + val = ch; + }else if ("`$\\".indexOf(ch) != -1) { + val = ch; + } else if (stack.inFormatString) { + if (ch == "n") + val = "\n"; + else if (ch == "t") + val = "\n"; + else if ("ulULE".indexOf(ch) != -1) { + val = {changeCase: ch, local: ch > "a"}; + } + } + + return [val]; + }}, + {regex: /}/, onMatch: function(val, state, stack) { + return [stack.length ? stack.shift() : val]; + }}, + {regex: /\$(?:\d+|\w+)/, onMatch: TabstopToken}, + {regex: /\$\{[\dA-Z_a-z]+/, onMatch: function(str, state, stack) { + var t = TabstopToken(str.substr(1), state, stack); + stack.unshift(t[0]); + return t; + }, next: "snippetVar"}, + {regex: /\n/, token: "newline", merge: false} + ], + snippetVar: [ + {regex: "\\|" + escape("\\|") + "*\\|", onMatch: function(val, state, stack) { + stack[0].choices = val.slice(1, -1).split(","); + }, next: "start"}, + {regex: "/(" + escape("/") + "+)/(?:(" + escape("/") + "*)/)(\\w*):?", + onMatch: function(val, state, stack) { + var ts = stack[0]; + ts.fmtString = val; + + val = this.splitRegex.exec(val); + ts.guard = val[1]; + ts.fmt = val[2]; + ts.flag = val[3]; + return ""; + }, next: "start"}, + {regex: "`" + escape("`") + "*`", onMatch: function(val, state, stack) { + stack[0].code = val.splice(1, -1); + return ""; + }, next: "start"}, + {regex: "\\?", onMatch: function(val, state, stack) { + if (stack[0]) + stack[0].expectIf = true; + }, next: "start"}, + {regex: "([^:}\\\\]|\\\\.)*:?", token: "", next: "start"} + ], + formatString: [ + {regex: "/(" + escape("/") + "+)/", token: "regex"}, + {regex: "", onMatch: function(val, state, stack) { + stack.inFormatString = true; + }, next: "start"} + ] + }); + SnippetManager.prototype.getTokenizer = function() { + return SnippetManager.$tokenizer; + }; + return SnippetManager.$tokenizer; + }; + + this.tokenizeTmSnippet = function(str, startState) { + return this.getTokenizer().getLineTokens(str, startState).tokens.map(function(x) { + return x.value || x; + }); + }; + + this.$getDefaultValue = function(editor, name) { + if (/^[A-Z]\d+$/.test(name)) { + var i = name.substr(1); + return (this.variables[name[0] + "__"] || {})[i]; + } + if (/^\d+$/.test(name)) { + return (this.variables.__ || {})[name]; + } + name = name.replace(/^TM_/, ""); + + if (!editor) + return; + var s = editor.session; + switch(name) { + case "CURRENT_WORD": + var r = s.getWordRange(); + case "SELECTION": + case "SELECTED_TEXT": + return s.getTextRange(r); + case "CURRENT_LINE": + return s.getLine(editor.getCursorPosition().row); + case "PREV_LINE": // not possible in textmate + return s.getLine(editor.getCursorPosition().row - 1); + case "LINE_INDEX": + return editor.getCursorPosition().column; + case "LINE_NUMBER": + return editor.getCursorPosition().row + 1; + case "SOFT_TABS": + return s.getUseSoftTabs() ? "YES" : "NO"; + case "TAB_SIZE": + return s.getTabSize(); + case "FILENAME": + case "FILEPATH": + return ""; + case "FULLNAME": + return "Ace"; + } + }; + this.variables = {}; + this.getVariableValue = function(editor, varName) { + if (this.variables.hasOwnProperty(varName)) + return this.variables[varName](editor, varName) || ""; + return this.$getDefaultValue(editor, varName) || ""; + }; + this.tmStrFormat = function(str, ch, editor) { + var flag = ch.flag || ""; + var re = ch.guard; + re = new RegExp(re, flag.replace(/[^gi]/, "")); + var fmtTokens = this.tokenizeTmSnippet(ch.fmt, "formatString"); + var _self = this; + var formatted = str.replace(re, function() { + _self.variables.__ = arguments; + var fmtParts = _self.resolveVariables(fmtTokens, editor); + var gChangeCase = "E"; + for (var i = 0; i < fmtParts.length; i++) { + var ch = fmtParts[i]; + if (typeof ch == "object") { + fmtParts[i] = ""; + if (ch.changeCase && ch.local) { + var next = fmtParts[i + 1]; + if (next && typeof next == "string") { + if (ch.changeCase == "u") + fmtParts[i] = next[0].toUpperCase(); + else + fmtParts[i] = next[0].toLowerCase(); + fmtParts[i + 1] = next.substr(1); + } + } else if (ch.changeCase) { + gChangeCase = ch.changeCase; + } + } else if (gChangeCase == "U") { + fmtParts[i] = ch.toUpperCase(); + } else if (gChangeCase == "L") { + fmtParts[i] = ch.toLowerCase(); + } + } + return fmtParts.join(""); + }); + this.variables.__ = null; + return formatted; + }; + + this.resolveVariables = function(snippet, editor) { + var result = []; + for (var i = 0; i < snippet.length; i++) { + var ch = snippet[i]; + if (typeof ch == "string") { + result.push(ch); + } else if (typeof ch != "object") { + continue; + } else if (ch.skip) { + gotoNext(ch); + } else if (ch.processed < i) { + continue; + } else if (ch.text) { + var value = this.getVariableValue(editor, ch.text); + if (value && ch.fmtString) + value = this.tmStrFormat(value, ch); + ch.processed = i; + if (ch.expectIf == null) { + if (value) { + result.push(value); + gotoNext(ch); + } + } else { + if (value) { + ch.skip = ch.elseBranch; + } else + gotoNext(ch); + } + } else if (ch.tabstopId != null) { + result.push(ch); + } else if (ch.changeCase != null) { + result.push(ch); + } + } + function gotoNext(ch) { + var i1 = snippet.indexOf(ch, i + 1); + if (i1 != -1) + i = i1; + } + return result; + }; + + this.insertSnippetForSelection = function(editor, snippetText) { + var cursor = editor.getCursorPosition(); + var line = editor.session.getLine(cursor.row); + var tabString = editor.session.getTabString(); + var indentString = line.match(/^\s*/)[0]; + + if (cursor.column < indentString.length) + indentString = indentString.slice(0, cursor.column); + + var tokens = this.tokenizeTmSnippet(snippetText); + tokens = this.resolveVariables(tokens, editor); + tokens = tokens.map(function(x) { + if (x == "\n") + return x + indentString; + if (typeof x == "string") + return x.replace(/\t/g, tabString); + return x; + }); + var tabstops = []; + tokens.forEach(function(p, i) { + if (typeof p != "object") + return; + var id = p.tabstopId; + var ts = tabstops[id]; + if (!ts) { + ts = tabstops[id] = []; + ts.index = id; + ts.value = ""; + } + if (ts.indexOf(p) !== -1) + return; + ts.push(p); + var i1 = tokens.indexOf(p, i + 1); + if (i1 === -1) + return; + + var value = tokens.slice(i + 1, i1); + var isNested = value.some(function(t) {return typeof t === "object"}); + if (isNested && !ts.value) { + ts.value = value; + } else if (value.length && (!ts.value || typeof ts.value !== "string")) { + ts.value = value.join(""); + } + }); + tabstops.forEach(function(ts) {ts.length = 0}); + var expanding = {}; + function copyValue(val) { + var copy = []; + for (var i = 0; i < val.length; i++) { + var p = val[i]; + if (typeof p == "object") { + if (expanding[p.tabstopId]) + continue; + var j = val.lastIndexOf(p, i - 1); + p = copy[j] || {tabstopId: p.tabstopId}; + } + copy[i] = p; + } + return copy; + } + for (var i = 0; i < tokens.length; i++) { + var p = tokens[i]; + if (typeof p != "object") + continue; + var id = p.tabstopId; + var i1 = tokens.indexOf(p, i + 1); + if (expanding[id]) { + if (expanding[id] === p) + expanding[id] = null; + continue; + } + + var ts = tabstops[id]; + var arg = typeof ts.value == "string" ? [ts.value] : copyValue(ts.value); + arg.unshift(i + 1, Math.max(0, i1 - i)); + arg.push(p); + expanding[id] = p; + tokens.splice.apply(tokens, arg); + + if (ts.indexOf(p) === -1) + ts.push(p); + } + var row = 0, column = 0; + var text = ""; + tokens.forEach(function(t) { + if (typeof t === "string") { + if (t[0] === "\n"){ + column = t.length - 1; + row ++; + } else + column += t.length; + text += t; + } else { + if (!t.start) + t.start = {row: row, column: column}; + else + t.end = {row: row, column: column}; + } + }); + var range = editor.getSelectionRange(); + var end = editor.session.replace(range, text); + + var tabstopManager = new TabstopManager(editor); + var selectionId = editor.inVirtualSelectionMode && editor.selection.index; + tabstopManager.addTabstops(tabstops, range.start, end, selectionId); + }; + + this.insertSnippet = function(editor, snippetText) { + var self = this; + if (editor.inVirtualSelectionMode) + return self.insertSnippetForSelection(editor, snippetText); + + editor.forEachSelection(function() { + self.insertSnippetForSelection(editor, snippetText); + }, null, {keepOrder: true}); + + if (editor.tabstopManager) + editor.tabstopManager.tabNext(); + }; + + this.$getScope = function(editor) { + var scope = editor.session.$mode.$id || ""; + scope = scope.split("/").pop(); + if (scope === "html" || scope === "php") { + if (scope === "php" && !editor.session.$mode.inlinePhp) + scope = "html"; + var c = editor.getCursorPosition(); + var state = editor.session.getState(c.row); + if (typeof state === "object") { + state = state[0]; + } + if (state.substring) { + if (state.substring(0, 3) == "js-") + scope = "javascript"; + else if (state.substring(0, 4) == "css-") + scope = "css"; + else if (state.substring(0, 4) == "php-") + scope = "php"; + } + } + + return scope; + }; + + this.getActiveScopes = function(editor) { + var scope = this.$getScope(editor); + var scopes = [scope]; + var snippetMap = this.snippetMap; + if (snippetMap[scope] && snippetMap[scope].includeScopes) { + scopes.push.apply(scopes, snippetMap[scope].includeScopes); + } + scopes.push("_"); + return scopes; + }; + + this.expandWithTab = function(editor, options) { + var self = this; + var result = editor.forEachSelection(function() { + return self.expandSnippetForSelection(editor, options); + }, null, {keepOrder: true}); + if (result && editor.tabstopManager) + editor.tabstopManager.tabNext(); + return result; + }; + + this.expandSnippetForSelection = function(editor, options) { + var cursor = editor.getCursorPosition(); + var line = editor.session.getLine(cursor.row); + var before = line.substring(0, cursor.column); + var after = line.substr(cursor.column); + + var snippetMap = this.snippetMap; + var snippet; + this.getActiveScopes(editor).some(function(scope) { + var snippets = snippetMap[scope]; + if (snippets) + snippet = this.findMatchingSnippet(snippets, before, after); + return !!snippet; + }, this); + if (!snippet) + return false; + if (options && options.dryRun) + return true; + editor.session.doc.removeInLine(cursor.row, + cursor.column - snippet.replaceBefore.length, + cursor.column + snippet.replaceAfter.length + ); + + this.variables.M__ = snippet.matchBefore; + this.variables.T__ = snippet.matchAfter; + this.insertSnippetForSelection(editor, snippet.content); + + this.variables.M__ = this.variables.T__ = null; + return true; + }; + + this.findMatchingSnippet = function(snippetList, before, after) { + for (var i = snippetList.length; i--;) { + var s = snippetList[i]; + if (s.startRe && !s.startRe.test(before)) + continue; + if (s.endRe && !s.endRe.test(after)) + continue; + if (!s.startRe && !s.endRe) + continue; + + s.matchBefore = s.startRe ? s.startRe.exec(before) : [""]; + s.matchAfter = s.endRe ? s.endRe.exec(after) : [""]; + s.replaceBefore = s.triggerRe ? s.triggerRe.exec(before)[0] : ""; + s.replaceAfter = s.endTriggerRe ? s.endTriggerRe.exec(after)[0] : ""; + return s; + } + }; + + this.snippetMap = {}; + this.snippetNameMap = {}; + this.register = function(snippets, scope) { + var snippetMap = this.snippetMap; + var snippetNameMap = this.snippetNameMap; + var self = this; + + if (!snippets) + snippets = []; + + function wrapRegexp(src) { + if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src)) + src = "(?:" + src + ")"; + + return src || ""; + } + function guardedRegexp(re, guard, opening) { + re = wrapRegexp(re); + guard = wrapRegexp(guard); + if (opening) { + re = guard + re; + if (re && re[re.length - 1] != "$") + re = re + "$"; + } else { + re = re + guard; + if (re && re[0] != "^") + re = "^" + re; + } + return new RegExp(re); + } + + function addSnippet(s) { + if (!s.scope) + s.scope = scope || "_"; + scope = s.scope; + if (!snippetMap[scope]) { + snippetMap[scope] = []; + snippetNameMap[scope] = {}; + } + + var map = snippetNameMap[scope]; + if (s.name) { + var old = map[s.name]; + if (old) + self.unregister(old); + map[s.name] = s; + } + snippetMap[scope].push(s); + + if (s.tabTrigger && !s.trigger) { + if (!s.guard && /^\w/.test(s.tabTrigger)) + s.guard = "\\b"; + s.trigger = lang.escapeRegExp(s.tabTrigger); + } + + s.startRe = guardedRegexp(s.trigger, s.guard, true); + s.triggerRe = new RegExp(s.trigger, "", true); + + s.endRe = guardedRegexp(s.endTrigger, s.endGuard, true); + s.endTriggerRe = new RegExp(s.endTrigger, "", true); + } + + if (snippets && snippets.content) + addSnippet(snippets); + else if (Array.isArray(snippets)) + snippets.forEach(addSnippet); + + this._signal("registerSnippets", {scope: scope}); + }; + this.unregister = function(snippets, scope) { + var snippetMap = this.snippetMap; + var snippetNameMap = this.snippetNameMap; + + function removeSnippet(s) { + var nameMap = snippetNameMap[s.scope||scope]; + if (nameMap && nameMap[s.name]) { + delete nameMap[s.name]; + var map = snippetMap[s.scope||scope]; + var i = map && map.indexOf(s); + if (i >= 0) + map.splice(i, 1); + } + } + if (snippets.content) + removeSnippet(snippets); + else if (Array.isArray(snippets)) + snippets.forEach(removeSnippet); + }; + this.parseSnippetFile = function(str) { + str = str.replace(/\r/g, ""); + var list = [], snippet = {}; + var re = /^#.*|^({[\s\S]*})\s*$|^(\S+) (.*)$|^((?:\n*\t.*)+)/gm; + var m; + while (m = re.exec(str)) { + if (m[1]) { + try { + snippet = JSON.parse(m[1]); + list.push(snippet); + } catch (e) {} + } if (m[4]) { + snippet.content = m[4].replace(/^\t/gm, ""); + list.push(snippet); + snippet = {}; + } else { + var key = m[2], val = m[3]; + if (key == "regex") { + var guardRe = /\/((?:[^\/\\]|\\.)*)|$/g; + snippet.guard = guardRe.exec(val)[1]; + snippet.trigger = guardRe.exec(val)[1]; + snippet.endTrigger = guardRe.exec(val)[1]; + snippet.endGuard = guardRe.exec(val)[1]; + } else if (key == "snippet") { + snippet.tabTrigger = val.match(/^\S*/)[0]; + if (!snippet.name) + snippet.name = val; + } else { + snippet[key] = val; + } + } + } + return list; + }; + this.getSnippetByName = function(name, editor) { + var snippetMap = this.snippetNameMap; + var snippet; + this.getActiveScopes(editor).some(function(scope) { + var snippets = snippetMap[scope]; + if (snippets) + snippet = snippets[name]; + return !!snippet; + }, this); + return snippet; + }; + +}).call(SnippetManager.prototype); + + +var TabstopManager = function(editor) { + if (editor.tabstopManager) + return editor.tabstopManager; + editor.tabstopManager = this; + this.$onChange = this.onChange.bind(this); + this.$onChangeSelection = lang.delayedCall(this.onChangeSelection.bind(this)).schedule; + this.$onChangeSession = this.onChangeSession.bind(this); + this.$onAfterExec = this.onAfterExec.bind(this); + this.attach(editor); +}; +(function() { + this.attach = function(editor) { + this.index = 0; + this.ranges = []; + this.tabstops = []; + this.$openTabstops = null; + this.selectedTabstop = null; + + this.editor = editor; + this.editor.on("change", this.$onChange); + this.editor.on("changeSelection", this.$onChangeSelection); + this.editor.on("changeSession", this.$onChangeSession); + this.editor.commands.on("afterExec", this.$onAfterExec); + this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); + }; + this.detach = function() { + this.tabstops.forEach(this.removeTabstopMarkers, this); + this.ranges = null; + this.tabstops = null; + this.selectedTabstop = null; + this.editor.removeListener("change", this.$onChange); + this.editor.removeListener("changeSelection", this.$onChangeSelection); + this.editor.removeListener("changeSession", this.$onChangeSession); + this.editor.commands.removeListener("afterExec", this.$onAfterExec); + this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler); + this.editor.tabstopManager = null; + this.editor = null; + }; + + this.onChange = function(e) { + var changeRange = e.data.range; + var isRemove = e.data.action[0] == "r"; + var start = changeRange.start; + var end = changeRange.end; + var startRow = start.row; + var endRow = end.row; + var lineDif = endRow - startRow; + var colDiff = end.column - start.column; + + if (isRemove) { + lineDif = -lineDif; + colDiff = -colDiff; + } + if (!this.$inChange && isRemove) { + var ts = this.selectedTabstop; + var changedOutside = ts && !ts.some(function(r) { + return comparePoints(r.start, start) <= 0 && comparePoints(r.end, end) >= 0; + }); + if (changedOutside) + return this.detach(); + } + var ranges = this.ranges; + for (var i = 0; i < ranges.length; i++) { + var r = ranges[i]; + if (r.end.row < start.row) + continue; + + if (isRemove && comparePoints(start, r.start) < 0 && comparePoints(end, r.end) > 0) { + this.removeRange(r); + i--; + continue; + } + + if (r.start.row == startRow && r.start.column > start.column) + r.start.column += colDiff; + if (r.end.row == startRow && r.end.column >= start.column) + r.end.column += colDiff; + if (r.start.row >= startRow) + r.start.row += lineDif; + if (r.end.row >= startRow) + r.end.row += lineDif; + + if (comparePoints(r.start, r.end) > 0) + this.removeRange(r); + } + if (!ranges.length) + this.detach(); + }; + this.updateLinkedFields = function() { + var ts = this.selectedTabstop; + if (!ts || !ts.hasLinkedRanges) + return; + this.$inChange = true; + var session = this.editor.session; + var text = session.getTextRange(ts.firstNonLinked); + for (var i = ts.length; i--;) { + var range = ts[i]; + if (!range.linked) + continue; + var fmt = exports.snippetManager.tmStrFormat(text, range.original); + session.replace(range, fmt); + } + this.$inChange = false; + }; + this.onAfterExec = function(e) { + if (e.command && !e.command.readOnly) + this.updateLinkedFields(); + }; + this.onChangeSelection = function() { + if (!this.editor) + return; + var lead = this.editor.selection.lead; + var anchor = this.editor.selection.anchor; + var isEmpty = this.editor.selection.isEmpty(); + for (var i = this.ranges.length; i--;) { + if (this.ranges[i].linked) + continue; + var containsLead = this.ranges[i].contains(lead.row, lead.column); + var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column); + if (containsLead && containsAnchor) + return; + } + this.detach(); + }; + this.onChangeSession = function() { + this.detach(); + }; + this.tabNext = function(dir) { + var max = this.tabstops.length; + var index = this.index + (dir || 1); + index = Math.min(Math.max(index, 1), max); + if (index == max) + index = 0; + this.selectTabstop(index); + if (index === 0) + this.detach(); + }; + this.selectTabstop = function(index) { + this.$openTabstops = null; + var ts = this.tabstops[this.index]; + if (ts) + this.addTabstopMarkers(ts); + this.index = index; + ts = this.tabstops[this.index]; + if (!ts || !ts.length) + return; + + this.selectedTabstop = ts; + if (!this.editor.inVirtualSelectionMode) { + var sel = this.editor.multiSelect; + sel.toSingleRange(ts.firstNonLinked.clone()); + for (var i = ts.length; i--;) { + if (ts.hasLinkedRanges && ts[i].linked) + continue; + sel.addRange(ts[i].clone(), true); + } + if (sel.ranges[0]) + sel.addRange(sel.ranges[0].clone()); + } else { + this.editor.selection.setRange(ts.firstNonLinked); + } + + this.editor.keyBinding.addKeyboardHandler(this.keyboardHandler); + }; + this.addTabstops = function(tabstops, start, end) { + if (!this.$openTabstops) + this.$openTabstops = []; + if (!tabstops[0]) { + var p = Range.fromPoints(end, end); + moveRelative(p.start, start); + moveRelative(p.end, start); + tabstops[0] = [p]; + tabstops[0].index = 0; + } + + var i = this.index; + var arg = [i + 1, 0]; + var ranges = this.ranges; + tabstops.forEach(function(ts, index) { + var dest = this.$openTabstops[index] || ts; + + for (var i = ts.length; i--;) { + var p = ts[i]; + var range = Range.fromPoints(p.start, p.end || p.start); + movePoint(range.start, start); + movePoint(range.end, start); + range.original = p; + range.tabstop = dest; + ranges.push(range); + if (dest != ts) + dest.unshift(range); + else + dest[i] = range; + if (p.fmtString) { + range.linked = true; + dest.hasLinkedRanges = true; + } else if (!dest.firstNonLinked) + dest.firstNonLinked = range; + } + if (!dest.firstNonLinked) + dest.hasLinkedRanges = false; + if (dest === ts) { + arg.push(dest); + this.$openTabstops[index] = dest; + } + this.addTabstopMarkers(dest); + }, this); + + if (arg.length > 2) { + if (this.tabstops.length) + arg.push(arg.splice(2, 1)[0]); + this.tabstops.splice.apply(this.tabstops, arg); + } + }; + + this.addTabstopMarkers = function(ts) { + var session = this.editor.session; + ts.forEach(function(range) { + if (!range.markerId) + range.markerId = session.addMarker(range, "ace_snippet-marker", "text"); + }); + }; + this.removeTabstopMarkers = function(ts) { + var session = this.editor.session; + ts.forEach(function(range) { + session.removeMarker(range.markerId); + range.markerId = null; + }); + }; + this.removeRange = function(range) { + var i = range.tabstop.indexOf(range); + range.tabstop.splice(i, 1); + i = this.ranges.indexOf(range); + this.ranges.splice(i, 1); + this.editor.session.removeMarker(range.markerId); + if (!range.tabstop.length) { + i = this.tabstops.indexOf(range.tabstop); + if (i != -1) + this.tabstops.splice(i, 1); + if (!this.tabstops.length) + this.detach(); + } + }; + + this.keyboardHandler = new HashHandler(); + this.keyboardHandler.bindKeys({ + "Tab": function(ed) { + if (exports.snippetManager && exports.snippetManager.expandWithTab(ed)) { + return; + } + + ed.tabstopManager.tabNext(1); + }, + "Shift-Tab": function(ed) { + ed.tabstopManager.tabNext(-1); + }, + "Esc": function(ed) { + ed.tabstopManager.detach(); + }, + "Return": function(ed) { + return false; + } + }); +}).call(TabstopManager.prototype); + + + +var changeTracker = {}; +changeTracker.onChange = Anchor.prototype.onChange; +changeTracker.setPosition = function(row, column) { + this.pos.row = row; + this.pos.column = column; +}; +changeTracker.update = function(pos, delta, $insertRight) { + this.$insertRight = $insertRight; + this.pos = pos; + this.onChange(delta); +}; + +var movePoint = function(point, diff) { + if (point.row == 0) + point.column += diff.column; + point.row += diff.row; +}; + +var moveRelative = function(point, start) { + if (point.row == start.row) + point.column -= start.column; + point.row -= start.row; +}; + + +require("./lib/dom").importCssString("\ +.ace_snippet-marker {\ + -moz-box-sizing: border-box;\ + box-sizing: border-box;\ + background: rgba(194, 193, 208, 0.09);\ + border: 1px dotted rgba(211, 208, 235, 0.62);\ + position: absolute;\ +}"); + +exports.snippetManager = new SnippetManager(); + + +var Editor = require("./editor").Editor; +(function() { + this.insertSnippet = function(content, options) { + return exports.snippetManager.insertSnippet(this, content, options); + }; + this.expandSnippet = function(options) { + return exports.snippetManager.expandWithTab(this, options); + }; +}).call(Editor.prototype); + +}); + +define("ace/autocomplete/popup",["require","exports","module","ace/edit_session","ace/virtual_renderer","ace/editor","ace/range","ace/lib/event","ace/lib/lang","ace/lib/dom"], function(require, exports, module) { +"use strict"; + +var EditSession = require("../edit_session").EditSession; +var Renderer = require("../virtual_renderer").VirtualRenderer; +var Editor = require("../editor").Editor; +var Range = require("../range").Range; +var event = require("../lib/event"); +var lang = require("../lib/lang"); +var dom = require("../lib/dom"); + +var $singleLineEditor = function(el) { + var renderer = new Renderer(el); + + renderer.$maxLines = 4; + + var editor = new Editor(renderer); + + editor.setHighlightActiveLine(false); + editor.setShowPrintMargin(false); + editor.renderer.setShowGutter(false); + editor.renderer.setHighlightGutterLine(false); + + editor.$mouseHandler.$focusWaitTimout = 0; + editor.$highlightTagPending = true; + + return editor; +}; + +var AcePopup = function(parentNode) { + var el = dom.createElement("div"); + var popup = new $singleLineEditor(el); + + if (parentNode) + parentNode.appendChild(el); + el.style.display = "none"; + popup.renderer.content.style.cursor = "default"; + popup.renderer.setStyle("ace_autocomplete"); + + popup.setOption("displayIndentGuides", false); + popup.setOption("dragDelay", 150); + + var noop = function(){}; + + popup.focus = noop; + popup.$isFocused = true; + + popup.renderer.$cursorLayer.restartTimer = noop; + popup.renderer.$cursorLayer.element.style.opacity = 0; + + popup.renderer.$maxLines = 8; + popup.renderer.$keepTextAreaAtCursor = false; + + popup.setHighlightActiveLine(false); + popup.session.highlight(""); + popup.session.$searchHighlight.clazz = "ace_highlight-marker"; + + popup.on("mousedown", function(e) { + var pos = e.getDocumentPosition(); + popup.selection.moveToPosition(pos); + selectionMarker.start.row = selectionMarker.end.row = pos.row; + e.stop(); + }); + + var lastMouseEvent; + var hoverMarker = new Range(-1,0,-1,Infinity); + var selectionMarker = new Range(-1,0,-1,Infinity); + selectionMarker.id = popup.session.addMarker(selectionMarker, "ace_active-line", "fullLine"); + popup.setSelectOnHover = function(val) { + if (!val) { + hoverMarker.id = popup.session.addMarker(hoverMarker, "ace_line-hover", "fullLine"); + } else if (hoverMarker.id) { + popup.session.removeMarker(hoverMarker.id); + hoverMarker.id = null; + } + }; + popup.setSelectOnHover(false); + popup.on("mousemove", function(e) { + if (!lastMouseEvent) { + lastMouseEvent = e; + return; + } + if (lastMouseEvent.x == e.x && lastMouseEvent.y == e.y) { + return; + } + lastMouseEvent = e; + lastMouseEvent.scrollTop = popup.renderer.scrollTop; + var row = lastMouseEvent.getDocumentPosition().row; + if (hoverMarker.start.row != row) { + if (!hoverMarker.id) + popup.setRow(row); + setHoverMarker(row); + } + }); + popup.renderer.on("beforeRender", function() { + if (lastMouseEvent && hoverMarker.start.row != -1) { + lastMouseEvent.$pos = null; + var row = lastMouseEvent.getDocumentPosition().row; + if (!hoverMarker.id) + popup.setRow(row); + setHoverMarker(row, true); + } + }); + popup.renderer.on("afterRender", function() { + var row = popup.getRow(); + var t = popup.renderer.$textLayer; + var selected = t.element.childNodes[row - t.config.firstRow]; + if (selected == t.selectedNode) + return; + if (t.selectedNode) + dom.removeCssClass(t.selectedNode, "ace_selected"); + t.selectedNode = selected; + if (selected) + dom.addCssClass(selected, "ace_selected"); + }); + var hideHoverMarker = function() { setHoverMarker(-1) }; + var setHoverMarker = function(row, suppressRedraw) { + if (row !== hoverMarker.start.row) { + hoverMarker.start.row = hoverMarker.end.row = row; + if (!suppressRedraw) + popup.session._emit("changeBackMarker"); + popup._emit("changeHoverMarker"); + } + }; + popup.getHoveredRow = function() { + return hoverMarker.start.row; + }; + + event.addListener(popup.container, "mouseout", hideHoverMarker); + popup.on("hide", hideHoverMarker); + popup.on("changeSelection", hideHoverMarker); + + popup.session.doc.getLength = function() { + return popup.data.length; + }; + popup.session.doc.getLine = function(i) { + var data = popup.data[i]; + if (typeof data == "string") + return data; + return (data && data.value) || ""; + }; + + var bgTokenizer = popup.session.bgTokenizer; + bgTokenizer.$tokenizeRow = function(row) { + var data = popup.data[row]; + var tokens = []; + if (!data) + return tokens; + if (typeof data == "string") + data = {value: data}; + if (!data.caption) + data.caption = data.value || data.name; + + var last = -1; + var flag, c; + for (var i = 0; i < data.caption.length; i++) { + c = data.caption[i]; + flag = data.matchMask & (1 << i) ? 1 : 0; + if (last !== flag) { + tokens.push({type: data.className || "" + ( flag ? "completion-highlight" : ""), value: c}); + last = flag; + } else { + tokens[tokens.length - 1].value += c; + } + } + + if (data.meta) { + var maxW = popup.renderer.$size.scrollerWidth / popup.renderer.layerConfig.characterWidth; + var metaData = data.meta; + if (metaData.length + data.caption.length > maxW - 2) { + metaData = metaData.substr(0, maxW - data.caption.length - 3) + "\u2026" + } + tokens.push({type: "rightAlignedText", value: metaData}); + } + return tokens; + }; + bgTokenizer.$updateOnChange = noop; + bgTokenizer.start = noop; + + popup.session.$computeWidth = function() { + return this.screenWidth = 0; + }; + + popup.$blockScrolling = Infinity; + popup.isOpen = false; + popup.isTopdown = false; + + popup.data = []; + popup.setData = function(list) { + popup.data = list || []; + popup.setValue(lang.stringRepeat("\n", list.length), -1); + popup.setRow(0); + }; + popup.getData = function(row) { + return popup.data[row]; + }; + + popup.getRow = function() { + return selectionMarker.start.row; + }; + popup.setRow = function(line) { + line = Math.max(-1, Math.min(this.data.length, line)); + if (selectionMarker.start.row != line) { + popup.selection.clearSelection(); + selectionMarker.start.row = selectionMarker.end.row = line || 0; + popup.session._emit("changeBackMarker"); + popup.moveCursorTo(line || 0, 0); + if (popup.isOpen) + popup._signal("select"); + } + }; + + popup.on("changeSelection", function() { + if (popup.isOpen) + popup.setRow(popup.selection.lead.row); + popup.renderer.scrollCursorIntoView(); + }); + + popup.hide = function() { + this.container.style.display = "none"; + this._signal("hide"); + popup.isOpen = false; + }; + popup.show = function(pos, lineHeight, topdownOnly) { + var el = this.container; + var screenHeight = window.innerHeight; + var screenWidth = window.innerWidth; + var renderer = this.renderer; + var maxH = renderer.$maxLines * lineHeight * 1.4; + var top = pos.top + this.$borderSize; + if (top + maxH > screenHeight - lineHeight && !topdownOnly) { + el.style.top = ""; + el.style.bottom = screenHeight - top + "px"; + popup.isTopdown = false; + } else { + top += lineHeight; + el.style.top = top + "px"; + el.style.bottom = ""; + popup.isTopdown = true; + } + + el.style.display = ""; + this.renderer.$textLayer.checkForSizeChanges(); + + var left = pos.left; + if (left + el.offsetWidth > screenWidth) + left = screenWidth - el.offsetWidth; + + el.style.left = left + "px"; + + this._signal("show"); + lastMouseEvent = null; + popup.isOpen = true; + }; + + popup.getTextLeftOffset = function() { + return this.$borderSize + this.renderer.$padding + this.$imageSize; + }; + + popup.$imageSize = 0; + popup.$borderSize = 1; + + return popup; +}; + +dom.importCssString("\ +.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\ + background-color: #CAD6FA;\ + z-index: 1;\ +}\ +.ace_editor.ace_autocomplete .ace_line-hover {\ + border: 1px solid #abbffe;\ + margin-top: -1px;\ + background: rgba(233,233,253,0.4);\ +}\ +.ace_editor.ace_autocomplete .ace_line-hover {\ + position: absolute;\ + z-index: 2;\ +}\ +.ace_editor.ace_autocomplete .ace_scroller {\ + background: none;\ + border: none;\ + box-shadow: none;\ +}\ +.ace_rightAlignedText {\ + color: gray;\ + display: inline-block;\ + position: absolute;\ + right: 4px;\ + text-align: right;\ + z-index: -1;\ +}\ +.ace_editor.ace_autocomplete .ace_completion-highlight{\ + color: #000;\ + text-shadow: 0 0 0.01em;\ +}\ +.ace_editor.ace_autocomplete {\ + width: 280px;\ + z-index: 200000;\ + background: #fbfbfb;\ + color: #444;\ + border: 1px lightgray solid;\ + position: fixed;\ + box-shadow: 2px 3px 5px rgba(0,0,0,.2);\ + line-height: 1.4;\ +}"); + +exports.AcePopup = AcePopup; + +}); + +define("ace/autocomplete/util",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.parForEach = function(array, fn, callback) { + var completed = 0; + var arLength = array.length; + if (arLength === 0) + callback(); + for (var i = 0; i < arLength; i++) { + fn(array[i], function(result, err) { + completed++; + if (completed === arLength) + callback(result, err); + }); + } +}; + +var ID_REGEX = /[a-zA-Z_0-9\$\-\u00A2-\uFFFF]/; + +exports.retrievePrecedingIdentifier = function(text, pos, regex) { + regex = regex || ID_REGEX; + var buf = []; + for (var i = pos-1; i >= 0; i--) { + if (regex.test(text[i])) + buf.push(text[i]); + else + break; + } + return buf.reverse().join(""); +}; + +exports.retrieveFollowingIdentifier = function(text, pos, regex) { + regex = regex || ID_REGEX; + var buf = []; + for (var i = pos; i < text.length; i++) { + if (regex.test(text[i])) + buf.push(text[i]); + else + break; + } + return buf; +}; + +}); + +define("ace/autocomplete",["require","exports","module","ace/keyboard/hash_handler","ace/autocomplete/popup","ace/autocomplete/util","ace/lib/event","ace/lib/lang","ace/lib/dom","ace/snippets"], function(require, exports, module) { +"use strict"; + +var HashHandler = require("./keyboard/hash_handler").HashHandler; +var AcePopup = require("./autocomplete/popup").AcePopup; +var util = require("./autocomplete/util"); +var event = require("./lib/event"); +var lang = require("./lib/lang"); +var dom = require("./lib/dom"); +var snippetManager = require("./snippets").snippetManager; + +var Autocomplete = function() { + this.autoInsert = false; + this.autoSelect = true; + this.exactMatch = false; + this.gatherCompletionsId = 0; + this.keyboardHandler = new HashHandler(); + this.keyboardHandler.bindKeys(this.commands); + + this.blurListener = this.blurListener.bind(this); + this.changeListener = this.changeListener.bind(this); + this.mousedownListener = this.mousedownListener.bind(this); + this.mousewheelListener = this.mousewheelListener.bind(this); + + this.changeTimer = lang.delayedCall(function() { + this.updateCompletions(true); + }.bind(this)); + + this.tooltipTimer = lang.delayedCall(this.updateDocTooltip.bind(this), 50); +}; + +(function() { + + this.$init = function() { + this.popup = new AcePopup(document.body || document.documentElement); + this.popup.on("click", function(e) { + this.insertMatch(); + e.stop(); + }.bind(this)); + this.popup.focus = this.editor.focus.bind(this.editor); + this.popup.on("show", this.tooltipTimer.bind(null, null)); + this.popup.on("select", this.tooltipTimer.bind(null, null)); + this.popup.on("changeHoverMarker", this.tooltipTimer.bind(null, null)); + return this.popup; + }; + + this.getPopup = function() { + return this.popup || this.$init(); + }; + + this.openPopup = function(editor, prefix, keepPopupPosition) { + if (!this.popup) + this.$init(); + + this.popup.setData(this.completions.filtered); + + editor.keyBinding.addKeyboardHandler(this.keyboardHandler); + + var renderer = editor.renderer; + this.popup.setRow(this.autoSelect ? 0 : -1); + if (!keepPopupPosition) { + this.popup.setTheme(editor.getTheme()); + this.popup.setFontSize(editor.getFontSize()); + + var lineHeight = renderer.layerConfig.lineHeight; + + var pos = renderer.$cursorLayer.getPixelPosition(this.base, true); + pos.left -= this.popup.getTextLeftOffset(); + + var rect = editor.container.getBoundingClientRect(); + pos.top += rect.top - renderer.layerConfig.offset; + pos.left += rect.left - editor.renderer.scrollLeft; + pos.left += renderer.$gutterLayer.gutterWidth; + + this.popup.show(pos, lineHeight); + } else if (keepPopupPosition && !prefix) { + this.detach(); + } + }; + + this.detach = function() { + this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler); + this.editor.off("changeSelection", this.changeListener); + this.editor.off("blur", this.blurListener); + this.editor.off("mousedown", this.mousedownListener); + this.editor.off("mousewheel", this.mousewheelListener); + this.changeTimer.cancel(); + this.hideDocTooltip(); + + this.gatherCompletionsId += 1; + if (this.popup && this.popup.isOpen) + this.popup.hide(); + + if (this.base) + this.base.detach(); + this.activated = false; + this.completions = this.base = null; + }; + + this.changeListener = function(e) { + var cursor = this.editor.selection.lead; + if (cursor.row != this.base.row || cursor.column < this.base.column) { + this.detach(); + } + if (this.activated) + this.changeTimer.schedule(); + else + this.detach(); + }; + + this.blurListener = function(e) { + var el = document.activeElement; + var text = this.editor.textInput.getElement() + if (el != text && el.parentNode != this.popup.container + && el != this.tooltipNode && e.relatedTarget != this.tooltipNode + && e.relatedTarget != text + ) { + this.detach(); + } + }; + + this.mousedownListener = function(e) { + this.detach(); + }; + + this.mousewheelListener = function(e) { + this.detach(); + }; + + this.goTo = function(where) { + var row = this.popup.getRow(); + var max = this.popup.session.getLength() - 1; + + switch(where) { + case "up": row = row <= 0 ? max : row - 1; break; + case "down": row = row >= max ? -1 : row + 1; break; + case "start": row = 0; break; + case "end": row = max; break; + } + + this.popup.setRow(row); + }; + + this.insertMatch = function(data) { + if (!data) + data = this.popup.getData(this.popup.getRow()); + if (!data) + return false; + + if (data.completer && data.completer.insertMatch) { + data.completer.insertMatch(this.editor, data); + } else { + if (this.completions.filterText) { + var ranges = this.editor.selection.getAllRanges(); + for (var i = 0, range; range = ranges[i]; i++) { + range.start.column -= this.completions.filterText.length; + this.editor.session.remove(range); + } + } + if (data.snippet) + snippetManager.insertSnippet(this.editor, data.snippet); + else + this.editor.execCommand("insertstring", data.value || data); + } + this.detach(); + }; + + + this.commands = { + "Up": function(editor) { editor.completer.goTo("up"); }, + "Down": function(editor) { editor.completer.goTo("down"); }, + "Ctrl-Up|Ctrl-Home": function(editor) { editor.completer.goTo("start"); }, + "Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); }, + + "Esc": function(editor) { editor.completer.detach(); }, + "Space": function(editor) { editor.completer.detach(); editor.insert(" ");}, + "Return": function(editor) { return editor.completer.insertMatch(); }, + "Shift-Return": function(editor) { editor.completer.insertMatch(true); }, + "Tab": function(editor) { + var result = editor.completer.insertMatch(); + if (!result && !editor.tabstopManager) + editor.completer.goTo("down"); + else + return result; + }, + + "PageUp": function(editor) { editor.completer.popup.gotoPageUp(); }, + "PageDown": function(editor) { editor.completer.popup.gotoPageDown(); } + }; + + this.gatherCompletions = function(editor, callback) { + var session = editor.getSession(); + var pos = editor.getCursorPosition(); + + var line = session.getLine(pos.row); + var prefix = util.retrievePrecedingIdentifier(line, pos.column); + + this.base = session.doc.createAnchor(pos.row, pos.column - prefix.length); + this.base.$insertRight = true; + + var matches = []; + var total = editor.completers.length; + editor.completers.forEach(function(completer, i) { + completer.getCompletions(editor, session, pos, prefix, function(err, results) { + if (!err) + matches = matches.concat(results); + var pos = editor.getCursorPosition(); + var line = session.getLine(pos.row); + callback(null, { + prefix: util.retrievePrecedingIdentifier(line, pos.column, results[0] && results[0].identifierRegex), + matches: matches, + finished: (--total === 0) + }); + }); + }); + return true; + }; + + this.showPopup = function(editor) { + if (this.editor) + this.detach(); + + this.activated = true; + + this.editor = editor; + if (editor.completer != this) { + if (editor.completer) + editor.completer.detach(); + editor.completer = this; + } + + editor.on("changeSelection", this.changeListener); + editor.on("blur", this.blurListener); + editor.on("mousedown", this.mousedownListener); + editor.on("mousewheel", this.mousewheelListener); + + this.updateCompletions(); + }; + + this.updateCompletions = function(keepPopupPosition) { + if (keepPopupPosition && this.base && this.completions) { + var pos = this.editor.getCursorPosition(); + var prefix = this.editor.session.getTextRange({start: this.base, end: pos}); + if (prefix == this.completions.filterText) + return; + this.completions.setFilter(prefix); + if (!this.completions.filtered.length) + return this.detach(); + if (this.completions.filtered.length == 1 + && this.completions.filtered[0].value == prefix + && !this.completions.filtered[0].snippet) + return this.detach(); + this.openPopup(this.editor, prefix, keepPopupPosition); + return; + } + var _id = this.gatherCompletionsId; + this.gatherCompletions(this.editor, function(err, results) { + var detachIfFinished = function() { + if (!results.finished) return; + return this.detach(); + }.bind(this); + + var prefix = results.prefix; + var matches = results && results.matches; + + if (!matches || !matches.length) + return detachIfFinished(); + if (prefix.indexOf(results.prefix) !== 0 || _id != this.gatherCompletionsId) + return; + + this.completions = new FilteredList(matches); + + if (this.exactMatch) + this.completions.exactMatch = true; + + this.completions.setFilter(prefix); + var filtered = this.completions.filtered; + if (!filtered.length) + return detachIfFinished(); + if (filtered.length == 1 && filtered[0].value == prefix && !filtered[0].snippet) + return detachIfFinished(); + if (this.autoInsert && filtered.length == 1 && results.finished) + return this.insertMatch(filtered[0]); + + this.openPopup(this.editor, prefix, keepPopupPosition); + }.bind(this)); + }; + + this.cancelContextMenu = function() { + this.editor.$mouseHandler.cancelContextMenu(); + }; + + this.updateDocTooltip = function() { + var popup = this.popup; + var all = popup.data; + var selected = all && (all[popup.getHoveredRow()] || all[popup.getRow()]); + var doc = null; + if (!selected || !this.editor || !this.popup.isOpen) + return this.hideDocTooltip(); + this.editor.completers.some(function(completer) { + if (completer.getDocTooltip) + doc = completer.getDocTooltip(selected); + return doc; + }); + if (!doc) + doc = selected; + + if (typeof doc == "string") + doc = {docText: doc} + if (!doc || !(doc.docHTML || doc.docText)) + return this.hideDocTooltip(); + this.showDocTooltip(doc); + }; + + this.showDocTooltip = function(item) { + if (!this.tooltipNode) { + this.tooltipNode = dom.createElement("div"); + this.tooltipNode.className = "ace_tooltip ace_doc-tooltip"; + this.tooltipNode.style.margin = 0; + this.tooltipNode.style.pointerEvents = "auto"; + this.tooltipNode.tabIndex = -1; + this.tooltipNode.onblur = this.blurListener.bind(this); + } + + var tooltipNode = this.tooltipNode; + if (item.docHTML) { + tooltipNode.innerHTML = item.docHTML; + } else if (item.docText) { + tooltipNode.textContent = item.docText; + } + + if (!tooltipNode.parentNode) + document.body.appendChild(tooltipNode); + var popup = this.popup; + var rect = popup.container.getBoundingClientRect(); + tooltipNode.style.top = popup.container.style.top; + tooltipNode.style.bottom = popup.container.style.bottom; + + if (window.innerWidth - rect.right < 320) { + tooltipNode.style.right = window.innerWidth - rect.left + "px"; + tooltipNode.style.left = ""; + } else { + tooltipNode.style.left = (rect.right + 1) + "px"; + tooltipNode.style.right = ""; + } + tooltipNode.style.display = "block"; + }; + + this.hideDocTooltip = function() { + this.tooltipTimer.cancel(); + if (!this.tooltipNode) return; + var el = this.tooltipNode; + if (!this.editor.isFocused() && document.activeElement == el) + this.editor.focus(); + this.tooltipNode = null; + if (el.parentNode) + el.parentNode.removeChild(el); + }; + +}).call(Autocomplete.prototype); + +Autocomplete.startCommand = { + name: "startAutocomplete", + exec: function(editor) { + if (!editor.completer) + editor.completer = new Autocomplete(); + editor.completer.autoInsert = false; + editor.completer.autoSelect = true; + editor.completer.showPopup(editor); + editor.completer.cancelContextMenu(); + }, + bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space" +}; + +var FilteredList = function(array, filterText, mutateData) { + this.all = array; + this.filtered = array; + this.filterText = filterText || ""; + this.exactMatch = false; +}; +(function(){ + this.setFilter = function(str) { + if (str.length > this.filterText && str.lastIndexOf(this.filterText, 0) === 0) + var matches = this.filtered; + else + var matches = this.all; + + this.filterText = str; + matches = this.filterCompletions(matches, this.filterText); + matches = matches.sort(function(a, b) { + return b.exactMatch - a.exactMatch || b.score - a.score; + }); + var prev = null; + matches = matches.filter(function(item){ + var caption = item.snippet || item.caption || item.value; + if (caption === prev) return false; + prev = caption; + return true; + }); + + this.filtered = matches; + }; + this.filterCompletions = function(items, needle) { + var results = []; + var upper = needle.toUpperCase(); + var lower = needle.toLowerCase(); + loop: for (var i = 0, item; item = items[i]; i++) { + var caption = item.value || item.caption || item.snippet; + if (!caption) continue; + var lastIndex = -1; + var matchMask = 0; + var penalty = 0; + var index, distance; + + if (this.exactMatch) { + if (needle !== caption.substr(0, needle.length)) + continue loop; + }else{ + for (var j = 0; j < needle.length; j++) { + var i1 = caption.indexOf(lower[j], lastIndex + 1); + var i2 = caption.indexOf(upper[j], lastIndex + 1); + index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2; + if (index < 0) + continue loop; + distance = index - lastIndex - 1; + if (distance > 0) { + if (lastIndex === -1) + penalty += 10; + penalty += distance; + } + matchMask = matchMask | (1 << index); + lastIndex = index; + } + } + item.matchMask = matchMask; + item.exactMatch = penalty ? 0 : 1; + item.score = (item.score || 0) - penalty; + results.push(item); + } + return results; + }; +}).call(FilteredList.prototype); + +exports.Autocomplete = Autocomplete; +exports.FilteredList = FilteredList; + +}); + +define("ace/autocomplete/text_completer",["require","exports","module","ace/range"], function(require, exports, module) { + var Range = require("../range").Range; + + var splitRegex = /[^a-zA-Z_0-9\$\-\u00C0-\u1FFF\u2C00-\uD7FF\w]+/; + + function getWordIndex(doc, pos) { + var textBefore = doc.getTextRange(Range.fromPoints({row: 0, column:0}, pos)); + return textBefore.split(splitRegex).length - 1; + } + function wordDistance(doc, pos) { + var prefixPos = getWordIndex(doc, pos); + var words = doc.getValue().split(splitRegex); + var wordScores = Object.create(null); + + var currentWord = words[prefixPos]; + + words.forEach(function(word, idx) { + if (!word || word === currentWord) return; + + var distance = Math.abs(prefixPos - idx); + var score = words.length - distance; + if (wordScores[word]) { + wordScores[word] = Math.max(score, wordScores[word]); + } else { + wordScores[word] = score; + } + }); + return wordScores; + } + + exports.getCompletions = function(editor, session, pos, prefix, callback) { + var wordScore = wordDistance(session, pos, prefix); + var wordList = Object.keys(wordScore); + callback(null, wordList.map(function(word) { + return { + caption: word, + value: word, + score: wordScore[word], + meta: "local" + }; + })); + }; +}); + +define("ace/ext/language_tools",["require","exports","module","ace/snippets","ace/autocomplete","ace/config","ace/lib/lang","ace/autocomplete/util","ace/autocomplete/text_completer","ace/editor","ace/config"], function(require, exports, module) { +"use strict"; + +var snippetManager = require("../snippets").snippetManager; +var Autocomplete = require("../autocomplete").Autocomplete; +var config = require("../config"); +var lang = require("../lib/lang"); +var util = require("../autocomplete/util"); + +var textCompleter = require("../autocomplete/text_completer"); +var keyWordCompleter = { + getCompletions: function(editor, session, pos, prefix, callback) { + if (session.$mode.completer) { + return session.$mode.completer.getCompletions(editor, session, pos, prefix, callback); + } + var state = editor.session.getState(pos.row); + var completions = session.$mode.getCompletions(state, session, pos, prefix); + callback(null, completions); + } +}; + +var snippetCompleter = { + getCompletions: function(editor, session, pos, prefix, callback) { + var snippetMap = snippetManager.snippetMap; + var completions = []; + snippetManager.getActiveScopes(editor).forEach(function(scope) { + var snippets = snippetMap[scope] || []; + for (var i = snippets.length; i--;) { + var s = snippets[i]; + var caption = s.name || s.tabTrigger; + if (!caption) + continue; + completions.push({ + caption: caption, + snippet: s.content, + meta: s.tabTrigger && !s.name ? s.tabTrigger + "\u21E5 " : "snippet", + type: "snippet" + }); + } + }, this); + callback(null, completions); + }, + getDocTooltip: function(item) { + if (item.type == "snippet" && !item.docHTML) { + item.docHTML = [ + "", lang.escapeHTML(item.caption), "", "
", + lang.escapeHTML(item.snippet) + ].join(""); + } + } +}; + +var completers = [snippetCompleter, textCompleter, keyWordCompleter]; +exports.setCompleters = function(val) { + completers = val || []; +}; +exports.addCompleter = function(completer) { + completers.push(completer); +}; +exports.textCompleter = textCompleter; +exports.keyWordCompleter = keyWordCompleter; +exports.snippetCompleter = snippetCompleter; + +var expandSnippet = { + name: "expandSnippet", + exec: function(editor) { + return snippetManager.expandWithTab(editor); + }, + bindKey: "Tab" +}; + +var onChangeMode = function(e, editor) { + loadSnippetsForMode(editor.session.$mode); +}; + +var loadSnippetsForMode = function(mode) { + var id = mode.$id; + if (!snippetManager.files) + snippetManager.files = {}; + loadSnippetFile(id); + if (mode.modes) + mode.modes.forEach(loadSnippetsForMode); +}; + +var loadSnippetFile = function(id) { + if (!id || snippetManager.files[id]) + return; + var snippetFilePath = id.replace("mode", "snippets"); + snippetManager.files[id] = {}; + config.loadModule(snippetFilePath, function(m) { + if (m) { + snippetManager.files[id] = m; + if (!m.snippets && m.snippetText) + m.snippets = snippetManager.parseSnippetFile(m.snippetText); + snippetManager.register(m.snippets || [], m.scope); + if (m.includeScopes) { + snippetManager.snippetMap[m.scope].includeScopes = m.includeScopes; + m.includeScopes.forEach(function(x) { + loadSnippetFile("ace/mode/" + x); + }); + } + } + }); +}; + +function getCompletionPrefix(editor) { + var pos = editor.getCursorPosition(); + var line = editor.session.getLine(pos.row); + var prefix; + editor.completers.forEach(function(completer) { + if (completer.identifierRegexps) { + completer.identifierRegexps.forEach(function(identifierRegex) { + if (!prefix && identifierRegex) + prefix = util.retrievePrecedingIdentifier(line, pos.column, identifierRegex); + }); + } + }); + return prefix || util.retrievePrecedingIdentifier(line, pos.column); +} + +var doLiveAutocomplete = function(e) { + var editor = e.editor; + var text = e.args || ""; + var hasCompleter = editor.completer && editor.completer.activated; + if (e.command.name === "backspace") { + if (hasCompleter && !getCompletionPrefix(editor)) + editor.completer.detach(); + } + else if (e.command.name === "insertstring") { + var prefix = getCompletionPrefix(editor); + if (prefix && !hasCompleter) { + if (!editor.completer) { + editor.completer = new Autocomplete(); + } + editor.completer.autoInsert = false; + editor.completer.showPopup(editor); + } + } +}; + +var Editor = require("../editor").Editor; +require("../config").defineOptions(Editor.prototype, "editor", { + enableBasicAutocompletion: { + set: function(val) { + if (val) { + if (!this.completers) + this.completers = Array.isArray(val)? val: completers; + this.commands.addCommand(Autocomplete.startCommand); + } else { + this.commands.removeCommand(Autocomplete.startCommand); + } + }, + value: false + }, + enableLiveAutocompletion: { + set: function(val) { + if (val) { + if (!this.completers) + this.completers = Array.isArray(val)? val: completers; + this.commands.on('afterExec', doLiveAutocomplete); + } else { + this.commands.removeListener('afterExec', doLiveAutocomplete); + } + }, + value: false + }, + enableSnippets: { + set: function(val) { + if (val) { + this.commands.addCommand(expandSnippet); + this.on("changeMode", onChangeMode); + onChangeMode(null, this); + } else { + this.commands.removeCommand(expandSnippet); + this.off("changeMode", onChangeMode); + } + }, + value: false + } +}); +}); + (function() { + window.require(["ace/ext/language_tools"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-linking.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-linking.js new file mode 100644 index 00000000..e004d6b7 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-linking.js @@ -0,0 +1,52 @@ +define("ace/ext/linking",["require","exports","module","ace/editor","ace/config"], function(require, exports, module) { + +var Editor = require("ace/editor").Editor; + +require("../config").defineOptions(Editor.prototype, "editor", { + enableLinking: { + set: function(val) { + if (val) { + this.on("click", onClick); + this.on("mousemove", onMouseMove); + } else { + this.off("click", onClick); + this.off("mousemove", onMouseMove); + } + }, + value: false + } +}) + +function onMouseMove(e) { + var editor = e.editor; + var ctrl = e.getAccelKey(); + + if (ctrl) { + var editor = e.editor; + var docPos = e.getDocumentPosition(); + var session = editor.session; + var token = session.getTokenAt(docPos.row, docPos.column); + + editor._emit("linkHover", {position: docPos, token: token}); + } +} + +function onClick(e) { + var ctrl = e.getAccelKey(); + var button = e.getButton(); + + if (button == 0 && ctrl) { + var editor = e.editor; + var docPos = e.getDocumentPosition(); + var session = editor.session; + var token = session.getTokenAt(docPos.row, docPos.column); + + editor._emit("linkClick", {position: docPos, token: token}); + } +} + +}); + (function() { + window.require(["ace/ext/linking"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-modelist.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-modelist.js new file mode 100644 index 00000000..27681ba5 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-modelist.js @@ -0,0 +1,190 @@ +define("ace/ext/modelist",["require","exports","module"], function(require, exports, module) { +"use strict"; + +var modes = []; +function getModeForPath(path) { + var mode = modesByName.text; + var fileName = path.split(/[\/\\]/).pop(); + for (var i = 0; i < modes.length; i++) { + if (modes[i].supportsFile(fileName)) { + mode = modes[i]; + break; + } + } + return mode; +} + +var Mode = function(name, caption, extensions) { + this.name = name; + this.caption = caption; + this.mode = "ace/mode/" + name; + this.extensions = extensions; + if (/\^/.test(extensions)) { + var re = extensions.replace(/\|(\^)?/g, function(a, b){ + return "$|" + (b ? "^" : "^.*\\."); + }) + "$"; + } else { + var re = "^.*\\.(" + extensions + ")$"; + } + + this.extRe = new RegExp(re, "gi"); +}; + +Mode.prototype.supportsFile = function(filename) { + return filename.match(this.extRe); +}; +var supportedModes = { + ABAP: ["abap"], + ABC: ["abc"], + ActionScript:["as"], + ADA: ["ada|adb"], + Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"], + AsciiDoc: ["asciidoc"], + Assembly_x86:["asm"], + AutoHotKey: ["ahk"], + BatchFile: ["bat|cmd"], + C9Search: ["c9search_results"], + C_Cpp: ["cpp|c|cc|cxx|h|hh|hpp"], + Cirru: ["cirru|cr"], + Clojure: ["clj|cljs"], + Cobol: ["CBL|COB"], + coffee: ["coffee|cf|cson|^Cakefile"], + ColdFusion: ["cfm"], + CSharp: ["cs"], + CSS: ["css"], + Curly: ["curly"], + D: ["d|di"], + Dart: ["dart"], + Diff: ["diff|patch"], + Dockerfile: ["^Dockerfile"], + Dot: ["dot"], + Dummy: ["dummy"], + DummySyntax: ["dummy"], + Eiffel: ["e"], + EJS: ["ejs"], + Elixir: ["ex|exs"], + Elm: ["elm"], + Erlang: ["erl|hrl"], + Forth: ["frt|fs|ldr"], + FTL: ["ftl"], + Gcode: ["gcode"], + Gherkin: ["feature"], + Gitignore: ["^.gitignore"], + Glsl: ["glsl|frag|vert"], + golang: ["go"], + Groovy: ["groovy"], + HAML: ["haml"], + Handlebars: ["hbs|handlebars|tpl|mustache"], + Haskell: ["hs"], + haXe: ["hx"], + HTML: ["html|htm|xhtml"], + HTML_Ruby: ["erb|rhtml|html.erb"], + INI: ["ini|conf|cfg|prefs"], + Io: ["io"], + Jack: ["jack"], + Jade: ["jade"], + Java: ["java"], + JavaScript: ["js|jsm"], + JSON: ["json"], + JSONiq: ["jq"], + JSP: ["jsp"], + JSX: ["jsx"], + Julia: ["jl"], + LaTeX: ["tex|latex|ltx|bib"], + Lean: ["lean|hlean"], + LESS: ["less"], + Liquid: ["liquid"], + Lisp: ["lisp"], + LiveScript: ["ls"], + LogiQL: ["logic|lql"], + LSL: ["lsl"], + Lua: ["lua"], + LuaPage: ["lp"], + Lucene: ["lucene"], + Makefile: ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"], + Markdown: ["md|markdown"], + Mask: ["mask"], + MATLAB: ["matlab"], + MEL: ["mel"], + MUSHCode: ["mc|mush"], + MySQL: ["mysql"], + Nix: ["nix"], + ObjectiveC: ["m|mm"], + OCaml: ["ml|mli"], + Pascal: ["pas|p"], + Perl: ["pl|pm"], + pgSQL: ["pgsql"], + PHP: ["php|phtml"], + Powershell: ["ps1"], + Praat: ["praat|praatscript|psc|proc"], + Prolog: ["plg|prolog"], + Properties: ["properties"], + Protobuf: ["proto"], + Python: ["py"], + R: ["r"], + RDoc: ["Rd"], + RHTML: ["Rhtml"], + Ruby: ["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"], + Rust: ["rs"], + SASS: ["sass"], + SCAD: ["scad"], + Scala: ["scala"], + Scheme: ["scm|rkt"], + SCSS: ["scss"], + SH: ["sh|bash|^.bashrc"], + SJS: ["sjs"], + Smarty: ["smarty|tpl"], + snippets: ["snippets"], + Soy_Template:["soy"], + Space: ["space"], + SQL: ["sql"], + Stylus: ["styl|stylus"], + SVG: ["svg"], + Tcl: ["tcl"], + Tex: ["tex"], + Text: ["txt"], + Textile: ["textile"], + Toml: ["toml"], + Twig: ["twig"], + Typescript: ["ts|typescript|str"], + Vala: ["vala"], + VBScript: ["vbs|vb"], + Velocity: ["vm"], + Verilog: ["v|vh|sv|svh"], + VHDL: ["vhd|vhdl"], + XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"], + XQuery: ["xq"], + YAML: ["yaml|yml"], + Django: ["html"] +}; + +var nameOverrides = { + ObjectiveC: "Objective-C", + CSharp: "C#", + golang: "Go", + C_Cpp: "C and C++", + coffee: "CoffeeScript", + HTML_Ruby: "HTML (Ruby)", + FTL: "FreeMarker" +}; +var modesByName = {}; +for (var name in supportedModes) { + var data = supportedModes[name]; + var displayName = (nameOverrides[name] || name).replace(/_/g, " "); + var filename = name.toLowerCase(); + var mode = new Mode(filename, displayName, data[0]); + modesByName[filename] = mode; + modes.push(mode); +} + +module.exports = { + getModeForPath: getModeForPath, + modes: modes, + modesByName: modesByName +}; + +}); + (function() { + window.require(["ace/ext/modelist"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-old_ie.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-old_ie.js new file mode 100644 index 00000000..0e33b712 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-old_ie.js @@ -0,0 +1,494 @@ +define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"], function(require, exports, module) { +"use strict"; + +var dom = require("../lib/dom"); +var lang = require("../lib/lang"); +var event = require("../lib/event"); +var searchboxCss = "\ +.ace_search {\ +background-color: #ddd;\ +border: 1px solid #cbcbcb;\ +border-top: 0 none;\ +max-width: 325px;\ +overflow: hidden;\ +margin: 0;\ +padding: 4px;\ +padding-right: 6px;\ +padding-bottom: 0;\ +position: absolute;\ +top: 0px;\ +z-index: 99;\ +white-space: normal;\ +}\ +.ace_search.left {\ +border-left: 0 none;\ +border-radius: 0px 0px 5px 0px;\ +left: 0;\ +}\ +.ace_search.right {\ +border-radius: 0px 0px 0px 5px;\ +border-right: 0 none;\ +right: 0;\ +}\ +.ace_search_form, .ace_replace_form {\ +border-radius: 3px;\ +border: 1px solid #cbcbcb;\ +float: left;\ +margin-bottom: 4px;\ +overflow: hidden;\ +}\ +.ace_search_form.ace_nomatch {\ +outline: 1px solid red;\ +}\ +.ace_search_field {\ +background-color: white;\ +border-right: 1px solid #cbcbcb;\ +border: 0 none;\ +-webkit-box-sizing: border-box;\ +-moz-box-sizing: border-box;\ +box-sizing: border-box;\ +float: left;\ +height: 22px;\ +outline: 0;\ +padding: 0 7px;\ +width: 214px;\ +margin: 0;\ +}\ +.ace_searchbtn,\ +.ace_replacebtn {\ +background: #fff;\ +border: 0 none;\ +border-left: 1px solid #dcdcdc;\ +cursor: pointer;\ +float: left;\ +height: 22px;\ +margin: 0;\ +padding: 0;\ +position: relative;\ +}\ +.ace_searchbtn:last-child,\ +.ace_replacebtn:last-child {\ +border-top-right-radius: 3px;\ +border-bottom-right-radius: 3px;\ +}\ +.ace_searchbtn:disabled {\ +background: none;\ +cursor: default;\ +}\ +.ace_searchbtn {\ +background-position: 50% 50%;\ +background-repeat: no-repeat;\ +width: 27px;\ +}\ +.ace_searchbtn.prev {\ +background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); \ +}\ +.ace_searchbtn.next {\ +background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); \ +}\ +.ace_searchbtn_close {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;\ +border-radius: 50%;\ +border: 0 none;\ +color: #656565;\ +cursor: pointer;\ +float: right;\ +font: 16px/16px Arial;\ +height: 14px;\ +margin: 5px 1px 9px 5px;\ +padding: 0;\ +text-align: center;\ +width: 14px;\ +}\ +.ace_searchbtn_close:hover {\ +background-color: #656565;\ +background-position: 50% 100%;\ +color: white;\ +}\ +.ace_replacebtn.prev {\ +width: 54px\ +}\ +.ace_replacebtn.next {\ +width: 27px\ +}\ +.ace_button {\ +margin-left: 2px;\ +cursor: pointer;\ +-webkit-user-select: none;\ +-moz-user-select: none;\ +-o-user-select: none;\ +-ms-user-select: none;\ +user-select: none;\ +overflow: hidden;\ +opacity: 0.7;\ +border: 1px solid rgba(100,100,100,0.23);\ +padding: 1px;\ +-moz-box-sizing: border-box;\ +box-sizing: border-box;\ +color: black;\ +}\ +.ace_button:hover {\ +background-color: #eee;\ +opacity:1;\ +}\ +.ace_button:active {\ +background-color: #ddd;\ +}\ +.ace_button.checked {\ +border-color: #3399ff;\ +opacity:1;\ +}\ +.ace_search_options{\ +margin-bottom: 3px;\ +text-align: right;\ +-webkit-user-select: none;\ +-moz-user-select: none;\ +-o-user-select: none;\ +-ms-user-select: none;\ +user-select: none;\ +}"; +var HashHandler = require("../keyboard/hash_handler").HashHandler; +var keyUtil = require("../lib/keys"); + +dom.importCssString(searchboxCss, "ace_searchbox"); + +var html = ''.replace(/>\s+/g, ">"); + +var SearchBox = function(editor, range, showReplaceForm) { + var div = dom.createElement("div"); + div.innerHTML = html; + this.element = div.firstChild; + + this.$init(); + this.setEditor(editor); +}; + +(function() { + this.setEditor = function(editor) { + editor.searchBox = this; + editor.container.appendChild(this.element); + this.editor = editor; + }; + + this.$initElements = function(sb) { + this.searchBox = sb.querySelector(".ace_search_form"); + this.replaceBox = sb.querySelector(".ace_replace_form"); + this.searchOptions = sb.querySelector(".ace_search_options"); + this.regExpOption = sb.querySelector("[action=toggleRegexpMode]"); + this.caseSensitiveOption = sb.querySelector("[action=toggleCaseSensitive]"); + this.wholeWordOption = sb.querySelector("[action=toggleWholeWords]"); + this.searchInput = this.searchBox.querySelector(".ace_search_field"); + this.replaceInput = this.replaceBox.querySelector(".ace_search_field"); + }; + + this.$init = function() { + var sb = this.element; + + this.$initElements(sb); + + var _this = this; + event.addListener(sb, "mousedown", function(e) { + setTimeout(function(){ + _this.activeInput.focus(); + }, 0); + event.stopPropagation(e); + }); + event.addListener(sb, "click", function(e) { + var t = e.target || e.srcElement; + var action = t.getAttribute("action"); + if (action && _this[action]) + _this[action](); + else if (_this.$searchBarKb.commands[action]) + _this.$searchBarKb.commands[action].exec(_this); + event.stopPropagation(e); + }); + + event.addCommandKeyListener(sb, function(e, hashId, keyCode) { + var keyString = keyUtil.keyCodeToString(keyCode); + var command = _this.$searchBarKb.findKeyCommand(hashId, keyString); + if (command && command.exec) { + command.exec(_this); + event.stopEvent(e); + } + }); + + this.$onChange = lang.delayedCall(function() { + _this.find(false, false); + }); + + event.addListener(this.searchInput, "input", function() { + _this.$onChange.schedule(20); + }); + event.addListener(this.searchInput, "focus", function() { + _this.activeInput = _this.searchInput; + _this.searchInput.value && _this.highlight(); + }); + event.addListener(this.replaceInput, "focus", function() { + _this.activeInput = _this.replaceInput; + _this.searchInput.value && _this.highlight(); + }); + }; + this.$closeSearchBarKb = new HashHandler([{ + bindKey: "Esc", + name: "closeSearchBar", + exec: function(editor) { + editor.searchBox.hide(); + } + }]); + this.$searchBarKb = new HashHandler(); + this.$searchBarKb.bindKeys({ + "Ctrl-f|Command-f|Ctrl-H|Command-Option-F": function(sb) { + var isReplace = sb.isReplace = !sb.isReplace; + sb.replaceBox.style.display = isReplace ? "" : "none"; + sb[isReplace ? "replaceInput" : "searchInput"].focus(); + }, + "Ctrl-G|Command-G": function(sb) { + sb.findNext(); + }, + "Ctrl-Shift-G|Command-Shift-G": function(sb) { + sb.findPrev(); + }, + "esc": function(sb) { + setTimeout(function() { sb.hide();}); + }, + "Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replace(); + sb.findNext(); + }, + "Shift-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replace(); + sb.findPrev(); + }, + "Alt-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replaceAll(); + sb.findAll(); + }, + "Tab": function(sb) { + (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus(); + } + }); + + this.$searchBarKb.addCommands([{ + name: "toggleRegexpMode", + bindKey: {win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/"}, + exec: function(sb) { + sb.regExpOption.checked = !sb.regExpOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleCaseSensitive", + bindKey: {win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I"}, + exec: function(sb) { + sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleWholeWords", + bindKey: {win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W"}, + exec: function(sb) { + sb.wholeWordOption.checked = !sb.wholeWordOption.checked; + sb.$syncOptions(); + } + }]); + + this.$syncOptions = function() { + dom.setCssClass(this.regExpOption, "checked", this.regExpOption.checked); + dom.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked); + dom.setCssClass(this.caseSensitiveOption, "checked", this.caseSensitiveOption.checked); + this.find(false, false); + }; + + this.highlight = function(re) { + this.editor.session.highlight(re || this.editor.$search.$options.re); + this.editor.renderer.updateBackMarkers() + }; + this.find = function(skipCurrent, backwards) { + var range = this.editor.find(this.searchInput.value, { + skipCurrent: skipCurrent, + backwards: backwards, + wrap: true, + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + }; + this.findNext = function() { + this.find(true, false); + }; + this.findPrev = function() { + this.find(true, true); + }; + this.findAll = function(){ + var range = this.editor.findAll(this.searchInput.value, { + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + this.hide(); + }; + this.replace = function() { + if (!this.editor.getReadOnly()) + this.editor.replace(this.replaceInput.value); + }; + this.replaceAndFindNext = function() { + if (!this.editor.getReadOnly()) { + this.editor.replace(this.replaceInput.value); + this.findNext() + } + }; + this.replaceAll = function() { + if (!this.editor.getReadOnly()) + this.editor.replaceAll(this.replaceInput.value); + }; + + this.hide = function() { + this.element.style.display = "none"; + this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb); + this.editor.focus(); + }; + this.show = function(value, isReplace) { + this.element.style.display = ""; + this.replaceBox.style.display = isReplace ? "" : "none"; + + this.isReplace = isReplace; + + if (value) + this.searchInput.value = value; + this.searchInput.focus(); + this.searchInput.select(); + + this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb); + }; + + this.isFocused = function() { + var el = document.activeElement; + return el == this.searchInput || el == this.replaceInput; + } +}).call(SearchBox.prototype); + +exports.SearchBox = SearchBox; + +exports.Search = function(editor, isReplace) { + var sb = editor.searchBox || new SearchBox(editor); + sb.show(editor.session.getTextRange(), isReplace); +}; + +}); + +define("ace/ext/old_ie",["require","exports","module","ace/lib/useragent","ace/tokenizer","ace/ext/searchbox","ace/mode/text"], function(require, exports, module) { +"use strict"; +var MAX_TOKEN_COUNT = 1000; +var useragent = require("../lib/useragent"); +var TokenizerModule = require("../tokenizer"); + +function patch(obj, name, regexp, replacement) { + eval("obj['" + name + "']=" + obj[name].toString().replace( + regexp, replacement + )); +} + +if (useragent.isIE && useragent.isIE < 10 && window.top.document.compatMode === "BackCompat") + useragent.isOldIE = true; + +if (typeof document != "undefined" && !document.documentElement.querySelector) { + useragent.isOldIE = true; + var qs = function(el, selector) { + if (selector.charAt(0) == ".") { + var classNeme = selector.slice(1); + } else { + var m = selector.match(/(\w+)=(\w+)/); + var attr = m && m[1]; + var attrVal = m && m[2]; + } + for (var i = 0; i < el.all.length; i++) { + var ch = el.all[i]; + if (classNeme) { + if (ch.className.indexOf(classNeme) != -1) + return ch; + } else if (attr) { + if (ch.getAttribute(attr) == attrVal) + return ch; + } + } + }; + var sb = require("./searchbox").SearchBox.prototype; + patch( + sb, "$initElements", + /([^\s=]*).querySelector\((".*?")\)/g, + "qs($1, $2)" + ); +} + +var compliantExecNpcg = /()??/.exec("")[1] === undefined; +if (compliantExecNpcg) + return; +var proto = TokenizerModule.Tokenizer.prototype; +TokenizerModule.Tokenizer_orig = TokenizerModule.Tokenizer; +proto.getLineTokens_orig = proto.getLineTokens; + +patch( + TokenizerModule, "Tokenizer", + "ruleRegExps.push(adjustedregex);\n", + function(m) { + return m + '\ + if (state[i].next && RegExp(adjustedregex).test(""))\n\ + rule._qre = RegExp(adjustedregex, "g");\n\ + '; + } +); +TokenizerModule.Tokenizer.prototype = proto; +patch( + proto, "getLineTokens", + /if \(match\[i \+ 1\] === undefined\)\s*continue;/, + "if (!match[i + 1]) {\n\ + if (value)continue;\n\ + var qre = state[mapping[i]]._qre;\n\ + if (!qre) continue;\n\ + qre.lastIndex = lastIndex;\n\ + if (!qre.exec(line) || qre.lastIndex != lastIndex)\n\ + continue;\n\ + }" +); + +patch( + require("../mode/text").Mode.prototype, "getTokenizer", + /Tokenizer/, + "TokenizerModule.Tokenizer" +); + +useragent.isOldIE = true; + +}); + (function() { + window.require(["ace/ext/old_ie"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-searchbox.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-searchbox.js new file mode 100644 index 00000000..9f1115bf --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-searchbox.js @@ -0,0 +1,409 @@ +define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"], function(require, exports, module) { +"use strict"; + +var dom = require("../lib/dom"); +var lang = require("../lib/lang"); +var event = require("../lib/event"); +var searchboxCss = "\ +.ace_search {\ +background-color: #ddd;\ +border: 1px solid #cbcbcb;\ +border-top: 0 none;\ +max-width: 325px;\ +overflow: hidden;\ +margin: 0;\ +padding: 4px;\ +padding-right: 6px;\ +padding-bottom: 0;\ +position: absolute;\ +top: 0px;\ +z-index: 99;\ +white-space: normal;\ +}\ +.ace_search.left {\ +border-left: 0 none;\ +border-radius: 0px 0px 5px 0px;\ +left: 0;\ +}\ +.ace_search.right {\ +border-radius: 0px 0px 0px 5px;\ +border-right: 0 none;\ +right: 0;\ +}\ +.ace_search_form, .ace_replace_form {\ +border-radius: 3px;\ +border: 1px solid #cbcbcb;\ +float: left;\ +margin-bottom: 4px;\ +overflow: hidden;\ +}\ +.ace_search_form.ace_nomatch {\ +outline: 1px solid red;\ +}\ +.ace_search_field {\ +background-color: white;\ +border-right: 1px solid #cbcbcb;\ +border: 0 none;\ +-webkit-box-sizing: border-box;\ +-moz-box-sizing: border-box;\ +box-sizing: border-box;\ +float: left;\ +height: 22px;\ +outline: 0;\ +padding: 0 7px;\ +width: 214px;\ +margin: 0;\ +}\ +.ace_searchbtn,\ +.ace_replacebtn {\ +background: #fff;\ +border: 0 none;\ +border-left: 1px solid #dcdcdc;\ +cursor: pointer;\ +float: left;\ +height: 22px;\ +margin: 0;\ +padding: 0;\ +position: relative;\ +}\ +.ace_searchbtn:last-child,\ +.ace_replacebtn:last-child {\ +border-top-right-radius: 3px;\ +border-bottom-right-radius: 3px;\ +}\ +.ace_searchbtn:disabled {\ +background: none;\ +cursor: default;\ +}\ +.ace_searchbtn {\ +background-position: 50% 50%;\ +background-repeat: no-repeat;\ +width: 27px;\ +}\ +.ace_searchbtn.prev {\ +background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); \ +}\ +.ace_searchbtn.next {\ +background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); \ +}\ +.ace_searchbtn_close {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;\ +border-radius: 50%;\ +border: 0 none;\ +color: #656565;\ +cursor: pointer;\ +float: right;\ +font: 16px/16px Arial;\ +height: 14px;\ +margin: 5px 1px 9px 5px;\ +padding: 0;\ +text-align: center;\ +width: 14px;\ +}\ +.ace_searchbtn_close:hover {\ +background-color: #656565;\ +background-position: 50% 100%;\ +color: white;\ +}\ +.ace_replacebtn.prev {\ +width: 54px\ +}\ +.ace_replacebtn.next {\ +width: 27px\ +}\ +.ace_button {\ +margin-left: 2px;\ +cursor: pointer;\ +-webkit-user-select: none;\ +-moz-user-select: none;\ +-o-user-select: none;\ +-ms-user-select: none;\ +user-select: none;\ +overflow: hidden;\ +opacity: 0.7;\ +border: 1px solid rgba(100,100,100,0.23);\ +padding: 1px;\ +-moz-box-sizing: border-box;\ +box-sizing: border-box;\ +color: black;\ +}\ +.ace_button:hover {\ +background-color: #eee;\ +opacity:1;\ +}\ +.ace_button:active {\ +background-color: #ddd;\ +}\ +.ace_button.checked {\ +border-color: #3399ff;\ +opacity:1;\ +}\ +.ace_search_options{\ +margin-bottom: 3px;\ +text-align: right;\ +-webkit-user-select: none;\ +-moz-user-select: none;\ +-o-user-select: none;\ +-ms-user-select: none;\ +user-select: none;\ +}"; +var HashHandler = require("../keyboard/hash_handler").HashHandler; +var keyUtil = require("../lib/keys"); + +dom.importCssString(searchboxCss, "ace_searchbox"); + +var html = ''.replace(/>\s+/g, ">"); + +var SearchBox = function(editor, range, showReplaceForm) { + var div = dom.createElement("div"); + div.innerHTML = html; + this.element = div.firstChild; + + this.$init(); + this.setEditor(editor); +}; + +(function() { + this.setEditor = function(editor) { + editor.searchBox = this; + editor.container.appendChild(this.element); + this.editor = editor; + }; + + this.$initElements = function(sb) { + this.searchBox = sb.querySelector(".ace_search_form"); + this.replaceBox = sb.querySelector(".ace_replace_form"); + this.searchOptions = sb.querySelector(".ace_search_options"); + this.regExpOption = sb.querySelector("[action=toggleRegexpMode]"); + this.caseSensitiveOption = sb.querySelector("[action=toggleCaseSensitive]"); + this.wholeWordOption = sb.querySelector("[action=toggleWholeWords]"); + this.searchInput = this.searchBox.querySelector(".ace_search_field"); + this.replaceInput = this.replaceBox.querySelector(".ace_search_field"); + }; + + this.$init = function() { + var sb = this.element; + + this.$initElements(sb); + + var _this = this; + event.addListener(sb, "mousedown", function(e) { + setTimeout(function(){ + _this.activeInput.focus(); + }, 0); + event.stopPropagation(e); + }); + event.addListener(sb, "click", function(e) { + var t = e.target || e.srcElement; + var action = t.getAttribute("action"); + if (action && _this[action]) + _this[action](); + else if (_this.$searchBarKb.commands[action]) + _this.$searchBarKb.commands[action].exec(_this); + event.stopPropagation(e); + }); + + event.addCommandKeyListener(sb, function(e, hashId, keyCode) { + var keyString = keyUtil.keyCodeToString(keyCode); + var command = _this.$searchBarKb.findKeyCommand(hashId, keyString); + if (command && command.exec) { + command.exec(_this); + event.stopEvent(e); + } + }); + + this.$onChange = lang.delayedCall(function() { + _this.find(false, false); + }); + + event.addListener(this.searchInput, "input", function() { + _this.$onChange.schedule(20); + }); + event.addListener(this.searchInput, "focus", function() { + _this.activeInput = _this.searchInput; + _this.searchInput.value && _this.highlight(); + }); + event.addListener(this.replaceInput, "focus", function() { + _this.activeInput = _this.replaceInput; + _this.searchInput.value && _this.highlight(); + }); + }; + this.$closeSearchBarKb = new HashHandler([{ + bindKey: "Esc", + name: "closeSearchBar", + exec: function(editor) { + editor.searchBox.hide(); + } + }]); + this.$searchBarKb = new HashHandler(); + this.$searchBarKb.bindKeys({ + "Ctrl-f|Command-f|Ctrl-H|Command-Option-F": function(sb) { + var isReplace = sb.isReplace = !sb.isReplace; + sb.replaceBox.style.display = isReplace ? "" : "none"; + sb[isReplace ? "replaceInput" : "searchInput"].focus(); + }, + "Ctrl-G|Command-G": function(sb) { + sb.findNext(); + }, + "Ctrl-Shift-G|Command-Shift-G": function(sb) { + sb.findPrev(); + }, + "esc": function(sb) { + setTimeout(function() { sb.hide();}); + }, + "Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replace(); + sb.findNext(); + }, + "Shift-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replace(); + sb.findPrev(); + }, + "Alt-Return": function(sb) { + if (sb.activeInput == sb.replaceInput) + sb.replaceAll(); + sb.findAll(); + }, + "Tab": function(sb) { + (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus(); + } + }); + + this.$searchBarKb.addCommands([{ + name: "toggleRegexpMode", + bindKey: {win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/"}, + exec: function(sb) { + sb.regExpOption.checked = !sb.regExpOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleCaseSensitive", + bindKey: {win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I"}, + exec: function(sb) { + sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleWholeWords", + bindKey: {win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W"}, + exec: function(sb) { + sb.wholeWordOption.checked = !sb.wholeWordOption.checked; + sb.$syncOptions(); + } + }]); + + this.$syncOptions = function() { + dom.setCssClass(this.regExpOption, "checked", this.regExpOption.checked); + dom.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked); + dom.setCssClass(this.caseSensitiveOption, "checked", this.caseSensitiveOption.checked); + this.find(false, false); + }; + + this.highlight = function(re) { + this.editor.session.highlight(re || this.editor.$search.$options.re); + this.editor.renderer.updateBackMarkers() + }; + this.find = function(skipCurrent, backwards) { + var range = this.editor.find(this.searchInput.value, { + skipCurrent: skipCurrent, + backwards: backwards, + wrap: true, + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + }; + this.findNext = function() { + this.find(true, false); + }; + this.findPrev = function() { + this.find(true, true); + }; + this.findAll = function(){ + var range = this.editor.findAll(this.searchInput.value, { + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked + }); + var noMatch = !range && this.searchInput.value; + dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); + this.editor._emit("findSearchBox", { match: !noMatch }); + this.highlight(); + this.hide(); + }; + this.replace = function() { + if (!this.editor.getReadOnly()) + this.editor.replace(this.replaceInput.value); + }; + this.replaceAndFindNext = function() { + if (!this.editor.getReadOnly()) { + this.editor.replace(this.replaceInput.value); + this.findNext() + } + }; + this.replaceAll = function() { + if (!this.editor.getReadOnly()) + this.editor.replaceAll(this.replaceInput.value); + }; + + this.hide = function() { + this.element.style.display = "none"; + this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb); + this.editor.focus(); + }; + this.show = function(value, isReplace) { + this.element.style.display = ""; + this.replaceBox.style.display = isReplace ? "" : "none"; + + this.isReplace = isReplace; + + if (value) + this.searchInput.value = value; + this.searchInput.focus(); + this.searchInput.select(); + + this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb); + }; + + this.isFocused = function() { + var el = document.activeElement; + return el == this.searchInput || el == this.replaceInput; + } +}).call(SearchBox.prototype); + +exports.SearchBox = SearchBox; + +exports.Search = function(editor, isReplace) { + var sb = editor.searchBox || new SearchBox(editor); + sb.show(editor.session.getTextRange(), isReplace); +}; + +}); + (function() { + window.require(["ace/ext/searchbox"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-settings_menu.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-settings_menu.js new file mode 100644 index 00000000..76e2d441 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-settings_menu.js @@ -0,0 +1,640 @@ +define("ace/ext/menu_tools/element_generator",["require","exports","module"], function(require, exports, module) { +'use strict'; +module.exports.createOption = function createOption (obj) { + var attribute; + var el = document.createElement('option'); + for(attribute in obj) { + if(obj.hasOwnProperty(attribute)) { + if(attribute === 'selected') { + el.setAttribute(attribute, obj[attribute]); + } else { + el[attribute] = obj[attribute]; + } + } + } + return el; +}; +module.exports.createCheckbox = function createCheckbox (id, checked, clss) { + var el = document.createElement('input'); + el.setAttribute('type', 'checkbox'); + el.setAttribute('id', id); + el.setAttribute('name', id); + el.setAttribute('value', checked); + el.setAttribute('class', clss); + if(checked) { + el.setAttribute('checked', 'checked'); + } + return el; +}; +module.exports.createInput = function createInput (id, value, clss) { + var el = document.createElement('input'); + el.setAttribute('type', 'text'); + el.setAttribute('id', id); + el.setAttribute('name', id); + el.setAttribute('value', value); + el.setAttribute('class', clss); + return el; +}; +module.exports.createLabel = function createLabel (text, labelFor) { + var el = document.createElement('label'); + el.setAttribute('for', labelFor); + el.textContent = text; + return el; +}; +module.exports.createSelection = function createSelection (id, values, clss) { + var el = document.createElement('select'); + el.setAttribute('id', id); + el.setAttribute('name', id); + el.setAttribute('class', clss); + values.forEach(function(item) { + el.appendChild(module.exports.createOption(item)); + }); + return el; +}; + +}); + +define("ace/ext/modelist",["require","exports","module"], function(require, exports, module) { +"use strict"; + +var modes = []; +function getModeForPath(path) { + var mode = modesByName.text; + var fileName = path.split(/[\/\\]/).pop(); + for (var i = 0; i < modes.length; i++) { + if (modes[i].supportsFile(fileName)) { + mode = modes[i]; + break; + } + } + return mode; +} + +var Mode = function(name, caption, extensions) { + this.name = name; + this.caption = caption; + this.mode = "ace/mode/" + name; + this.extensions = extensions; + if (/\^/.test(extensions)) { + var re = extensions.replace(/\|(\^)?/g, function(a, b){ + return "$|" + (b ? "^" : "^.*\\."); + }) + "$"; + } else { + var re = "^.*\\.(" + extensions + ")$"; + } + + this.extRe = new RegExp(re, "gi"); +}; + +Mode.prototype.supportsFile = function(filename) { + return filename.match(this.extRe); +}; +var supportedModes = { + ABAP: ["abap"], + ABC: ["abc"], + ActionScript:["as"], + ADA: ["ada|adb"], + Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"], + AsciiDoc: ["asciidoc"], + Assembly_x86:["asm"], + AutoHotKey: ["ahk"], + BatchFile: ["bat|cmd"], + C9Search: ["c9search_results"], + C_Cpp: ["cpp|c|cc|cxx|h|hh|hpp"], + Cirru: ["cirru|cr"], + Clojure: ["clj|cljs"], + Cobol: ["CBL|COB"], + coffee: ["coffee|cf|cson|^Cakefile"], + ColdFusion: ["cfm"], + CSharp: ["cs"], + CSS: ["css"], + Curly: ["curly"], + D: ["d|di"], + Dart: ["dart"], + Diff: ["diff|patch"], + Dockerfile: ["^Dockerfile"], + Dot: ["dot"], + Dummy: ["dummy"], + DummySyntax: ["dummy"], + Eiffel: ["e"], + EJS: ["ejs"], + Elixir: ["ex|exs"], + Elm: ["elm"], + Erlang: ["erl|hrl"], + Forth: ["frt|fs|ldr"], + FTL: ["ftl"], + Gcode: ["gcode"], + Gherkin: ["feature"], + Gitignore: ["^.gitignore"], + Glsl: ["glsl|frag|vert"], + golang: ["go"], + Groovy: ["groovy"], + HAML: ["haml"], + Handlebars: ["hbs|handlebars|tpl|mustache"], + Haskell: ["hs"], + haXe: ["hx"], + HTML: ["html|htm|xhtml"], + HTML_Ruby: ["erb|rhtml|html.erb"], + INI: ["ini|conf|cfg|prefs"], + Io: ["io"], + Jack: ["jack"], + Jade: ["jade"], + Java: ["java"], + JavaScript: ["js|jsm"], + JSON: ["json"], + JSONiq: ["jq"], + JSP: ["jsp"], + JSX: ["jsx"], + Julia: ["jl"], + LaTeX: ["tex|latex|ltx|bib"], + Lean: ["lean|hlean"], + LESS: ["less"], + Liquid: ["liquid"], + Lisp: ["lisp"], + LiveScript: ["ls"], + LogiQL: ["logic|lql"], + LSL: ["lsl"], + Lua: ["lua"], + LuaPage: ["lp"], + Lucene: ["lucene"], + Makefile: ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"], + Markdown: ["md|markdown"], + Mask: ["mask"], + MATLAB: ["matlab"], + MEL: ["mel"], + MUSHCode: ["mc|mush"], + MySQL: ["mysql"], + Nix: ["nix"], + ObjectiveC: ["m|mm"], + OCaml: ["ml|mli"], + Pascal: ["pas|p"], + Perl: ["pl|pm"], + pgSQL: ["pgsql"], + PHP: ["php|phtml"], + Powershell: ["ps1"], + Praat: ["praat|praatscript|psc|proc"], + Prolog: ["plg|prolog"], + Properties: ["properties"], + Protobuf: ["proto"], + Python: ["py"], + R: ["r"], + RDoc: ["Rd"], + RHTML: ["Rhtml"], + Ruby: ["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"], + Rust: ["rs"], + SASS: ["sass"], + SCAD: ["scad"], + Scala: ["scala"], + Scheme: ["scm|rkt"], + SCSS: ["scss"], + SH: ["sh|bash|^.bashrc"], + SJS: ["sjs"], + Smarty: ["smarty|tpl"], + snippets: ["snippets"], + Soy_Template:["soy"], + Space: ["space"], + SQL: ["sql"], + Stylus: ["styl|stylus"], + SVG: ["svg"], + Tcl: ["tcl"], + Tex: ["tex"], + Text: ["txt"], + Textile: ["textile"], + Toml: ["toml"], + Twig: ["twig"], + Typescript: ["ts|typescript|str"], + Vala: ["vala"], + VBScript: ["vbs|vb"], + Velocity: ["vm"], + Verilog: ["v|vh|sv|svh"], + VHDL: ["vhd|vhdl"], + XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"], + XQuery: ["xq"], + YAML: ["yaml|yml"], + Django: ["html"] +}; + +var nameOverrides = { + ObjectiveC: "Objective-C", + CSharp: "C#", + golang: "Go", + C_Cpp: "C and C++", + coffee: "CoffeeScript", + HTML_Ruby: "HTML (Ruby)", + FTL: "FreeMarker" +}; +var modesByName = {}; +for (var name in supportedModes) { + var data = supportedModes[name]; + var displayName = (nameOverrides[name] || name).replace(/_/g, " "); + var filename = name.toLowerCase(); + var mode = new Mode(filename, displayName, data[0]); + modesByName[filename] = mode; + modes.push(mode); +} + +module.exports = { + getModeForPath: getModeForPath, + modes: modes, + modesByName: modesByName +}; + +}); + +define("ace/ext/themelist",["require","exports","module","ace/lib/fixoldbrowsers"], function(require, exports, module) { +"use strict"; +require("ace/lib/fixoldbrowsers"); + +var themeData = [ + ["Chrome" ], + ["Clouds" ], + ["Crimson Editor" ], + ["Dawn" ], + ["Dreamweaver" ], + ["Eclipse" ], + ["GitHub" ], + ["Solarized Light"], + ["TextMate" ], + ["Tomorrow" ], + ["XCode" ], + ["Kuroir"], + ["KatzenMilch"], + ["Ambiance" ,"ambiance" , "dark"], + ["Chaos" ,"chaos" , "dark"], + ["Clouds Midnight" ,"clouds_midnight" , "dark"], + ["Cobalt" ,"cobalt" , "dark"], + ["idle Fingers" ,"idle_fingers" , "dark"], + ["krTheme" ,"kr_theme" , "dark"], + ["Merbivore" ,"merbivore" , "dark"], + ["Merbivore Soft" ,"merbivore_soft" , "dark"], + ["Mono Industrial" ,"mono_industrial" , "dark"], + ["Monokai" ,"monokai" , "dark"], + ["Pastel on dark" ,"pastel_on_dark" , "dark"], + ["Solarized Dark" ,"solarized_dark" , "dark"], + ["Terminal" ,"terminal" , "dark"], + ["Tomorrow Night" ,"tomorrow_night" , "dark"], + ["Tomorrow Night Blue" ,"tomorrow_night_blue" , "dark"], + ["Tomorrow Night Bright","tomorrow_night_bright" , "dark"], + ["Tomorrow Night 80s" ,"tomorrow_night_eighties" , "dark"], + ["Twilight" ,"twilight" , "dark"], + ["Vibrant Ink" ,"vibrant_ink" , "dark"] +]; + + +exports.themesByName = {}; +exports.themes = themeData.map(function(data) { + var name = data[1] || data[0].replace(/ /g, "_").toLowerCase(); + var theme = { + caption: data[0], + theme: "ace/theme/" + name, + isDark: data[2] == "dark", + name: name + }; + exports.themesByName[name] = theme; + return theme; +}); + +}); + +define("ace/ext/menu_tools/add_editor_menu_options",["require","exports","module","ace/ext/modelist","ace/ext/themelist"], function(require, exports, module) { +'use strict'; +module.exports.addEditorMenuOptions = function addEditorMenuOptions (editor) { + var modelist = require('../modelist'); + var themelist = require('../themelist'); + editor.menuOptions = { + setNewLineMode: [{ + textContent: "unix", + value: "unix" + }, { + textContent: "windows", + value: "windows" + }, { + textContent: "auto", + value: "auto" + }], + setTheme: [], + setMode: [], + setKeyboardHandler: [{ + textContent: "ace", + value: "" + }, { + textContent: "vim", + value: "ace/keyboard/vim" + }, { + textContent: "emacs", + value: "ace/keyboard/emacs" + }, { + textContent: "textarea", + value: "ace/keyboard/textarea" + }, { + textContent: "sublime", + value: "ace/keyboard/sublime" + }] + }; + + editor.menuOptions.setTheme = themelist.themes.map(function(theme) { + return { + textContent: theme.caption, + value: theme.theme + }; + }); + + editor.menuOptions.setMode = modelist.modes.map(function(mode) { + return { + textContent: mode.name, + value: mode.mode + }; + }); +}; + + +}); + +define("ace/ext/menu_tools/get_set_functions",["require","exports","module"], function(require, exports, module) { +'use strict'; +module.exports.getSetFunctions = function getSetFunctions (editor) { + var out = []; + var my = { + 'editor' : editor, + 'session' : editor.session, + 'renderer' : editor.renderer + }; + var opts = []; + var skip = [ + 'setOption', + 'setUndoManager', + 'setDocument', + 'setValue', + 'setBreakpoints', + 'setScrollTop', + 'setScrollLeft', + 'setSelectionStyle', + 'setWrapLimitRange' + ]; + ['renderer', 'session', 'editor'].forEach(function(esra) { + var esr = my[esra]; + var clss = esra; + for(var fn in esr) { + if(skip.indexOf(fn) === -1) { + if(/^set/.test(fn) && opts.indexOf(fn) === -1) { + opts.push(fn); + out.push({ + 'functionName' : fn, + 'parentObj' : esr, + 'parentName' : clss + }); + } + } + } + }); + return out; +}; + +}); + +define("ace/ext/menu_tools/generate_settings_menu",["require","exports","module","ace/ext/menu_tools/element_generator","ace/ext/menu_tools/add_editor_menu_options","ace/ext/menu_tools/get_set_functions"], function(require, exports, module) { +'use strict'; +var egen = require('./element_generator'); +var addEditorMenuOptions = require('./add_editor_menu_options').addEditorMenuOptions; +var getSetFunctions = require('./get_set_functions').getSetFunctions; +module.exports.generateSettingsMenu = function generateSettingsMenu (editor) { + var elements = []; + function cleanupElementsList() { + elements.sort(function(a, b) { + var x = a.getAttribute('contains'); + var y = b.getAttribute('contains'); + return x.localeCompare(y); + }); + } + function wrapElements() { + var topmenu = document.createElement('div'); + topmenu.setAttribute('id', 'ace_settingsmenu'); + elements.forEach(function(element) { + topmenu.appendChild(element); + }); + + var el = topmenu.appendChild(document.createElement('div')); + var version = "1.1.8"; + el.style.padding = "1em"; + el.textContent = "Ace version " + version; + + return topmenu; + } + function createNewEntry(obj, clss, item, val) { + var el; + var div = document.createElement('div'); + div.setAttribute('contains', item); + div.setAttribute('class', 'ace_optionsMenuEntry'); + div.setAttribute('style', 'clear: both;'); + + div.appendChild(egen.createLabel( + item.replace(/^set/, '').replace(/([A-Z])/g, ' $1').trim(), + item + )); + + if (Array.isArray(val)) { + el = egen.createSelection(item, val, clss); + el.addEventListener('change', function(e) { + try{ + editor.menuOptions[e.target.id].forEach(function(x) { + if(x.textContent !== e.target.textContent) { + delete x.selected; + } + }); + obj[e.target.id](e.target.value); + } catch (err) { + throw new Error(err); + } + }); + } else if(typeof val === 'boolean') { + el = egen.createCheckbox(item, val, clss); + el.addEventListener('change', function(e) { + try{ + obj[e.target.id](!!e.target.checked); + } catch (err) { + throw new Error(err); + } + }); + } else { + el = egen.createInput(item, val, clss); + el.addEventListener('change', function(e) { + try{ + if(e.target.value === 'true') { + obj[e.target.id](true); + } else if(e.target.value === 'false') { + obj[e.target.id](false); + } else { + obj[e.target.id](e.target.value); + } + } catch (err) { + throw new Error(err); + } + }); + } + el.style.cssText = 'float:right;'; + div.appendChild(el); + return div; + } + function makeDropdown(item, esr, clss, fn) { + var val = editor.menuOptions[item]; + var currentVal = esr[fn](); + if (typeof currentVal == 'object') + currentVal = currentVal.$id; + val.forEach(function(valuex) { + if (valuex.value === currentVal) + valuex.selected = 'selected'; + }); + return createNewEntry(esr, clss, item, val); + } + function handleSet(setObj) { + var item = setObj.functionName; + var esr = setObj.parentObj; + var clss = setObj.parentName; + var val; + var fn = item.replace(/^set/, 'get'); + if(editor.menuOptions[item] !== undefined) { + elements.push(makeDropdown(item, esr, clss, fn)); + } else if(typeof esr[fn] === 'function') { + try { + val = esr[fn](); + if(typeof val === 'object') { + val = val.$id; + } + elements.push( + createNewEntry(esr, clss, item, val) + ); + } catch (e) { + } + } + } + addEditorMenuOptions(editor); + getSetFunctions(editor).forEach(function(setObj) { + handleSet(setObj); + }); + cleanupElementsList(); + return wrapElements(); +}; + +}); + +define("ace/ext/menu_tools/overlay_page",["require","exports","module","ace/lib/dom"], function(require, exports, module) { +'use strict'; +var dom = require("../../lib/dom"); +var cssText = "#ace_settingsmenu, #kbshortcutmenu {\ +background-color: #F7F7F7;\ +color: black;\ +box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);\ +padding: 1em 0.5em 2em 1em;\ +overflow: auto;\ +position: absolute;\ +margin: 0;\ +bottom: 0;\ +right: 0;\ +top: 0;\ +z-index: 9991;\ +cursor: default;\ +}\ +.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {\ +box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);\ +background-color: rgba(255, 255, 255, 0.6);\ +color: black;\ +}\ +.ace_optionsMenuEntry:hover {\ +background-color: rgba(100, 100, 100, 0.1);\ +-webkit-transition: all 0.5s;\ +transition: all 0.3s\ +}\ +.ace_closeButton {\ +background: rgba(245, 146, 146, 0.5);\ +border: 1px solid #F48A8A;\ +border-radius: 50%;\ +padding: 7px;\ +position: absolute;\ +right: -8px;\ +top: -8px;\ +z-index: 1000;\ +}\ +.ace_closeButton{\ +background: rgba(245, 146, 146, 0.9);\ +}\ +.ace_optionsMenuKey {\ +color: darkslateblue;\ +font-weight: bold;\ +}\ +.ace_optionsMenuCommand {\ +color: darkcyan;\ +font-weight: normal;\ +}"; +dom.importCssString(cssText); +module.exports.overlayPage = function overlayPage(editor, contentElement, top, right, bottom, left) { + top = top ? 'top: ' + top + ';' : ''; + bottom = bottom ? 'bottom: ' + bottom + ';' : ''; + right = right ? 'right: ' + right + ';' : ''; + left = left ? 'left: ' + left + ';' : ''; + + var closer = document.createElement('div'); + var contentContainer = document.createElement('div'); + + function documentEscListener(e) { + if (e.keyCode === 27) { + closer.click(); + } + } + + closer.style.cssText = 'margin: 0; padding: 0; ' + + 'position: fixed; top:0; bottom:0; left:0; right:0;' + + 'z-index: 9990; ' + + 'background-color: rgba(0, 0, 0, 0.3);'; + closer.addEventListener('click', function() { + document.removeEventListener('keydown', documentEscListener); + closer.parentNode.removeChild(closer); + editor.focus(); + closer = null; + }); + document.addEventListener('keydown', documentEscListener); + + contentContainer.style.cssText = top + right + bottom + left; + contentContainer.addEventListener('click', function(e) { + e.stopPropagation(); + }); + + var wrapper = dom.createElement("div"); + wrapper.style.position = "relative"; + + var closeButton = dom.createElement("div"); + closeButton.className = "ace_closeButton"; + closeButton.addEventListener('click', function() { + closer.click(); + }); + + wrapper.appendChild(closeButton); + contentContainer.appendChild(wrapper); + + contentContainer.appendChild(contentElement); + closer.appendChild(contentContainer); + document.body.appendChild(closer); + editor.blur(); +}; + +}); + +define("ace/ext/settings_menu",["require","exports","module","ace/ext/menu_tools/generate_settings_menu","ace/ext/menu_tools/overlay_page","ace/editor"], function(require, exports, module) { +"use strict"; +var generateSettingsMenu = require('./menu_tools/generate_settings_menu').generateSettingsMenu; +var overlayPage = require('./menu_tools/overlay_page').overlayPage; +function showSettingsMenu(editor) { + var sm = document.getElementById('ace_settingsmenu'); + if (!sm) + overlayPage(editor, generateSettingsMenu(editor), '0', '0', '0'); +} +module.exports.init = function(editor) { + var Editor = require("ace/editor").Editor; + Editor.prototype.showSettingsMenu = function() { + showSettingsMenu(this); + }; +}; +}); + (function() { + window.require(["ace/ext/settings_menu"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-spellcheck.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-spellcheck.js new file mode 100644 index 00000000..be79c4a2 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-spellcheck.js @@ -0,0 +1,71 @@ +define("ace/ext/spellcheck",["require","exports","module","ace/lib/event","ace/editor","ace/config"], function(require, exports, module) { +"use strict"; +var event = require("../lib/event"); + +exports.contextMenuHandler = function(e){ + var host = e.target; + var text = host.textInput.getElement(); + if (!host.selection.isEmpty()) + return; + var c = host.getCursorPosition(); + var r = host.session.getWordRange(c.row, c.column); + var w = host.session.getTextRange(r); + + host.session.tokenRe.lastIndex = 0; + if (!host.session.tokenRe.test(w)) + return; + var PLACEHOLDER = "\x01\x01"; + var value = w + " " + PLACEHOLDER; + text.value = value; + text.setSelectionRange(w.length, w.length + 1); + text.setSelectionRange(0, 0); + text.setSelectionRange(0, w.length); + + var afterKeydown = false; + event.addListener(text, "keydown", function onKeydown() { + event.removeListener(text, "keydown", onKeydown); + afterKeydown = true; + }); + + host.textInput.setInputHandler(function(newVal) { + console.log(newVal , value, text.selectionStart, text.selectionEnd) + if (newVal == value) + return ''; + if (newVal.lastIndexOf(value, 0) === 0) + return newVal.slice(value.length); + if (newVal.substr(text.selectionEnd) == value) + return newVal.slice(0, -value.length); + if (newVal.slice(-2) == PLACEHOLDER) { + var val = newVal.slice(0, -2); + if (val.slice(-1) == " ") { + if (afterKeydown) + return val.substring(0, text.selectionEnd); + val = val.slice(0, -1); + host.session.replace(r, val); + return ""; + } + } + + return newVal; + }); +}; +var Editor = require("../editor").Editor; +require("../config").defineOptions(Editor.prototype, "editor", { + spellcheck: { + set: function(val) { + var text = this.textInput.getElement(); + text.spellcheck = !!val; + if (!val) + this.removeListener("nativecontextmenu", exports.contextMenuHandler); + else + this.on("nativecontextmenu", exports.contextMenuHandler); + }, + value: true + } +}); + +}); + (function() { + window.require(["ace/ext/spellcheck"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-split.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-split.js new file mode 100644 index 00000000..30a3f6f0 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-split.js @@ -0,0 +1,246 @@ +define("ace/split",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter","ace/editor","ace/virtual_renderer","ace/edit_session"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var lang = require("./lib/lang"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; + +var Editor = require("./editor").Editor; +var Renderer = require("./virtual_renderer").VirtualRenderer; +var EditSession = require("./edit_session").EditSession; + + +var Split = function(container, theme, splits) { + this.BELOW = 1; + this.BESIDE = 0; + + this.$container = container; + this.$theme = theme; + this.$splits = 0; + this.$editorCSS = ""; + this.$editors = []; + this.$orientation = this.BESIDE; + + this.setSplits(splits || 1); + this.$cEditor = this.$editors[0]; + + + this.on("focus", function(editor) { + this.$cEditor = editor; + }.bind(this)); +}; + +(function(){ + + oop.implement(this, EventEmitter); + + this.$createEditor = function() { + var el = document.createElement("div"); + el.className = this.$editorCSS; + el.style.cssText = "position: absolute; top:0px; bottom:0px"; + this.$container.appendChild(el); + var editor = new Editor(new Renderer(el, this.$theme)); + + editor.on("focus", function() { + this._emit("focus", editor); + }.bind(this)); + + this.$editors.push(editor); + editor.setFontSize(this.$fontSize); + return editor; + }; + + this.setSplits = function(splits) { + var editor; + if (splits < 1) { + throw "The number of splits have to be > 0!"; + } + + if (splits == this.$splits) { + return; + } else if (splits > this.$splits) { + while (this.$splits < this.$editors.length && this.$splits < splits) { + editor = this.$editors[this.$splits]; + this.$container.appendChild(editor.container); + editor.setFontSize(this.$fontSize); + this.$splits ++; + } + while (this.$splits < splits) { + this.$createEditor(); + this.$splits ++; + } + } else { + while (this.$splits > splits) { + editor = this.$editors[this.$splits - 1]; + this.$container.removeChild(editor.container); + this.$splits --; + } + } + this.resize(); + }; + this.getSplits = function() { + return this.$splits; + }; + this.getEditor = function(idx) { + return this.$editors[idx]; + }; + this.getCurrentEditor = function() { + return this.$cEditor; + }; + this.focus = function() { + this.$cEditor.focus(); + }; + this.blur = function() { + this.$cEditor.blur(); + }; + this.setTheme = function(theme) { + this.$editors.forEach(function(editor) { + editor.setTheme(theme); + }); + }; + this.setKeyboardHandler = function(keybinding) { + this.$editors.forEach(function(editor) { + editor.setKeyboardHandler(keybinding); + }); + }; + this.forEach = function(callback, scope) { + this.$editors.forEach(callback, scope); + }; + + + this.$fontSize = ""; + this.setFontSize = function(size) { + this.$fontSize = size; + this.forEach(function(editor) { + editor.setFontSize(size); + }); + }; + + this.$cloneSession = function(session) { + var s = new EditSession(session.getDocument(), session.getMode()); + + var undoManager = session.getUndoManager(); + if (undoManager) { + var undoManagerProxy = new UndoManagerProxy(undoManager, s); + s.setUndoManager(undoManagerProxy); + } + s.$informUndoManager = lang.delayedCall(function() { s.$deltas = []; }); + s.setTabSize(session.getTabSize()); + s.setUseSoftTabs(session.getUseSoftTabs()); + s.setOverwrite(session.getOverwrite()); + s.setBreakpoints(session.getBreakpoints()); + s.setUseWrapMode(session.getUseWrapMode()); + s.setUseWorker(session.getUseWorker()); + s.setWrapLimitRange(session.$wrapLimitRange.min, + session.$wrapLimitRange.max); + s.$foldData = session.$cloneFoldData(); + + return s; + }; + this.setSession = function(session, idx) { + var editor; + if (idx == null) { + editor = this.$cEditor; + } else { + editor = this.$editors[idx]; + } + var isUsed = this.$editors.some(function(editor) { + return editor.session === session; + }); + + if (isUsed) { + session = this.$cloneSession(session); + } + editor.setSession(session); + return session; + }; + this.getOrientation = function() { + return this.$orientation; + }; + this.setOrientation = function(orientation) { + if (this.$orientation == orientation) { + return; + } + this.$orientation = orientation; + this.resize(); + }; + this.resize = function() { + var width = this.$container.clientWidth; + var height = this.$container.clientHeight; + var editor; + + if (this.$orientation == this.BESIDE) { + var editorWidth = width / this.$splits; + for (var i = 0; i < this.$splits; i++) { + editor = this.$editors[i]; + editor.container.style.width = editorWidth + "px"; + editor.container.style.top = "0px"; + editor.container.style.left = i * editorWidth + "px"; + editor.container.style.height = height + "px"; + editor.resize(); + } + } else { + var editorHeight = height / this.$splits; + for (var i = 0; i < this.$splits; i++) { + editor = this.$editors[i]; + editor.container.style.width = width + "px"; + editor.container.style.top = i * editorHeight + "px"; + editor.container.style.left = "0px"; + editor.container.style.height = editorHeight + "px"; + editor.resize(); + } + } + }; + +}).call(Split.prototype); + + +function UndoManagerProxy(undoManager, session) { + this.$u = undoManager; + this.$doc = session; +} + +(function() { + this.execute = function(options) { + this.$u.execute(options); + }; + + this.undo = function() { + var selectionRange = this.$u.undo(true); + if (selectionRange) { + this.$doc.selection.setSelectionRange(selectionRange); + } + }; + + this.redo = function() { + var selectionRange = this.$u.redo(true); + if (selectionRange) { + this.$doc.selection.setSelectionRange(selectionRange); + } + }; + + this.reset = function() { + this.$u.reset(); + }; + + this.hasUndo = function() { + return this.$u.hasUndo(); + }; + + this.hasRedo = function() { + return this.$u.hasRedo(); + }; +}).call(UndoManagerProxy.prototype); + +exports.Split = Split; +}); + +define("ace/ext/split",["require","exports","module","ace/split"], function(require, exports, module) { +"use strict"; +module.exports = require("../split"); + +}); + (function() { + window.require(["ace/ext/split"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-static_highlight.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-static_highlight.js new file mode 100644 index 00000000..1ecb6c5f --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-static_highlight.js @@ -0,0 +1,154 @@ +define("ace/ext/static_highlight",["require","exports","module","ace/edit_session","ace/layer/text","ace/config","ace/lib/dom"], function(require, exports, module) { +"use strict"; + +var EditSession = require("../edit_session").EditSession; +var TextLayer = require("../layer/text").Text; +var baseStyles = ".ace_static_highlight {\ +font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace;\ +font-size: 12px;\ +}\ +.ace_static_highlight .ace_gutter {\ +width: 25px !important;\ +float: left;\ +text-align: right;\ +padding: 0 3px 0 0;\ +margin-right: 3px;\ +position: static !important;\ +}\ +.ace_static_highlight .ace_line { clear: both; }\ +.ace_static_highlight .ace_gutter-cell {\ +-moz-user-select: -moz-none;\ +-khtml-user-select: none;\ +-webkit-user-select: none;\ +user-select: none;\ +}\ +.ace_static_highlight .ace_gutter-cell:before {\ +content: counter(ace_line, decimal);\ +counter-increment: ace_line;\ +}\ +.ace_static_highlight {\ +counter-reset: ace_line;\ +}\ +"; +var config = require("../config"); +var dom = require("../lib/dom"); + + +var highlight = function(el, opts, callback) { + var m = el.className.match(/lang-(\w+)/); + var mode = opts.mode || m && ("ace/mode/" + m[1]); + if (!mode) + return false; + var theme = opts.theme || "ace/theme/textmate"; + + var data = ""; + var nodes = []; + + if (el.firstElementChild) { + var textLen = 0; + for (var i = 0; i < el.childNodes.length; i++) { + var ch = el.childNodes[i]; + if (ch.nodeType == 3) { + textLen += ch.data.length; + data += ch.data; + } else { + nodes.push(textLen, ch); + } + } + } else { + data = dom.getInnerText(el); + if (opts.trim) + data = data.trim(); + } + + highlight.render(data, mode, theme, opts.firstLineNumber, !opts.showGutter, function (highlighted) { + dom.importCssString(highlighted.css, "ace_highlight"); + el.innerHTML = highlighted.html; + var container = el.firstChild.firstChild; + for (var i = 0; i < nodes.length; i += 2) { + var pos = highlighted.session.doc.indexToPosition(nodes[i]); + var node = nodes[i + 1]; + var lineEl = container.children[pos.row]; + lineEl && lineEl.appendChild(node); + } + callback && callback(); + }); +}; +highlight.render = function(input, mode, theme, lineStart, disableGutter, callback) { + var waiting = 1; + var modeCache = EditSession.prototype.$modes; + if (typeof theme == "string") { + waiting++; + config.loadModule(['theme', theme], function(m) { + theme = m; + --waiting || done(); + }); + } + var modeOptions; + if (mode && typeof mode === "object" && !mode.getTokenizer) { + modeOptions = mode; + mode = modeOptions.path; + } + if (typeof mode == "string") { + waiting++; + config.loadModule(['mode', mode], function(m) { + if (!modeCache[mode] || modeOptions) + modeCache[mode] = new m.Mode(modeOptions); + mode = modeCache[mode]; + --waiting || done(); + }); + } + function done() { + var result = highlight.renderSync(input, mode, theme, lineStart, disableGutter); + return callback ? callback(result) : result; + } + return --waiting || done(); +}; +highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) { + lineStart = parseInt(lineStart || 1, 10); + + var session = new EditSession(""); + session.setUseWorker(false); + session.setMode(mode); + + var textLayer = new TextLayer(document.createElement("div")); + textLayer.setSession(session); + textLayer.config = { + characterWidth: 10, + lineHeight: 20 + }; + + session.setValue(input); + + var stringBuilder = []; + var length = session.getLength(); + + for(var ix = 0; ix < length; ix++) { + stringBuilder.push("
"); + if (!disableGutter) + stringBuilder.push("" + /*(ix + lineStart) + */ ""); + textLayer.$renderLine(stringBuilder, ix, true, false); + stringBuilder.push("\n
"); + } + var html = "
" + + "
" + + stringBuilder.join("") + + "
" + + "
"; + + textLayer.destroy(); + + return { + css: baseStyles + theme.cssText, + html: html, + session: session + }; +}; + +module.exports = highlight; +module.exports.highlight =highlight; +}); + (function() { + window.require(["ace/ext/static_highlight"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-statusbar.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-statusbar.js new file mode 100644 index 00000000..838d7c61 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-statusbar.js @@ -0,0 +1,51 @@ +define("ace/ext/statusbar",["require","exports","module","ace/lib/dom","ace/lib/lang"], function(require, exports, module) { +"use strict"; +var dom = require("ace/lib/dom"); +var lang = require("ace/lib/lang"); + +var StatusBar = function(editor, parentNode) { + this.element = dom.createElement("div"); + this.element.className = "ace_status-indicator"; + this.element.style.cssText = "display: inline-block;"; + parentNode.appendChild(this.element); + + var statusUpdate = lang.delayedCall(function(){ + this.updateStatus(editor) + }.bind(this)); + editor.on("changeStatus", function() { + statusUpdate.schedule(100); + }); + editor.on("changeSelection", function() { + statusUpdate.schedule(100); + }); +}; + +(function(){ + this.updateStatus = function(editor) { + var status = []; + function add(str, separator) { + str && status.push(str, separator || "|"); + } + + add(editor.keyBinding.getStatusText(editor)); + if (editor.commands.recording) + add("REC"); + + var c = editor.selection.lead; + add(c.row + ":" + c.column, " "); + if (!editor.selection.isEmpty()) { + var r = editor.getSelectionRange(); + add("(" + (r.end.row - r.start.row) + ":" +(r.end.column - r.start.column) + ")"); + } + status.pop(); + this.element.textContent = status.join(""); + }; +}).call(StatusBar.prototype); + +exports.StatusBar = StatusBar; + +}); + (function() { + window.require(["ace/ext/statusbar"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-textarea.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-textarea.js new file mode 100644 index 00000000..98fff053 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-textarea.js @@ -0,0 +1,632 @@ +define("ace/theme/textmate",["require","exports","module","ace/lib/dom"], function(require, exports, module) { +"use strict"; + +exports.isDark = false; +exports.cssClass = "ace-tm"; +exports.cssText = ".ace-tm .ace_gutter {\ +background: #f0f0f0;\ +color: #333;\ +}\ +.ace-tm .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8;\ +}\ +.ace-tm .ace_fold {\ +background-color: #6B72E6;\ +}\ +.ace-tm {\ +background-color: #FFFFFF;\ +color: black;\ +}\ +.ace-tm .ace_cursor {\ +color: black;\ +}\ +.ace-tm .ace_invisible {\ +color: rgb(191, 191, 191);\ +}\ +.ace-tm .ace_storage,\ +.ace-tm .ace_keyword {\ +color: blue;\ +}\ +.ace-tm .ace_constant {\ +color: rgb(197, 6, 11);\ +}\ +.ace-tm .ace_constant.ace_buildin {\ +color: rgb(88, 72, 246);\ +}\ +.ace-tm .ace_constant.ace_language {\ +color: rgb(88, 92, 246);\ +}\ +.ace-tm .ace_constant.ace_library {\ +color: rgb(6, 150, 14);\ +}\ +.ace-tm .ace_invalid {\ +background-color: rgba(255, 0, 0, 0.1);\ +color: red;\ +}\ +.ace-tm .ace_support.ace_function {\ +color: rgb(60, 76, 114);\ +}\ +.ace-tm .ace_support.ace_constant {\ +color: rgb(6, 150, 14);\ +}\ +.ace-tm .ace_support.ace_type,\ +.ace-tm .ace_support.ace_class {\ +color: rgb(109, 121, 222);\ +}\ +.ace-tm .ace_keyword.ace_operator {\ +color: rgb(104, 118, 135);\ +}\ +.ace-tm .ace_string {\ +color: rgb(3, 106, 7);\ +}\ +.ace-tm .ace_comment {\ +color: rgb(76, 136, 107);\ +}\ +.ace-tm .ace_comment.ace_doc {\ +color: rgb(0, 102, 255);\ +}\ +.ace-tm .ace_comment.ace_doc.ace_tag {\ +color: rgb(128, 159, 191);\ +}\ +.ace-tm .ace_constant.ace_numeric {\ +color: rgb(0, 0, 205);\ +}\ +.ace-tm .ace_variable {\ +color: rgb(49, 132, 149);\ +}\ +.ace-tm .ace_xml-pe {\ +color: rgb(104, 104, 91);\ +}\ +.ace-tm .ace_entity.ace_name.ace_function {\ +color: #0000A2;\ +}\ +.ace-tm .ace_heading {\ +color: rgb(12, 7, 255);\ +}\ +.ace-tm .ace_list {\ +color:rgb(185, 6, 144);\ +}\ +.ace-tm .ace_meta.ace_tag {\ +color:rgb(0, 22, 142);\ +}\ +.ace-tm .ace_string.ace_regex {\ +color: rgb(255, 0, 0)\ +}\ +.ace-tm .ace_marker-layer .ace_selection {\ +background: rgb(181, 213, 255);\ +}\ +.ace-tm.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px white;\ +border-radius: 2px;\ +}\ +.ace-tm .ace_marker-layer .ace_step {\ +background: rgb(252, 255, 0);\ +}\ +.ace-tm .ace_marker-layer .ace_stack {\ +background: rgb(164, 229, 101);\ +}\ +.ace-tm .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgb(192, 192, 192);\ +}\ +.ace-tm .ace_marker-layer .ace_active-line {\ +background: rgba(0, 0, 0, 0.07);\ +}\ +.ace-tm .ace_gutter-active-line {\ +background-color : #dcdcdc;\ +}\ +.ace-tm .ace_marker-layer .ace_selected-word {\ +background: rgb(250, 250, 255);\ +border: 1px solid rgb(200, 200, 250);\ +}\ +.ace-tm .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ +}\ +"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); + +define("ace/ace",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/dom","ace/lib/event","ace/editor","ace/edit_session","ace/undomanager","ace/virtual_renderer","ace/worker/worker_client","ace/keyboard/hash_handler","ace/placeholder","ace/multi_select","ace/mode/folding/fold_mode","ace/theme/textmate","ace/ext/error_marker","ace/config"], function(require, exports, module) { +"use strict"; + +require("./lib/fixoldbrowsers"); + +var dom = require("./lib/dom"); +var event = require("./lib/event"); + +var Editor = require("./editor").Editor; +var EditSession = require("./edit_session").EditSession; +var UndoManager = require("./undomanager").UndoManager; +var Renderer = require("./virtual_renderer").VirtualRenderer; +require("./worker/worker_client"); +require("./keyboard/hash_handler"); +require("./placeholder"); +require("./multi_select"); +require("./mode/folding/fold_mode"); +require("./theme/textmate"); +require("./ext/error_marker"); + +exports.config = require("./config"); +exports.require = require; +exports.edit = function(el) { + if (typeof(el) == "string") { + var _id = el; + el = document.getElementById(_id); + if (!el) + throw new Error("ace.edit can't find div #" + _id); + } + + if (el && el.env && el.env.editor instanceof Editor) + return el.env.editor; + + var value = ""; + if (el && /input|textarea/i.test(el.tagName)) { + var oldNode = el; + value = oldNode.value; + el = dom.createElement("pre"); + oldNode.parentNode.replaceChild(el, oldNode); + } else { + value = dom.getInnerText(el); + el.innerHTML = ''; + } + + var doc = exports.createEditSession(value); + + var editor = new Editor(new Renderer(el)); + editor.setSession(doc); + + var env = { + document: doc, + editor: editor, + onResize: editor.resize.bind(editor, null) + }; + if (oldNode) env.textarea = oldNode; + event.addListener(window, "resize", env.onResize); + editor.on("destroy", function() { + event.removeListener(window, "resize", env.onResize); + env.editor.container.env = null; // prevent memory leak on old ie + }); + editor.container.env = editor.env = env; + return editor; +}; +exports.createEditSession = function(text, mode) { + var doc = new EditSession(text, mode); + doc.setUndoManager(new UndoManager()); + return doc; +} +exports.EditSession = EditSession; +exports.UndoManager = UndoManager; +}); + +define("ace/ext/textarea",["require","exports","module","ace/lib/event","ace/lib/useragent","ace/lib/net","ace/ace","ace/theme/textmate"], function(require, exports, module) { +"use strict"; + +var event = require("../lib/event"); +var UA = require("../lib/useragent"); +var net = require("../lib/net"); +var ace = require("../ace"); + +require("../theme/textmate"); + +module.exports = exports = ace; +var getCSSProperty = function(element, container, property) { + var ret = element.style[property]; + + if (!ret) { + if (window.getComputedStyle) { + ret = window.getComputedStyle(element, '').getPropertyValue(property); + } else { + ret = element.currentStyle[property]; + } + } + + if (!ret || ret == 'auto' || ret == 'intrinsic') { + ret = container.style[property]; + } + return ret; +}; + +function applyStyles(elm, styles) { + for (var style in styles) { + elm.style[style] = styles[style]; + } +} + +function setupContainer(element, getValue) { + if (element.type != 'textarea') { + throw new Error("Textarea required!"); + } + + var parentNode = element.parentNode; + var container = document.createElement('div'); + var resizeEvent = function() { + var style = 'position:relative;'; + [ + 'margin-top', 'margin-left', 'margin-right', 'margin-bottom' + ].forEach(function(item) { + style += item + ':' + + getCSSProperty(element, container, item) + ';'; + }); + var width = getCSSProperty(element, container, 'width') || (element.clientWidth + "px"); + var height = getCSSProperty(element, container, 'height') || (element.clientHeight + "px"); + style += 'height:' + height + ';width:' + width + ';'; + style += 'display:inline-block;'; + container.setAttribute('style', style); + }; + event.addListener(window, 'resize', resizeEvent); + resizeEvent(); + parentNode.insertBefore(container, element.nextSibling); + while (parentNode !== document) { + if (parentNode.tagName.toUpperCase() === 'FORM') { + var oldSumit = parentNode.onsubmit; + parentNode.onsubmit = function(evt) { + element.value = getValue(); + if (oldSumit) { + oldSumit.call(this, evt); + } + }; + break; + } + parentNode = parentNode.parentNode; + } + return container; +} + +exports.transformTextarea = function(element, options) { + var session; + var container = setupContainer(element, function() { + return session.getValue(); + }); + element.style.display = 'none'; + container.style.background = 'white'; + var editorDiv = document.createElement("div"); + applyStyles(editorDiv, { + top: "0px", + left: "0px", + right: "0px", + bottom: "0px", + border: "1px solid gray", + position: "absolute" + }); + container.appendChild(editorDiv); + + var settingOpener = document.createElement("div"); + applyStyles(settingOpener, { + position: "absolute", + right: "0px", + bottom: "0px", + background: "red", + cursor: "nw-resize", + borderStyle: "solid", + borderWidth: "9px 8px 10px 9px", + width: "2px", + borderColor: "lightblue gray gray lightblue", + zIndex: 101 + }); + + var settingDiv = document.createElement("div"); + var settingDivStyles = { + top: "0px", + left: "20%", + right: "0px", + bottom: "0px", + position: "absolute", + padding: "5px", + zIndex: 100, + color: "white", + display: "none", + overflow: "auto", + fontSize: "14px", + boxShadow: "-5px 2px 3px gray" + }; + if (!UA.isOldIE) { + settingDivStyles.backgroundColor = "rgba(0, 0, 0, 0.6)"; + } else { + settingDivStyles.backgroundColor = "#333"; + } + + applyStyles(settingDiv, settingDivStyles); + container.appendChild(settingDiv); + + options = options || exports.defaultOptions; + var editor = ace.edit(editorDiv); + session = editor.getSession(); + + session.setValue(element.value || element.innerHTML); + editor.focus(); + container.appendChild(settingOpener); + setupApi(editor, editorDiv, settingDiv, ace, options, load); + setupSettingPanel(settingDiv, settingOpener, editor); + + var state = ""; + event.addListener(settingOpener, "mousemove", function(e) { + var rect = this.getBoundingClientRect(); + var x = e.clientX - rect.left, y = e.clientY - rect.top; + if (x + y < (rect.width + rect.height)/2) { + this.style.cursor = "pointer"; + state = "toggle"; + } else { + state = "resize"; + this.style.cursor = "nw-resize"; + } + }); + + event.addListener(settingOpener, "mousedown", function(e) { + if (state == "toggle") { + editor.setDisplaySettings(); + return; + } + container.style.zIndex = 100000; + var rect = container.getBoundingClientRect(); + var startX = rect.width + rect.left - e.clientX; + var startY = rect.height + rect.top - e.clientY; + event.capture(settingOpener, function(e) { + container.style.width = e.clientX - rect.left + startX + "px"; + container.style.height = e.clientY - rect.top + startY + "px"; + editor.resize(); + }, function() {}); + }); + + return editor; +}; + +function load(url, module, callback) { + net.loadScript(url, function() { + require([module], callback); + }); +} + +function setupApi(editor, editorDiv, settingDiv, ace, options, loader) { + var session = editor.getSession(); + var renderer = editor.renderer; + loader = loader || load; + + function toBool(value) { + return value === "true" || value == true; + } + + editor.setDisplaySettings = function(display) { + if (display == null) + display = settingDiv.style.display == "none"; + if (display) { + settingDiv.style.display = "block"; + settingDiv.hideButton.focus(); + editor.on("focus", function onFocus() { + editor.removeListener("focus", onFocus); + settingDiv.style.display = "none"; + }); + } else { + editor.focus(); + } + }; + + editor.$setOption = editor.setOption; + editor.$getOption = editor.getOption; + editor.setOption = function(key, value) { + switch (key) { + case "mode": + editor.$setOption("mode", "ace/mode/" + value) + break; + case "theme": + editor.$setOption("theme", "ace/theme/" + value) + break; + case "keybindings": + switch (value) { + case "vim": + editor.setKeyboardHandler("ace/keyboard/vim"); + break; + case "emacs": + editor.setKeyboardHandler("ace/keyboard/emacs"); + break; + default: + editor.setKeyboardHandler(null); + } + break; + + case "softWrap": + case "fontSize": + editor.$setOption(key, value); + break; + + default: + editor.$setOption(key, toBool(value)); + } + }; + + editor.getOption = function(key) { + switch (key) { + case "mode": + return editor.$getOption("mode").substr("ace/mode/".length) + break; + + case "theme": + return editor.$getOption("theme").substr("ace/theme/".length) + break; + + case "keybindings": + var value = editor.getKeyboardHandler() + switch (value && value.$id) { + case "ace/keyboard/vim": + return "vim"; + case "ace/keyboard/emacs": + return "emacs"; + default: + return "ace"; + } + break; + + default: + return editor.$getOption(key); + } + }; + + editor.setOptions(options); + return editor; +} + +function setupSettingPanel(settingDiv, settingOpener, editor) { + var BOOL = null; + + var desc = { + mode: "Mode:", + wrap: "Soft Wrap:", + theme: "Theme:", + fontSize: "Font Size:", + showGutter: "Display Gutter:", + keybindings: "Keyboard", + showPrintMargin: "Show Print Margin:", + useSoftTabs: "Use Soft Tabs:", + showInvisibles: "Show Invisibles" + }; + + var optionValues = { + mode: { + text: "Plain", + javascript: "JavaScript", + xml: "XML", + html: "HTML", + css: "CSS", + scss: "SCSS", + python: "Python", + php: "PHP", + java: "Java", + ruby: "Ruby", + c_cpp: "C/C++", + coffee: "CoffeeScript", + json: "json", + perl: "Perl", + clojure: "Clojure", + ocaml: "OCaml", + csharp: "C#", + haxe: "haXe", + svg: "SVG", + textile: "Textile", + groovy: "Groovy", + liquid: "Liquid", + Scala: "Scala" + }, + theme: { + clouds: "Clouds", + clouds_midnight: "Clouds Midnight", + cobalt: "Cobalt", + crimson_editor: "Crimson Editor", + dawn: "Dawn", + eclipse: "Eclipse", + idle_fingers: "Idle Fingers", + kr_theme: "Kr Theme", + merbivore: "Merbivore", + merbivore_soft: "Merbivore Soft", + mono_industrial: "Mono Industrial", + monokai: "Monokai", + pastel_on_dark: "Pastel On Dark", + solarized_dark: "Solarized Dark", + solarized_light: "Solarized Light", + textmate: "Textmate", + twilight: "Twilight", + vibrant_ink: "Vibrant Ink" + }, + showGutter: BOOL, + fontSize: { + "10px": "10px", + "11px": "11px", + "12px": "12px", + "14px": "14px", + "16px": "16px" + }, + wrap: { + off: "Off", + 40: "40", + 80: "80", + free: "Free" + }, + keybindings: { + ace: "ace", + vim: "vim", + emacs: "emacs" + }, + showPrintMargin: BOOL, + useSoftTabs: BOOL, + showInvisibles: BOOL + }; + + var table = []; + table.push(""); + + function renderOption(builder, option, obj, cValue) { + if (!obj) { + builder.push( + "" + ); + return; + } + builder.push(""); + } + + for (var option in exports.defaultOptions) { + table.push(""); + table.push(""); + } + table.push("
SettingValue
", desc[option], ""); + renderOption(table, option, optionValues[option], editor.getOption(option)); + table.push("
"); + settingDiv.innerHTML = table.join(""); + + var onChange = function(e) { + var select = e.currentTarget; + editor.setOption(select.title, select.value); + }; + var onClick = function(e) { + var cb = e.currentTarget; + editor.setOption(cb.title, cb.checked); + }; + var selects = settingDiv.getElementsByTagName("select"); + for (var i = 0; i < selects.length; i++) + selects[i].onchange = onChange; + var cbs = settingDiv.getElementsByTagName("input"); + for (var i = 0; i < cbs.length; i++) + cbs[i].onclick = onClick; + + + var button = document.createElement("input"); + button.type = "button"; + button.value = "Hide"; + event.addListener(button, "click", function() { + editor.setDisplaySettings(false); + }); + settingDiv.appendChild(button); + settingDiv.hideButton = button; +} +exports.defaultOptions = { + mode: "javascript", + theme: "textmate", + wrap: "off", + fontSize: "12px", + showGutter: "false", + keybindings: "ace", + showPrintMargin: "false", + useSoftTabs: "true", + showInvisibles: "false" +}; + +}); + (function() { + window.require(["ace/ext/textarea"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-themelist.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-themelist.js new file mode 100644 index 00000000..5c5a60a9 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-themelist.js @@ -0,0 +1,58 @@ +define("ace/ext/themelist",["require","exports","module","ace/lib/fixoldbrowsers"], function(require, exports, module) { +"use strict"; +require("ace/lib/fixoldbrowsers"); + +var themeData = [ + ["Chrome" ], + ["Clouds" ], + ["Crimson Editor" ], + ["Dawn" ], + ["Dreamweaver" ], + ["Eclipse" ], + ["GitHub" ], + ["Solarized Light"], + ["TextMate" ], + ["Tomorrow" ], + ["XCode" ], + ["Kuroir"], + ["KatzenMilch"], + ["Ambiance" ,"ambiance" , "dark"], + ["Chaos" ,"chaos" , "dark"], + ["Clouds Midnight" ,"clouds_midnight" , "dark"], + ["Cobalt" ,"cobalt" , "dark"], + ["idle Fingers" ,"idle_fingers" , "dark"], + ["krTheme" ,"kr_theme" , "dark"], + ["Merbivore" ,"merbivore" , "dark"], + ["Merbivore Soft" ,"merbivore_soft" , "dark"], + ["Mono Industrial" ,"mono_industrial" , "dark"], + ["Monokai" ,"monokai" , "dark"], + ["Pastel on dark" ,"pastel_on_dark" , "dark"], + ["Solarized Dark" ,"solarized_dark" , "dark"], + ["Terminal" ,"terminal" , "dark"], + ["Tomorrow Night" ,"tomorrow_night" , "dark"], + ["Tomorrow Night Blue" ,"tomorrow_night_blue" , "dark"], + ["Tomorrow Night Bright","tomorrow_night_bright" , "dark"], + ["Tomorrow Night 80s" ,"tomorrow_night_eighties" , "dark"], + ["Twilight" ,"twilight" , "dark"], + ["Vibrant Ink" ,"vibrant_ink" , "dark"] +]; + + +exports.themesByName = {}; +exports.themes = themeData.map(function(data) { + var name = data[1] || data[0].replace(/ /g, "_").toLowerCase(); + var theme = { + caption: data[0], + theme: "ace/theme/" + name, + isDark: data[2] == "dark", + name: name + }; + exports.themesByName[name] = theme; + return theme; +}); + +}); + (function() { + window.require(["ace/ext/themelist"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/ext-whitespace.js b/Patent2Net/media/graph-recipes/app/assets/ace/ext-whitespace.js new file mode 100644 index 00000000..4cc97591 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/ext-whitespace.js @@ -0,0 +1,181 @@ +define("ace/ext/whitespace",["require","exports","module","ace/lib/lang"], function(require, exports, module) { +"use strict"; + +var lang = require("../lib/lang"); +exports.$detectIndentation = function(lines, fallback) { + var stats = []; + var changes = []; + var tabIndents = 0; + var prevSpaces = 0; + var max = Math.min(lines.length, 1000); + for (var i = 0; i < max; i++) { + var line = lines[i]; + if (!/^\s*[^*+\-\s]/.test(line)) + continue; + + if (line[0] == "\t") + tabIndents++; + + var spaces = line.match(/^ */)[0].length; + if (spaces && line[spaces] != "\t") { + var diff = spaces - prevSpaces; + if (diff > 0 && !(prevSpaces%diff) && !(spaces%diff)) + changes[diff] = (changes[diff] || 0) + 1; + + stats[spaces] = (stats[spaces] || 0) + 1; + } + prevSpaces = spaces; + while (i < max && line[line.length - 1] == "\\") + line = lines[i++]; + } + + function getScore(indent) { + var score = 0; + for (var i = indent; i < stats.length; i += indent) + score += stats[i] || 0; + return score; + } + + var changesTotal = changes.reduce(function(a,b){return a+b}, 0); + + var first = {score: 0, length: 0}; + var spaceIndents = 0; + for (var i = 1; i < 12; i++) { + var score = getScore(i); + if (i == 1) { + spaceIndents = score; + score = stats[1] ? 0.9 : 0.8; + if (!stats.length) + score = 0 + } else + score /= spaceIndents; + + if (changes[i]) + score += changes[i] / changesTotal; + + if (score > first.score) + first = {score: score, length: i}; + } + + if (first.score && first.score > 1.4) + var tabLength = first.length; + + if (tabIndents > spaceIndents + 1) + return {ch: "\t", length: tabLength}; + + if (spaceIndents > tabIndents + 1) + return {ch: " ", length: tabLength}; +}; + +exports.detectIndentation = function(session) { + var lines = session.getLines(0, 1000); + var indent = exports.$detectIndentation(lines) || {}; + + if (indent.ch) + session.setUseSoftTabs(indent.ch == " "); + + if (indent.length) + session.setTabSize(indent.length); + return indent; +}; + +exports.trimTrailingSpace = function(session, trimEmpty) { + var doc = session.getDocument(); + var lines = doc.getAllLines(); + + var min = trimEmpty ? -1 : 0; + + for (var i = 0, l=lines.length; i < l; i++) { + var line = lines[i]; + var index = line.search(/\s+$/); + + if (index > min) + doc.removeInLine(i, index, line.length); + } +}; + +exports.convertIndentation = function(session, ch, len) { + var oldCh = session.getTabString()[0]; + var oldLen = session.getTabSize(); + if (!len) len = oldLen; + if (!ch) ch = oldCh; + + var tab = ch == "\t" ? ch: lang.stringRepeat(ch, len); + + var doc = session.doc; + var lines = doc.getAllLines(); + + var cache = {}; + var spaceCache = {}; + for (var i = 0, l=lines.length; i < l; i++) { + var line = lines[i]; + var match = line.match(/^\s*/)[0]; + if (match) { + var w = session.$getStringScreenWidth(match)[0]; + var tabCount = Math.floor(w/oldLen); + var reminder = w%oldLen; + var toInsert = cache[tabCount] || (cache[tabCount] = lang.stringRepeat(tab, tabCount)); + toInsert += spaceCache[reminder] || (spaceCache[reminder] = lang.stringRepeat(" ", reminder)); + + if (toInsert != match) { + doc.removeInLine(i, 0, match.length); + doc.insertInLine({row: i, column: 0}, toInsert); + } + } + } + session.setTabSize(len); + session.setUseSoftTabs(ch == " "); +}; + +exports.$parseStringArg = function(text) { + var indent = {}; + if (/t/.test(text)) + indent.ch = "\t"; + else if (/s/.test(text)) + indent.ch = " "; + var m = text.match(/\d+/); + if (m) + indent.length = parseInt(m[0], 10); + return indent; +}; + +exports.$parseArg = function(arg) { + if (!arg) + return {}; + if (typeof arg == "string") + return exports.$parseStringArg(arg); + if (typeof arg.text == "string") + return exports.$parseStringArg(arg.text); + return arg; +}; + +exports.commands = [{ + name: "detectIndentation", + exec: function(editor) { + exports.detectIndentation(editor.session); + } +}, { + name: "trimTrailingSpace", + exec: function(editor) { + exports.trimTrailingSpace(editor.session); + } +}, { + name: "convertIndentation", + exec: function(editor, arg) { + var indent = exports.$parseArg(arg); + exports.convertIndentation(editor.session, indent.ch, indent.length); + } +}, { + name: "setIndentation", + exec: function(editor, arg) { + var indent = exports.$parseArg(arg); + indent.length && editor.session.setTabSize(indent.length); + indent.ch && editor.session.setUseSoftTabs(indent.ch == " "); + } +}]; + +}); + (function() { + window.require(["ace/ext/whitespace"], function() {}); + })(); + \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/keybinding-emacs.js b/Patent2Net/media/graph-recipes/app/assets/ace/keybinding-emacs.js new file mode 100644 index 00000000..92c263c8 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/keybinding-emacs.js @@ -0,0 +1,1182 @@ +define("ace/occur",["require","exports","module","ace/lib/oop","ace/range","ace/search","ace/edit_session","ace/search_highlight","ace/lib/dom"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var Range = require("./range").Range; +var Search = require("./search").Search; +var EditSession = require("./edit_session").EditSession; +var SearchHighlight = require("./search_highlight").SearchHighlight; +function Occur() {} + +oop.inherits(Occur, Search); + +(function() { + this.enter = function(editor, options) { + if (!options.needle) return false; + var pos = editor.getCursorPosition(); + this.displayOccurContent(editor, options); + var translatedPos = this.originalToOccurPosition(editor.session, pos); + editor.moveCursorToPosition(translatedPos); + return true; + } + this.exit = function(editor, options) { + var pos = options.translatePosition && editor.getCursorPosition(); + var translatedPos = pos && this.occurToOriginalPosition(editor.session, pos); + this.displayOriginalContent(editor); + if (translatedPos) + editor.moveCursorToPosition(translatedPos); + return true; + } + + this.highlight = function(sess, regexp) { + var hl = sess.$occurHighlight = sess.$occurHighlight || sess.addDynamicMarker( + new SearchHighlight(null, "ace_occur-highlight", "text")); + hl.setRegexp(regexp); + sess._emit("changeBackMarker"); // force highlight layer redraw + } + + this.displayOccurContent = function(editor, options) { + this.$originalSession = editor.session; + var found = this.matchingLines(editor.session, options); + var lines = found.map(function(foundLine) { return foundLine.content; }); + var occurSession = new EditSession(lines.join('\n')); + occurSession.$occur = this; + occurSession.$occurMatchingLines = found; + editor.setSession(occurSession); + this.$useEmacsStyleLineStart = this.$originalSession.$useEmacsStyleLineStart; + occurSession.$useEmacsStyleLineStart = this.$useEmacsStyleLineStart; + this.highlight(occurSession, options.re); + occurSession._emit('changeBackMarker'); + } + + this.displayOriginalContent = function(editor) { + editor.setSession(this.$originalSession); + this.$originalSession.$useEmacsStyleLineStart = this.$useEmacsStyleLineStart; + } + this.originalToOccurPosition = function(session, pos) { + var lines = session.$occurMatchingLines; + var nullPos = {row: 0, column: 0}; + if (!lines) return nullPos; + for (var i = 0; i < lines.length; i++) { + if (lines[i].row === pos.row) + return {row: i, column: pos.column}; + } + return nullPos; + } + this.occurToOriginalPosition = function(session, pos) { + var lines = session.$occurMatchingLines; + if (!lines || !lines[pos.row]) + return pos; + return {row: lines[pos.row].row, column: pos.column}; + } + + this.matchingLines = function(session, options) { + options = oop.mixin({}, options); + if (!session || !options.needle) return []; + var search = new Search(); + search.set(options); + return search.findAll(session).reduce(function(lines, range) { + var row = range.start.row; + var last = lines[lines.length-1]; + return last && last.row === row ? + lines : + lines.concat({row: row, content: session.getLine(row)}); + }, []); + } + +}).call(Occur.prototype); + +var dom = require('./lib/dom'); +dom.importCssString(".ace_occur-highlight {\n\ + border-radius: 4px;\n\ + background-color: rgba(87, 255, 8, 0.25);\n\ + position: absolute;\n\ + z-index: 4;\n\ + -moz-box-sizing: border-box;\n\ + -webkit-box-sizing: border-box;\n\ + box-sizing: border-box;\n\ + box-shadow: 0 0 4px rgb(91, 255, 50);\n\ +}\n\ +.ace_dark .ace_occur-highlight {\n\ + background-color: rgb(80, 140, 85);\n\ + box-shadow: 0 0 4px rgb(60, 120, 70);\n\ +}\n", "incremental-occur-highlighting"); + +exports.Occur = Occur; + +}); + +define("ace/commands/occur_commands",["require","exports","module","ace/config","ace/occur","ace/keyboard/hash_handler","ace/lib/oop"], function(require, exports, module) { + +var config = require("../config"), + Occur = require("../occur").Occur; +var occurStartCommand = { + name: "occur", + exec: function(editor, options) { + var alreadyInOccur = !!editor.session.$occur; + var occurSessionActive = new Occur().enter(editor, options); + if (occurSessionActive && !alreadyInOccur) + OccurKeyboardHandler.installIn(editor); + }, + readOnly: true +}; + +var occurCommands = [{ + name: "occurexit", + bindKey: 'esc|Ctrl-G', + exec: function(editor) { + var occur = editor.session.$occur; + if (!occur) return; + occur.exit(editor, {}); + if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor); + }, + readOnly: true +}, { + name: "occuraccept", + bindKey: 'enter', + exec: function(editor) { + var occur = editor.session.$occur; + if (!occur) return; + occur.exit(editor, {translatePosition: true}); + if (!editor.session.$occur) OccurKeyboardHandler.uninstallFrom(editor); + }, + readOnly: true +}]; + +var HashHandler = require("../keyboard/hash_handler").HashHandler; +var oop = require("../lib/oop"); + + +function OccurKeyboardHandler() {} + +oop.inherits(OccurKeyboardHandler, HashHandler); + +;(function() { + + this.isOccurHandler = true; + + this.attach = function(editor) { + HashHandler.call(this, occurCommands, editor.commands.platform); + this.$editor = editor; + } + + var handleKeyboard$super = this.handleKeyboard; + this.handleKeyboard = function(data, hashId, key, keyCode) { + var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode); + return (cmd && cmd.command) ? cmd : undefined; + } + +}).call(OccurKeyboardHandler.prototype); + +OccurKeyboardHandler.installIn = function(editor) { + var handler = new this(); + editor.keyBinding.addKeyboardHandler(handler); + editor.commands.addCommands(occurCommands); +} + +OccurKeyboardHandler.uninstallFrom = function(editor) { + editor.commands.removeCommands(occurCommands); + var handler = editor.getKeyboardHandler(); + if (handler.isOccurHandler) + editor.keyBinding.removeKeyboardHandler(handler); +} + +exports.occurStartCommand = occurStartCommand; + +}); + +define("ace/commands/incremental_search_commands",["require","exports","module","ace/config","ace/lib/oop","ace/keyboard/hash_handler","ace/commands/occur_commands"], function(require, exports, module) { + +var config = require("../config"); +var oop = require("../lib/oop"); +var HashHandler = require("../keyboard/hash_handler").HashHandler; +var occurStartCommand = require("./occur_commands").occurStartCommand; +exports.iSearchStartCommands = [{ + name: "iSearch", + bindKey: {win: "Ctrl-F", mac: "Command-F"}, + exec: function(editor, options) { + config.loadModule(["core", "ace/incremental_search"], function(e) { + var iSearch = e.iSearch = e.iSearch || new e.IncrementalSearch(); + iSearch.activate(editor, options.backwards); + if (options.jumpToFirstMatch) iSearch.next(options); + }); + }, + readOnly: true +}, { + name: "iSearchBackwards", + exec: function(editor, jumpToNext) { editor.execCommand('iSearch', {backwards: true}); }, + readOnly: true +}, { + name: "iSearchAndGo", + bindKey: {win: "Ctrl-K", mac: "Command-G"}, + exec: function(editor, jumpToNext) { editor.execCommand('iSearch', {jumpToFirstMatch: true, useCurrentOrPrevSearch: true}); }, + readOnly: true +}, { + name: "iSearchBackwardsAndGo", + bindKey: {win: "Ctrl-Shift-K", mac: "Command-Shift-G"}, + exec: function(editor) { editor.execCommand('iSearch', {jumpToFirstMatch: true, backwards: true, useCurrentOrPrevSearch: true}); }, + readOnly: true +}]; +exports.iSearchCommands = [{ + name: "restartSearch", + bindKey: {win: "Ctrl-F", mac: "Command-F"}, + exec: function(iSearch) { + iSearch.cancelSearch(true); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: "searchForward", + bindKey: {win: "Ctrl-S|Ctrl-K", mac: "Ctrl-S|Command-G"}, + exec: function(iSearch, options) { + options.useCurrentOrPrevSearch = true; + iSearch.next(options); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: "searchBackward", + bindKey: {win: "Ctrl-R|Ctrl-Shift-K", mac: "Ctrl-R|Command-Shift-G"}, + exec: function(iSearch, options) { + options.useCurrentOrPrevSearch = true; + options.backwards = true; + iSearch.next(options); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: "extendSearchTerm", + exec: function(iSearch, string) { + iSearch.addString(string); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: "extendSearchTermSpace", + bindKey: "space", + exec: function(iSearch) { iSearch.addString(' '); }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: "shrinkSearchTerm", + bindKey: "backspace", + exec: function(iSearch) { + iSearch.removeChar(); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: 'confirmSearch', + bindKey: 'return', + exec: function(iSearch) { iSearch.deactivate(); }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: 'cancelSearch', + bindKey: 'esc|Ctrl-G', + exec: function(iSearch) { iSearch.deactivate(true); }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: 'occurisearch', + bindKey: 'Ctrl-O', + exec: function(iSearch) { + var options = oop.mixin({}, iSearch.$options); + iSearch.deactivate(); + occurStartCommand.exec(iSearch.$editor, options); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: "yankNextWord", + bindKey: "Ctrl-w", + exec: function(iSearch) { + var ed = iSearch.$editor, + range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorWordRight(); }), + string = ed.session.getTextRange(range); + iSearch.addString(string); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: "yankNextChar", + bindKey: "Ctrl-Alt-y", + exec: function(iSearch) { + var ed = iSearch.$editor, + range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorRight(); }), + string = ed.session.getTextRange(range); + iSearch.addString(string); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: 'recenterTopBottom', + bindKey: 'Ctrl-l', + exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: 'selectAllMatches', + bindKey: 'Ctrl-space', + exec: function(iSearch) { + var ed = iSearch.$editor, + hl = ed.session.$isearchHighlight, + ranges = hl && hl.cache ? hl.cache + .reduce(function(ranges, ea) { + return ranges.concat(ea ? ea : []); }, []) : []; + iSearch.deactivate(false); + ranges.forEach(ed.selection.addRange.bind(ed.selection)); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: 'searchAsRegExp', + bindKey: 'Alt-r', + exec: function(iSearch) { + iSearch.convertNeedleToRegExp(); + }, + readOnly: true, + isIncrementalSearchCommand: true +}]; + +function IncrementalSearchKeyboardHandler(iSearch) { + this.$iSearch = iSearch; +} + +oop.inherits(IncrementalSearchKeyboardHandler, HashHandler); + +;(function() { + + this.attach = function(editor) { + var iSearch = this.$iSearch; + HashHandler.call(this, exports.iSearchCommands, editor.commands.platform); + this.$commandExecHandler = editor.commands.addEventListener('exec', function(e) { + if (!e.command.isIncrementalSearchCommand) return undefined; + e.stopPropagation(); + e.preventDefault(); + return e.command.exec(iSearch, e.args || {}); + }); + } + + this.detach = function(editor) { + if (!this.$commandExecHandler) return; + editor.commands.removeEventListener('exec', this.$commandExecHandler); + delete this.$commandExecHandler; + } + + var handleKeyboard$super = this.handleKeyboard; + this.handleKeyboard = function(data, hashId, key, keyCode) { + if (((hashId === 1/*ctrl*/ || hashId === 8/*command*/) && key === 'v') + || (hashId === 1/*ctrl*/ && key === 'y')) return null; + var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode); + if (cmd.command) { return cmd; } + if (hashId == -1) { + var extendCmd = this.commands.extendSearchTerm; + if (extendCmd) { return {command: extendCmd, args: key}; } + } + return {command: "null", passEvent: hashId == 0 || hashId == 4}; + } + +}).call(IncrementalSearchKeyboardHandler.prototype); + + +exports.IncrementalSearchKeyboardHandler = IncrementalSearchKeyboardHandler; + +}); + +define("ace/incremental_search",["require","exports","module","ace/lib/oop","ace/range","ace/search","ace/search_highlight","ace/commands/incremental_search_commands","ace/lib/dom","ace/commands/command_manager","ace/editor","ace/config"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var Range = require("./range").Range; +var Search = require("./search").Search; +var SearchHighlight = require("./search_highlight").SearchHighlight; +var iSearchCommandModule = require("./commands/incremental_search_commands"); +var ISearchKbd = iSearchCommandModule.IncrementalSearchKeyboardHandler; +function IncrementalSearch() { + this.$options = {wrap: false, skipCurrent: false}; + this.$keyboardHandler = new ISearchKbd(this); +} + +oop.inherits(IncrementalSearch, Search); + +function isRegExp(obj) { + return obj instanceof RegExp; +} + +function regExpToObject(re) { + var string = String(re), + start = string.indexOf('/'), + flagStart = string.lastIndexOf('/'); + return { + expression: string.slice(start+1, flagStart), + flags: string.slice(flagStart+1) + } +} + +function stringToRegExp(string, flags) { + try { + return new RegExp(string, flags); + } catch (e) { return string; } +} + +function objectToRegExp(obj) { + return stringToRegExp(obj.expression, obj.flags); +} + +;(function() { + + this.activate = function(ed, backwards) { + this.$editor = ed; + this.$startPos = this.$currentPos = ed.getCursorPosition(); + this.$options.needle = ''; + this.$options.backwards = backwards; + ed.keyBinding.addKeyboardHandler(this.$keyboardHandler); + this.$originalEditorOnPaste = ed.onPaste; ed.onPaste = this.onPaste.bind(this); + this.$mousedownHandler = ed.addEventListener('mousedown', this.onMouseDown.bind(this)); + this.selectionFix(ed); + this.statusMessage(true); + } + + this.deactivate = function(reset) { + this.cancelSearch(reset); + var ed = this.$editor; + ed.keyBinding.removeKeyboardHandler(this.$keyboardHandler); + if (this.$mousedownHandler) { + ed.removeEventListener('mousedown', this.$mousedownHandler); + delete this.$mousedownHandler; + } + ed.onPaste = this.$originalEditorOnPaste; + this.message(''); + } + + this.selectionFix = function(editor) { + if (editor.selection.isEmpty() && !editor.session.$emacsMark) { + editor.clearSelection(); + } + } + + this.highlight = function(regexp) { + var sess = this.$editor.session, + hl = sess.$isearchHighlight = sess.$isearchHighlight || sess.addDynamicMarker( + new SearchHighlight(null, "ace_isearch-result", "text")); + hl.setRegexp(regexp); + sess._emit("changeBackMarker"); // force highlight layer redraw + } + + this.cancelSearch = function(reset) { + var e = this.$editor; + this.$prevNeedle = this.$options.needle; + this.$options.needle = ''; + if (reset) { + e.moveCursorToPosition(this.$startPos); + this.$currentPos = this.$startPos; + } else { + e.pushEmacsMark && e.pushEmacsMark(this.$startPos, false); + } + this.highlight(null); + return Range.fromPoints(this.$currentPos, this.$currentPos); + } + + this.highlightAndFindWithNeedle = function(moveToNext, needleUpdateFunc) { + if (!this.$editor) return null; + var options = this.$options; + if (needleUpdateFunc) { + options.needle = needleUpdateFunc.call(this, options.needle || '') || ''; + } + if (options.needle.length === 0) { + this.statusMessage(true); + return this.cancelSearch(true); + }; + options.start = this.$currentPos; + var session = this.$editor.session, + found = this.find(session), + shouldSelect = this.$editor.emacsMark ? + !!this.$editor.emacsMark() : !this.$editor.selection.isEmpty(); + if (found) { + if (options.backwards) found = Range.fromPoints(found.end, found.start); + this.$editor.selection.setRange(Range.fromPoints(shouldSelect ? this.$startPos : found.end, found.end)); + if (moveToNext) this.$currentPos = found.end; + this.highlight(options.re) + } + + this.statusMessage(found); + + return found; + } + + this.addString = function(s) { + return this.highlightAndFindWithNeedle(false, function(needle) { + if (!isRegExp(needle)) + return needle + s; + var reObj = regExpToObject(needle); + reObj.expression += s; + return objectToRegExp(reObj); + }); + } + + this.removeChar = function(c) { + return this.highlightAndFindWithNeedle(false, function(needle) { + if (!isRegExp(needle)) + return needle.substring(0, needle.length-1); + var reObj = regExpToObject(needle); + reObj.expression = reObj.expression.substring(0, reObj.expression.length-1); + return objectToRegExp(reObj); + }); + } + + this.next = function(options) { + options = options || {}; + this.$options.backwards = !!options.backwards; + this.$currentPos = this.$editor.getCursorPosition(); + return this.highlightAndFindWithNeedle(true, function(needle) { + return options.useCurrentOrPrevSearch && needle.length === 0 ? + this.$prevNeedle || '' : needle; + }); + } + + this.onMouseDown = function(evt) { + this.deactivate(); + return true; + } + + this.onPaste = function(text) { + this.addString(text); + } + + this.convertNeedleToRegExp = function() { + return this.highlightAndFindWithNeedle(false, function(needle) { + return isRegExp(needle) ? needle : stringToRegExp(needle, 'ig'); + }); + } + + this.convertNeedleToString = function() { + return this.highlightAndFindWithNeedle(false, function(needle) { + return isRegExp(needle) ? regExpToObject(needle).expression : needle; + }); + } + + this.statusMessage = function(found) { + var options = this.$options, msg = ''; + msg += options.backwards ? 'reverse-' : ''; + msg += 'isearch: ' + options.needle; + msg += found ? '' : ' (not found)'; + this.message(msg); + } + + this.message = function(msg) { + if (this.$editor.showCommandLine) { + this.$editor.showCommandLine(msg); + this.$editor.focus(); + } else { + console.log(msg); + } + } + +}).call(IncrementalSearch.prototype); + + +exports.IncrementalSearch = IncrementalSearch; + +var dom = require('./lib/dom'); +dom.importCssString && dom.importCssString("\ +.ace_marker-layer .ace_isearch-result {\ + position: absolute;\ + z-index: 6;\ + -moz-box-sizing: border-box;\ + -webkit-box-sizing: border-box;\ + box-sizing: border-box;\ +}\ +div.ace_isearch-result {\ + border-radius: 4px;\ + background-color: rgba(255, 200, 0, 0.5);\ + box-shadow: 0 0 4px rgb(255, 200, 0);\ +}\ +.ace_dark div.ace_isearch-result {\ + background-color: rgb(100, 110, 160);\ + box-shadow: 0 0 4px rgb(80, 90, 140);\ +}", "incremental-search-highlighting"); +var commands = require("./commands/command_manager"); +(function() { + this.setupIncrementalSearch = function(editor, val) { + if (this.usesIncrementalSearch == val) return; + this.usesIncrementalSearch = val; + var iSearchCommands = iSearchCommandModule.iSearchStartCommands; + var method = val ? 'addCommands' : 'removeCommands'; + this[method](iSearchCommands); + }; +}).call(commands.CommandManager.prototype); +var Editor = require("./editor").Editor; +require("./config").defineOptions(Editor.prototype, "editor", { + useIncrementalSearch: { + set: function(val) { + this.keyBinding.$handlers.forEach(function(handler) { + if (handler.setupIncrementalSearch) { + handler.setupIncrementalSearch(this, val); + } + }); + this._emit('incrementalSearchSettingChanged', {isEnabled: val}); + } + } +}); + +}); + +define("ace/keyboard/emacs",["require","exports","module","ace/lib/dom","ace/incremental_search","ace/commands/incremental_search_commands","ace/keyboard/hash_handler","ace/lib/keys"], function(require, exports, module) { +"use strict"; + +var dom = require("../lib/dom"); +require("../incremental_search"); +var iSearchCommandModule = require("../commands/incremental_search_commands"); + + +var screenToTextBlockCoordinates = function(x, y) { + var canvasPos = this.scroller.getBoundingClientRect(); + + var col = Math.floor( + (x + this.scrollLeft - canvasPos.left - this.$padding) / this.characterWidth + ); + var row = Math.floor( + (y + this.scrollTop - canvasPos.top) / this.lineHeight + ); + + return this.session.screenToDocumentPosition(row, col); +}; + +var HashHandler = require("./hash_handler").HashHandler; +exports.handler = new HashHandler(); + +exports.handler.isEmacs = true; +exports.handler.$id = "ace/keyboard/emacs"; + +var initialized = false; +var $formerLongWords; +var $formerLineStart; + +exports.handler.attach = function(editor) { + if (!initialized) { + initialized = true; + dom.importCssString('\ + .emacs-mode .ace_cursor{\ + border: 1px rgba(50,250,50,0.8) solid!important;\ + -moz-box-sizing: border-box!important;\ + -webkit-box-sizing: border-box!important;\ + box-sizing: border-box!important;\ + background-color: rgba(0,250,0,0.9);\ + opacity: 0.5;\ + }\ + .emacs-mode .ace_hidden-cursors .ace_cursor{\ + opacity: 1;\ + background-color: transparent;\ + }\ + .emacs-mode .ace_overwrite-cursors .ace_cursor {\ + opacity: 1;\ + background-color: transparent;\ + border-width: 0 0 2px 2px !important;\ + }\ + .emacs-mode .ace_text-layer {\ + z-index: 4\ + }\ + .emacs-mode .ace_cursor-layer {\ + z-index: 2\ + }', 'emacsMode' + ); + } + $formerLongWords = editor.session.$selectLongWords; + editor.session.$selectLongWords = true; + $formerLineStart = editor.session.$useEmacsStyleLineStart; + editor.session.$useEmacsStyleLineStart = true; + + editor.session.$emacsMark = null; // the active mark + editor.session.$emacsMarkRing = editor.session.$emacsMarkRing || []; + + editor.emacsMark = function() { + return this.session.$emacsMark; + }; + + editor.setEmacsMark = function(p) { + this.session.$emacsMark = p; + }; + + editor.pushEmacsMark = function(p, activate) { + var prevMark = this.session.$emacsMark; + if (prevMark) + this.session.$emacsMarkRing.push(prevMark); + if (!p || activate) this.setEmacsMark(p); + else this.session.$emacsMarkRing.push(p); + }; + + editor.popEmacsMark = function() { + var mark = this.emacsMark(); + if (mark) { this.setEmacsMark(null); return mark; } + return this.session.$emacsMarkRing.pop(); + }; + + editor.getLastEmacsMark = function(p) { + return this.session.$emacsMark || this.session.$emacsMarkRing.slice(-1)[0]; + }; + + editor.emacsMarkForSelection = function(replacement) { + var sel = this.selection, + multiRangeLength = this.multiSelect ? + this.multiSelect.getAllRanges().length : 1, + selIndex = sel.index || 0, + markRing = this.session.$emacsMarkRing, + markIndex = markRing.length - (multiRangeLength - selIndex), + lastMark = markRing[markIndex] || sel.anchor; + if (replacement) { + markRing.splice(markIndex, 1, + "row" in replacement && "column" in replacement ? + replacement : undefined); + } + return lastMark; + } + + editor.on("click", $resetMarkMode); + editor.on("changeSession", $kbSessionChange); + editor.renderer.screenToTextCoordinates = screenToTextBlockCoordinates; + editor.setStyle("emacs-mode"); + editor.commands.addCommands(commands); + exports.handler.platform = editor.commands.platform; + editor.$emacsModeHandler = this; + editor.addEventListener('copy', this.onCopy); + editor.addEventListener('paste', this.onPaste); +}; + +exports.handler.detach = function(editor) { + delete editor.renderer.screenToTextCoordinates; + editor.session.$selectLongWords = $formerLongWords; + editor.session.$useEmacsStyleLineStart = $formerLineStart; + editor.removeEventListener("click", $resetMarkMode); + editor.removeEventListener("changeSession", $kbSessionChange); + editor.unsetStyle("emacs-mode"); + editor.commands.removeCommands(commands); + editor.removeEventListener('copy', this.onCopy); + editor.removeEventListener('paste', this.onPaste); + editor.$emacsModeHandler = null; +}; + +var $kbSessionChange = function(e) { + if (e.oldSession) { + e.oldSession.$selectLongWords = $formerLongWords; + e.oldSession.$useEmacsStyleLineStart = $formerLineStart; + } + + $formerLongWords = e.session.$selectLongWords; + e.session.$selectLongWords = true; + $formerLineStart = e.session.$useEmacsStyleLineStart; + e.session.$useEmacsStyleLineStart = true; + + if (!e.session.hasOwnProperty('$emacsMark')) + e.session.$emacsMark = null; + if (!e.session.hasOwnProperty('$emacsMarkRing')) + e.session.$emacsMarkRing = []; +}; + +var $resetMarkMode = function(e) { + e.editor.session.$emacsMark = null; +}; + +var keys = require("../lib/keys").KEY_MODS; +var eMods = {C: "ctrl", S: "shift", M: "alt", CMD: "command"}; +var combinations = ["C-S-M-CMD", + "S-M-CMD", "C-M-CMD", "C-S-CMD", "C-S-M", + "M-CMD", "S-CMD", "S-M", "C-CMD", "C-M", "C-S", + "CMD", "M", "S", "C"]; +combinations.forEach(function(c) { + var hashId = 0; + c.split("-").forEach(function(c) { + hashId = hashId | keys[eMods[c]]; + }); + eMods[hashId] = c.toLowerCase() + "-"; +}); + +exports.handler.onCopy = function(e, editor) { + if (editor.$handlesEmacsOnCopy) return; + editor.$handlesEmacsOnCopy = true; + exports.handler.commands.killRingSave.exec(editor); + editor.$handlesEmacsOnCopy = false; +}; + +exports.handler.onPaste = function(e, editor) { + editor.pushEmacsMark(editor.getCursorPosition()); +}; + +exports.handler.bindKey = function(key, command) { + if (typeof key == "object") + key = key[this.platform]; + if (!key) + return; + + var ckb = this.commandKeyBinding; + key.split("|").forEach(function(keyPart) { + keyPart = keyPart.toLowerCase(); + ckb[keyPart] = command; + var keyParts = keyPart.split(" ").slice(0,-1); + keyParts.reduce(function(keyMapKeys, keyPart, i) { + var prefix = keyMapKeys[i-1] ? keyMapKeys[i-1] + ' ' : ''; + return keyMapKeys.concat([prefix + keyPart]); + }, []).forEach(function(keyPart) { + if (!ckb[keyPart]) ckb[keyPart] = "null"; + }); + }, this); +}; + +exports.handler.getStatusText = function(editor, data) { + var str = ""; + if (data.count) + str += data.count; + if (data.keyChain) + str += " " + data.keyChain + return str; +}; + +exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { + if (keyCode === -1) return undefined; + + var editor = data.editor; + editor._signal("changeStatus"); + if (hashId == -1) { + editor.pushEmacsMark(); + if (data.count) { + var str = new Array(data.count + 1).join(key); + data.count = null; + return {command: "insertstring", args: str}; + } + } + + var modifier = eMods[hashId]; + if (modifier == "c-" || data.count) { + var count = parseInt(key[key.length - 1]); + if (typeof count === 'number' && !isNaN(count)) { + data.count = Math.max(data.count, 0) || 0; + data.count = 10 * data.count + count; + return {command: "null"}; + } + } + if (modifier) key = modifier + key; + if (data.keyChain) key = data.keyChain += " " + key; + var command = this.commandKeyBinding[key]; + data.keyChain = command == "null" ? key : ""; + if (!command) return undefined; + if (command === "null") return {command: "null"}; + + if (command === "universalArgument") { + data.count = -4; + return {command: "null"}; + } + var args; + if (typeof command !== "string") { + args = command.args; + if (command.command) command = command.command; + if (command === "goorselect") { + command = editor.emacsMark() ? args[1] : args[0]; + args = null; + } + } + + if (typeof command === "string") { + if (command === "insertstring" || + command === "splitline" || + command === "togglecomment") { + editor.pushEmacsMark(); + } + command = this.commands[command] || editor.commands.commands[command]; + if (!command) return undefined; + } + + if (!command.readOnly && !command.isYank) + data.lastCommand = null; + + if (!command.readOnly && editor.emacsMark()) + editor.setEmacsMark(null) + + if (data.count) { + var count = data.count; + data.count = 0; + if (!command || !command.handlesCount) { + return { + args: args, + command: { + exec: function(editor, args) { + for (var i = 0; i < count; i++) + command.exec(editor, args); + }, + multiSelectAction: command.multiSelectAction + } + }; + } else { + if (!args) args = {}; + if (typeof args === 'object') args.count = count; + } + } + + return {command: command, args: args}; +}; + +exports.emacsKeys = { + "Up|C-p" : {command: "goorselect", args: ["golineup","selectup"]}, + "Down|C-n" : {command: "goorselect", args: ["golinedown","selectdown"]}, + "Left|C-b" : {command: "goorselect", args: ["gotoleft","selectleft"]}, + "Right|C-f" : {command: "goorselect", args: ["gotoright","selectright"]}, + "C-Left|M-b" : {command: "goorselect", args: ["gotowordleft","selectwordleft"]}, + "C-Right|M-f" : {command: "goorselect", args: ["gotowordright","selectwordright"]}, + "Home|C-a" : {command: "goorselect", args: ["gotolinestart","selecttolinestart"]}, + "End|C-e" : {command: "goorselect", args: ["gotolineend","selecttolineend"]}, + "C-Home|S-M-,": {command: "goorselect", args: ["gotostart","selecttostart"]}, + "C-End|S-M-." : {command: "goorselect", args: ["gotoend","selecttoend"]}, + "S-Up|S-C-p" : "selectup", + "S-Down|S-C-n" : "selectdown", + "S-Left|S-C-b" : "selectleft", + "S-Right|S-C-f" : "selectright", + "S-C-Left|S-M-b" : "selectwordleft", + "S-C-Right|S-M-f" : "selectwordright", + "S-Home|S-C-a" : "selecttolinestart", + "S-End|S-C-e" : "selecttolineend", + "S-C-Home" : "selecttostart", + "S-C-End" : "selecttoend", + + "C-l" : "recenterTopBottom", + "M-s" : "centerselection", + "M-g": "gotoline", + "C-x C-p": "selectall", + "C-Down": {command: "goorselect", args: ["gotopagedown","selectpagedown"]}, + "C-Up": {command: "goorselect", args: ["gotopageup","selectpageup"]}, + "PageDown|C-v": {command: "goorselect", args: ["gotopagedown","selectpagedown"]}, + "PageUp|M-v": {command: "goorselect", args: ["gotopageup","selectpageup"]}, + "S-C-Down": "selectpagedown", + "S-C-Up": "selectpageup", + + "C-s": "iSearch", + "C-r": "iSearchBackwards", + + "M-C-s": "findnext", + "M-C-r": "findprevious", + "S-M-5": "replace", + "Backspace": "backspace", + "Delete|C-d": "del", + "Return|C-m": {command: "insertstring", args: "\n"}, // "newline" + "C-o": "splitline", + + "M-d|C-Delete": {command: "killWord", args: "right"}, + "C-Backspace|M-Backspace|M-Delete": {command: "killWord", args: "left"}, + "C-k": "killLine", + + "C-y|S-Delete": "yank", + "M-y": "yankRotate", + "C-g": "keyboardQuit", + + "C-w|C-S-W": "killRegion", + "M-w": "killRingSave", + "C-Space": "setMark", + "C-x C-x": "exchangePointAndMark", + + "C-t": "transposeletters", + "M-u": "touppercase", // Doesn't work + "M-l": "tolowercase", + "M-/": "autocomplete", // Doesn't work + "C-u": "universalArgument", + + "M-;": "togglecomment", + + "C-/|C-x u|S-C--|C-z": "undo", + "S-C-/|S-C-x u|C--|S-C-z": "redo", //infinite undo? + "C-x r": "selectRectangularRegion", + "M-x": {command: "focusCommandLine", args: "M-x "} +}; + + +exports.handler.bindKeys(exports.emacsKeys); + +exports.handler.addCommands({ + recenterTopBottom: function(editor) { + var renderer = editor.renderer; + var pos = renderer.$cursorLayer.getPixelPosition(); + var h = renderer.$size.scrollerHeight - renderer.lineHeight; + var scrollTop = renderer.scrollTop; + if (Math.abs(pos.top - scrollTop) < 2) { + scrollTop = pos.top - h; + } else if (Math.abs(pos.top - scrollTop - h * 0.5) < 2) { + scrollTop = pos.top; + } else { + scrollTop = pos.top - h * 0.5; + } + editor.session.setScrollTop(scrollTop); + }, + selectRectangularRegion: function(editor) { + editor.multiSelect.toggleBlockSelection(); + }, + setMark: { + exec: function(editor, args) { + + if (args && args.count) { + if (editor.inMultiSelectMode) editor.forEachSelection(moveToMark); + else moveToMark(); + moveToMark(); + return; + } + + var mark = editor.emacsMark(), + ranges = editor.selection.getAllRanges(), + rangePositions = ranges.map(function(r) { return {row: r.start.row, column: r.start.column}; }), + transientMarkModeActive = true, + hasNoSelection = ranges.every(function(range) { return range.isEmpty(); }); + if (transientMarkModeActive && (mark || !hasNoSelection)) { + if (editor.inMultiSelectMode) editor.forEachSelection({exec: editor.clearSelection.bind(editor)}) + else editor.clearSelection(); + if (mark) editor.pushEmacsMark(null); + return; + } + + if (!mark) { + rangePositions.forEach(function(pos) { editor.pushEmacsMark(pos); }); + editor.setEmacsMark(rangePositions[rangePositions.length-1]); + return; + } + + function moveToMark() { + var mark = editor.popEmacsMark(); + mark && editor.moveCursorToPosition(mark); + } + + }, + readOnly: true, + handlesCount: true + }, + exchangePointAndMark: { + exec: function exchangePointAndMark$exec(editor, args) { + var sel = editor.selection; + if (!args.count && !sel.isEmpty()) { // just invert selection + sel.setSelectionRange(sel.getRange(), !sel.isBackwards()); + return; + } + + if (args.count) { // replace mark and point + var pos = {row: sel.lead.row, column: sel.lead.column}; + sel.clearSelection(); + sel.moveCursorToPosition(editor.emacsMarkForSelection(pos)); + } else { // create selection to last mark + sel.selectToPosition(editor.emacsMarkForSelection()); + } + }, + readOnly: true, + handlesCount: true, + multiSelectAction: "forEach" + }, + killWord: { + exec: function(editor, dir) { + editor.clearSelection(); + if (dir == "left") + editor.selection.selectWordLeft(); + else + editor.selection.selectWordRight(); + + var range = editor.getSelectionRange(); + var text = editor.session.getTextRange(range); + exports.killRing.add(text); + + editor.session.remove(range); + editor.clearSelection(); + }, + multiSelectAction: "forEach" + }, + killLine: function(editor) { + editor.pushEmacsMark(null); + var pos = editor.getCursorPosition(); + if (pos.column === 0 && + editor.session.doc.getLine(pos.row).length === 0) { + editor.selection.selectLine(); + } else { + editor.clearSelection(); + editor.selection.selectLineEnd(); + } + var range = editor.getSelectionRange(); + var text = editor.session.getTextRange(range); + exports.killRing.add(text); + + editor.session.remove(range); + editor.clearSelection(); + }, + yank: function(editor) { + editor.onPaste(exports.killRing.get() || ''); + editor.keyBinding.$data.lastCommand = "yank"; + }, + yankRotate: function(editor) { + if (editor.keyBinding.$data.lastCommand != "yank") + return; + editor.undo(); + editor.session.$emacsMarkRing.pop(); // also undo recording mark + editor.onPaste(exports.killRing.rotate()); + editor.keyBinding.$data.lastCommand = "yank"; + }, + killRegion: { + exec: function(editor) { + exports.killRing.add(editor.getCopyText()); + editor.commands.byName.cut.exec(editor); + }, + readOnly: true, + multiSelectAction: "forEach" + }, + killRingSave: { + exec: function(editor) { + + editor.$handlesEmacsOnCopy = true; + var marks = editor.session.$emacsMarkRing.slice(), + deselectedMarks = []; + exports.killRing.add(editor.getCopyText()); + + setTimeout(function() { + function deselect() { + var sel = editor.selection, range = sel.getRange(), + pos = sel.isBackwards() ? range.end : range.start; + deselectedMarks.push({row: pos.row, column: pos.column}); + sel.clearSelection(); + } + editor.$handlesEmacsOnCopy = false; + if (editor.inMultiSelectMode) editor.forEachSelection({exec: deselect}); + else deselect(); + editor.session.$emacsMarkRing = marks.concat(deselectedMarks.reverse()); + }, 0); + }, + readOnly: true + }, + keyboardQuit: function(editor) { + editor.selection.clearSelection(); + editor.setEmacsMark(null); + editor.keyBinding.$data.count = null; + }, + focusCommandLine: function(editor, arg) { + if (editor.showCommandLine) + editor.showCommandLine(arg); + } +}); + +exports.handler.addCommands(iSearchCommandModule.iSearchStartCommands); + +var commands = exports.handler.commands; +commands.yank.isYank = true; +commands.yankRotate.isYank = true; + +exports.killRing = { + $data: [], + add: function(str) { + str && this.$data.push(str); + if (this.$data.length > 30) + this.$data.shift(); + }, + get: function(n) { + n = n || 1; + return this.$data.slice(this.$data.length-n, this.$data.length).reverse().join('\n'); + }, + pop: function() { + if (this.$data.length > 1) + this.$data.pop(); + return this.get(); + }, + rotate: function() { + this.$data.unshift(this.$data.pop()); + return this.get(); + } +}; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/keybinding-vim.js b/Patent2Net/media/graph-recipes/app/assets/ace/keybinding-vim.js new file mode 100644 index 00000000..6c691eb1 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/keybinding-vim.js @@ -0,0 +1,5387 @@ +define("ace/keyboard/vim",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/dom","ace/lib/oop","ace/lib/keys","ace/lib/event","ace/search","ace/lib/useragent","ace/search_highlight","ace/commands/multi_select_commands","ace/mode/text","ace/multi_select"], function(require, exports, module) { + 'use strict'; + + function log() { + var d = ""; + function format(p) { + if (typeof p != "object") + return p + ""; + if ("line" in p) { + return p.line + ":" + p.ch; + } + if ("anchor" in p) { + return format(p.anchor) + "->" + format(p.head); + } + if (Array.isArray(p)) + return "[" + p.map(function(x) { + return format(x); + }) + "]"; + return JSON.stringify(p); + } + for (var i = 0; i < arguments.length; i++) { + var p = arguments[i]; + var f = format(p); + d += f + " "; + } + console.log(d); + } + var Range = require("../range").Range; + var EventEmitter = require("../lib/event_emitter").EventEmitter; + var dom = require("../lib/dom"); + var oop = require("../lib/oop"); + var KEYS = require("../lib/keys"); + var event = require("../lib/event"); + var Search = require("../search").Search; + var useragent = require("../lib/useragent"); + var SearchHighlight = require("../search_highlight").SearchHighlight; + var multiSelectCommands = require("../commands/multi_select_commands"); + var TextModeTokenRe = require("../mode/text").Mode.prototype.tokenRe; + require("../multi_select"); + + var CodeMirror = function(ace) { + this.ace = ace; + this.state = {}; + this.marks = {}; + this.$uid = 0; + this.onChange = this.onChange.bind(this); + this.onSelectionChange = this.onSelectionChange.bind(this); + this.onBeforeEndOperation = this.onBeforeEndOperation.bind(this); + this.ace.on('change', this.onChange); + this.ace.on('changeSelection', this.onSelectionChange); + this.ace.on('beforeEndOperation', this.onBeforeEndOperation); + }; + CodeMirror.Pos = function(line, ch) { + if (!(this instanceof Pos)) return new Pos(line, ch); + this.line = line; this.ch = ch; + }; + CodeMirror.defineOption = function(name, val, setter) {}; + CodeMirror.commands = { + redo: function(cm) { cm.ace.redo(); }, + undo: function(cm) { cm.ace.undo(); }, + newlineAndIndent: function(cm) { cm.ace.insert("\n"); }, + }; + CodeMirror.keyMap = {}; + CodeMirror.addClass = CodeMirror.rmClass = + CodeMirror.e_stop = function() {}; + CodeMirror.keyName = function(e) { + if (e.key) return e.key; + var key = (KEYS[e.keyCode] || ""); + if (key.length == 1) key = key.toUpperCase(); + key = event.getModifierString(e).replace(/(^|-)\w/g, function(m) { + return m.toUpperCase(); + }) + key; + return key; + }; + CodeMirror.keyMap['default'] = function(key) { + return function(cm) { + var cmd = cm.ace.commands.commandKeyBinding[key.toLowerCase()]; + return cmd && cm.ace.execCommand(cmd) !== false; + }; + }; + CodeMirror.lookupKey = function lookupKey(key, map, handle) { + if (typeof map == "string") + map = CodeMirror.keyMap[map]; + var found = typeof map == "function" ? map(key) : map[key]; + if (found === false) return "nothing"; + if (found === "...") return "multi"; + if (found != null && handle(found)) return "handled"; + + if (map.fallthrough) { + if (!Array.isArray(map.fallthrough)) + return lookupKey(key, map.fallthrough, handle); + for (var i = 0; i < map.fallthrough.length; i++) { + var result = lookupKey(key, map.fallthrough[i], handle); + if (result) return result; + } + } + }; + + CodeMirror.signal = function(o, name, e) { return o._signal(name, e) }; + CodeMirror.on = event.addListener; + CodeMirror.off = event.removeListener; + CodeMirror.isWordChar = function(ch) { + TextModeTokenRe.lastIndex = 0; + return TextModeTokenRe.test(ch); + }; + +(function() { + oop.implement(CodeMirror.prototype, EventEmitter); + + this.destroy = function() { + this.ace.off('change', this.onChange); + this.ace.off('changeSelection', this.onSelectionChange); + this.ace.off('beforeEndOperation', this.onBeforeEndOperation); + this.removeOverlay(); + }; + this.virtualSelectionMode = function() { + return this.ace.inVirtualSelectionMode && this.ace.selection.index; + }; + this.onChange = function(delta) { + var oldDelta = delta.data; + delta = { + start: oldDelta.range.start, + end: oldDelta.range.end, + action: oldDelta.action, + lines: oldDelta.lines || [oldDelta.text] + };// v1.2 api compatibility + if (delta.action[0] == 'i') { + var change = { text: delta.lines }; + var curOp = this.curOp = this.curOp || {}; + if (!curOp.changeHandlers) + curOp.changeHandlers = this._eventRegistry["change"] && this._eventRegistry["change"].slice(); + if (this.virtualSelectionMode()) return; + if (!curOp.lastChange) { + curOp.lastChange = curOp.change = change; + } else { + curOp.lastChange.next = curOp.lastChange = change; + } + } + this.$updateMarkers(delta); + }; + this.onSelectionChange = function() { + var curOp = this.curOp = this.curOp || {}; + if (!curOp.cursorActivityHandlers) + curOp.cursorActivityHandlers = this._eventRegistry["cursorActivity"] && this._eventRegistry["cursorActivity"].slice(); + this.curOp.cursorActivity = true; + if (this.ace.inMultiSelectMode) { + this.ace.keyBinding.removeKeyboardHandler(multiSelectCommands.keyboardHandler); + } + }; + this.operation = function(fn, force) { + if (!force && this.curOp || force && this.curOp && this.curOp.force) { + return fn(); + } + if (force || !this.ace.curOp) { + if (this.curOp) + this.onBeforeEndOperation(); + } + if (!this.ace.curOp) { + var prevOp = this.ace.prevOp; + this.ace.startOperation({ + command: { name: "vim", scrollIntoView: "cursor" } + }); + } + var curOp = this.curOp = this.curOp || {}; + this.curOp.force = force; + var result = fn(); + if (this.ace.curOp && this.ace.curOp.command.name == "vim") { + this.ace.endOperation(); + if (!curOp.cursorActivity && !curOp.lastChange && prevOp) + this.ace.prevOp = prevOp; + } + if (force || !this.ace.curOp) { + if (this.curOp) + this.onBeforeEndOperation(); + } + return result; + }; + this.onBeforeEndOperation = function() { + var op = this.curOp; + if (op) { + if (op.change) { this.signal("change", op.change, op); } + if (op && op.cursorActivity) { this.signal("cursorActivity", null, op); } + this.curOp = null; + } + }; + + this.signal = function(eventName, e, handlers) { + var listeners = handlers ? handlers[eventName + "Handlers"] + : (this._eventRegistry || {})[eventName]; + if (!listeners) + return; + listeners = listeners.slice(); + for (var i=0; i 0) { + point.row += rowShift; + point.column += point.row == end.row ? colShift : 0; + continue; + } + if (!isInsert && cmp2 <= 0) { + point.row = start.row; + point.column = start.column; + if (cmp2 === 0) + point.bias = 1; + } + } + }; + var Marker = function(cm, id, row, column) { + this.cm = cm; + this.id = id; + this.row = row; + this.column = column; + cm.marks[this.id] = this; + }; + Marker.prototype.clear = function() { delete this.cm.marks[this.id] }; + Marker.prototype.find = function() { return toCmPos(this) }; + this.setBookmark = function(cursor, options) { + var bm = new Marker(this, this.$uid++, cursor.line, cursor.ch); + if (!options || !options.insertLeft) + bm.$insertRight = true; + this.marks[bm.id] = bm; + return bm; + }; + this.moveH = function(increment, unit) { + if (unit == 'char') { + var sel = this.ace.selection; + sel.clearSelection(); + sel.moveCursorBy(0, increment); + } + }; + this.findPosV = function(start, amount, unit, goalColumn) { + if (unit == 'page') { + var renderer = this.ace.renderer; + var config = renderer.layerConfig; + amount = amount * Math.floor(config.height / config.lineHeight); + unit = 'line'; + } + if (unit == 'line') { + var screenPos = this.ace.session.documentToScreenPosition(start.line, start.ch); + if (goalColumn != null) + screenPos.column = goalColumn; + screenPos.row += amount; + screenPos.row = Math.min(Math.max(0, screenPos.row), this.ace.session.getScreenLength() - 1); + var pos = this.ace.session.screenToDocumentPosition(screenPos.row, screenPos.column); + return toCmPos(pos); + } else { + debugger; + } + }; + this.charCoords = function(pos, mode) { + if (mode == 'div' || !mode) { + var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch); + return {left: sc.column, top: sc.row}; + }if (mode == 'local') { + var renderer = this.ace.renderer; + var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch); + var lh = renderer.layerConfig.lineHeight; + var cw = renderer.layerConfig.characterWidth; + var top = lh * sc.row; + return {left: sc.column * cw, top: top, bottom: top + lh}; + } + }; + this.coordsChar = function(pos, mode) { + var renderer = this.ace.renderer; + if (mode == 'local') { + var row = Math.max(0, Math.floor(pos.top / renderer.lineHeight)); + var col = Math.max(0, Math.floor(pos.left / renderer.characterWidth)); + var ch = renderer.session.screenToDocumentPosition(row, col); + return toCmPos(ch); + } else if (mode == 'div') { + throw "not implemented"; + } + }; + this.getSearchCursor = function(query, pos, caseFold) { + var caseSensitive = false; + var isRegexp = false; + if (query instanceof RegExp && !query.global) { + caseSensitive = !query.ignoreCase; + query = query.source; + isRegexp = true; + } + var search = new Search(); + if (pos.ch == undefined) pos.ch = Number.MAX_VALUE; + var acePos = {row: pos.line, column: pos.ch}; + var cm = this; + var last = null; + return { + findNext: function() { return this.find(false) }, + findPrevious: function() {return this.find(true) }, + find: function(back) { + search.setOptions({ + needle: query, + caseSensitive: caseSensitive, + wrap: false, + backwards: back, + regExp: isRegexp, + start: last || acePos + }); + var range = search.find(cm.ace.session); + if (range && range.isEmpty()) { + if (cm.getLine(range.start.row).length == range.start.column) { + search.$options.start = range; + range = search.find(cm.ace.session); + } + } + last = range; + return last; + }, + from: function() { return last && toCmPos(last.start) }, + to: function() { return last && toCmPos(last.end) }, + replace: function(text) { + if (last) { + last.end = cm.ace.session.doc.replace(last, text); + } + } + }; + }; + this.scrollTo = function(x, y) { + var renderer = this.ace.renderer; + var config = renderer.layerConfig; + var maxHeight = config.maxHeight; + maxHeight -= (renderer.$size.scrollerHeight - renderer.lineHeight) * renderer.$scrollPastEnd; + if (y != null) this.ace.session.setScrollTop(Math.max(0, Math.min(y, maxHeight))); + if (x != null) this.ace.session.setScrollLeft(Math.max(0, Math.min(x, config.width))); + }; + this.scrollInfo = function() { return 0; }; + this.scrollIntoView = function(pos, margin) { + if (pos) + this.ace.renderer.scrollCursorIntoView(toAcePos(pos), null, margin); + }; + this.getLine = function(row) { return this.ace.session.getLine(row) }; + this.getRange = function(s, e) { + return this.ace.session.getTextRange(new Range(s.line, s.ch, e.line, e.ch)); + }; + this.replaceRange = function(text, s, e) { + if (!e) e = s; + return this.ace.session.replace(new Range(s.line, s.ch, e.line, e.ch), text); + }; + this.replaceSelections = function(p) { + var sel = this.ace.selection; + if (this.ace.inVirtualSelectionMode) { + this.ace.session.replace(sel.getRange(), p[0] || ""); + return; + } + sel.inVirtualSelectionMode = true; + var ranges = sel.rangeList.ranges; + if (!ranges.length) ranges = [this.ace.multiSelect.getRange()]; + for (var i = ranges.length; i--;) + this.ace.session.replace(ranges[i], p[i] || ""); + sel.inVirtualSelectionMode = false; + }; + this.getSelection = function() { + return this.ace.getSelectedText(); + }; + this.getSelections = function() { + return this.listSelections().map(function(x) { + return this.getRange(x.anchor, x.head); + }, this); + }; + this.getInputField = function() { + return this.ace.textInput.getElement(); + }; + this.getWrapperElement = function() { + return this.ace.containter; + }; + var optMap = { + indentWithTabs: "useSoftTabs", + indentUnit: "tabSize", + firstLineNumber: "firstLineNumber" + }; + this.setOption = function(name, val) { + this.state[name] = val; + switch (name) { + case 'indentWithTabs': + name = optMap[name]; + val = !val; + break; + default: + name = optMap[name]; + } + if (name) + this.ace.setOption(name, val); + }; + this.getOption = function(name, val) { + var aceOpt = optMap[name]; + if (aceOpt) + val = this.ace.getOption(aceOpt); + switch (name) { + case 'indentWithTabs': + name = optMap[name]; + return !val; + } + return aceOpt ? val : this.state[name]; + }; + this.toggleOverwrite = function(on) { + this.state.overwrite = on; + return this.ace.setOverwrite(on); + }; + this.addOverlay = function(o) { + if (!this.$searchHighlight || !this.$searchHighlight.session) { + var highlight = new SearchHighlight(null, "ace_highlight-marker", "text"); + var marker = this.ace.session.addDynamicMarker(highlight); + highlight.id = marker.id; + highlight.session = this.ace.session; + highlight.destroy = function(o) { + highlight.session.off("change", highlight.updateOnChange); + highlight.session.off("changeEditor", highlight.destroy); + highlight.session.removeMarker(highlight.id); + highlight.session = null; + }; + highlight.updateOnChange = function(delta) { + delta = delta.data.range;// v1.2 api compatibility + var row = delta.start.row; + if (row == delta.end.row) highlight.cache[row] = undefined; + else highlight.cache.splice(row, highlight.cache.length); + }; + highlight.session.on("changeEditor", highlight.destroy); + highlight.session.on("change", highlight.updateOnChange); + } + var re = new RegExp(o.query.source, "gmi"); + this.$searchHighlight = o.highlight = highlight; + this.$searchHighlight.setRegexp(re); + this.ace.renderer.updateBackMarkers(); + }; + this.removeOverlay = function(o) { + if (this.$searchHighlight && this.$searchHighlight.session) { + this.$searchHighlight.destroy(); + } + }; + this.getScrollInfo = function() { + var renderer = this.ace.renderer; + var config = renderer.layerConfig; + return { + left: renderer.scrollLeft, + top: renderer.scrollTop, + height: config.maxHeight, + width: config.width, + clientHeight: config.height, + clientWidth: config.width + }; + }; + this.getValue = function() { + return this.ace.getValue(); + }; + this.setValue = function(v) { + return this.ace.setValue(v); + }; + this.getTokenTypeAt = function(pos) { + var token = this.ace.session.getTokenAt(pos.line, pos.ch); + return token && /comment|string/.test(token.type) ? "string" : ""; + }; + this.findMatchingBracket = function(pos) { + var m = this.ace.session.findMatchingBracket(toAcePos(pos)); + return {to: m && toCmPos(m)}; + }; + this.indentLine = function(line, method) { + if (method === true) + this.ace.session.indentRows(line, line, "\t"); + else if (method === false) + this.ace.session.outdentRows(new Range(line, 0, line, 0)); + }; + this.indexFromPos = function(pos) { + return this.ace.session.doc.positionToIndex(toAcePos(pos)); + }; + this.posFromIndex = function(index) { + return toCmPos(this.ace.session.doc.indexToPosition(index)); + }; + this.focus = function(index) { + return this.ace.focus(); + }; + this.blur = function(index) { + return this.ace.blur(); + }; + this.defaultTextHeight = function(index) { + return this.ace.renderer.layerConfig.lineHeight; + }; + this.scanForBracket = function(pos, dir, _, options) { + var re = options.bracketRegex.source; + if (dir == 1) { + var m = this.ace.session.$findClosingBracket(re.slice(1, 2), toAcePos(pos), /paren|text/); + } else { + var m = this.ace.session.$findOpeningBracket(re.slice(-2, -1), {row: pos.line, column: pos.ch + 1}, /paren|text/); + } + return m && {pos: toCmPos(m)}; + }; + this.refresh = function() { + return this.ace.resize(true); + }; +}).call(CodeMirror.prototype); + function toAcePos(cmPos) { + return {row: cmPos.line, column: cmPos.ch}; + } + function toCmPos(acePos) { + return new Pos(acePos.row, acePos.column); + } + + var StringStream = CodeMirror.StringStream = function(string, tabSize) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + this.lastColumnPos = this.lastColumnValue = 0; + this.lineStart = 0; + }; + + StringStream.prototype = { + eol: function() {return this.pos >= this.string.length;}, + sol: function() {return this.pos == this.lineStart;}, + peek: function() {return this.string.charAt(this.pos) || undefined;}, + next: function() { + if (this.pos < this.string.length) + return this.string.charAt(this.pos++); + }, + eat: function(match) { + var ch = this.string.charAt(this.pos); + if (typeof match == "string") var ok = ch == match; + else var ok = ch && (match.test ? match.test(ch) : match(ch)); + if (ok) {++this.pos; return ch;} + }, + eatWhile: function(match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start; + }, + eatSpace: function() { + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; + return this.pos > start; + }, + skipToEnd: function() {this.pos = this.string.length;}, + skipTo: function(ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true;} + }, + backUp: function(n) {this.pos -= n;}, + column: function() { + throw "not implemented"; + }, + indentation: function() { + throw "not implemented"; + }, + match: function(pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; + var substr = this.string.substr(this.pos, pattern.length); + if (cased(substr) == cased(pattern)) { + if (consume !== false) this.pos += pattern.length; + return true; + } + } else { + var match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) return null; + if (match && consume !== false) this.pos += match[0].length; + return match; + } + }, + current: function(){return this.string.slice(this.start, this.pos);}, + hideFirstChars: function(n, inner) { + this.lineStart += n; + try { return inner(); } + finally { this.lineStart -= n; } + } + }; +CodeMirror.defineExtension = function(name, fn) { + CodeMirror.prototype[name] = fn; +}; +dom.importCssString(".normal-mode .ace_cursor{\ + border: 0!important;\ + background-color: red;\ + opacity: 0.5;\ +}.ace_dialog {\ + position: absolute;\ + left: 0; right: 0;\ + background: white;\ + z-index: 15;\ + padding: .1em .8em;\ + overflow: hidden;\ + color: #333;\ +}\ +.ace_dialog-top {\ + border-bottom: 1px solid #eee;\ + top: 0;\ +}\ +.ace_dialog-bottom {\ + border-top: 1px solid #eee;\ + bottom: 0;\ +}\ +.ace_dialog input {\ + border: none;\ + outline: none;\ + background: transparent;\ + width: 20em;\ + color: inherit;\ + font-family: monospace;\ +}", "vimMode"); +(function() { + function dialogDiv(cm, template, bottom) { + var wrap = cm.ace.container; + var dialog; + dialog = wrap.appendChild(document.createElement("div")); + if (bottom) + dialog.className = "ace_dialog ace_dialog-bottom"; + else + dialog.className = "ace_dialog ace_dialog-top"; + + if (typeof template == "string") { + dialog.innerHTML = template; + } else { // Assuming it's a detached DOM element. + dialog.appendChild(template); + } + return dialog; + } + + function closeNotification(cm, newVal) { + if (cm.state.currentNotificationClose) + cm.state.currentNotificationClose(); + cm.state.currentNotificationClose = newVal; + } + + CodeMirror.defineExtension("openDialog", function(template, callback, options) { + if (this.virtualSelectionMode()) return; + if (!options) options = {}; + + closeNotification(this, null); + + var dialog = dialogDiv(this, template, options.bottom); + var closed = false, me = this; + function close(newVal) { + if (typeof newVal == 'string') { + inp.value = newVal; + } else { + if (closed) return; + closed = true; + dialog.parentNode.removeChild(dialog); + me.focus(); + + if (options.onClose) options.onClose(dialog); + } + } + + var inp = dialog.getElementsByTagName("input")[0], button; + if (inp) { + if (options.value) { + inp.value = options.value; + inp.select(); + } + + if (options.onInput) + CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); + if (options.onKeyUp) + CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); + + CodeMirror.on(inp, "keydown", function(e) { + if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } + if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { + inp.blur(); + CodeMirror.e_stop(e); + close(); + } + if (e.keyCode == 13) callback(inp.value); + }); + + if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); + + inp.focus(); + } else if (button = dialog.getElementsByTagName("button")[0]) { + CodeMirror.on(button, "click", function() { + close(); + me.focus(); + }); + + if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); + + button.focus(); + } + return close; + }); + + CodeMirror.defineExtension("openNotification", function(template, options) { + if (this.virtualSelectionMode()) return; + closeNotification(this, close); + var dialog = dialogDiv(this, template, options && options.bottom); + var closed = false, doneTimer; + var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; + + function close() { + if (closed) return; + closed = true; + clearTimeout(doneTimer); + dialog.parentNode.removeChild(dialog); + } + + CodeMirror.on(dialog, 'click', function(e) { + CodeMirror.e_preventDefault(e); + close(); + }); + + if (duration) + doneTimer = setTimeout(close, duration); + + return close; + }); +})(); + + + var defaultKeymap = [ + { keys: '', type: 'keyToKey', toKeys: 'h' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'l' }, + { keys: '', type: 'keyToKey', toKeys: 'h', context: 'normal'}, + { keys: '', type: 'keyToKey', toKeys: 'W' }, + { keys: '', type: 'keyToKey', toKeys: 'B', context: 'normal' }, + { keys: '', type: 'keyToKey', toKeys: 'w' }, + { keys: '', type: 'keyToKey', toKeys: 'b', context: 'normal' }, + { keys: '', type: 'keyToKey', toKeys: 'j' }, + { keys: '', type: 'keyToKey', toKeys: 'k' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, + { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, + { keys: 's', type: 'keyToKey', toKeys: 'xi', context: 'visual'}, + { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, + { keys: 'S', type: 'keyToKey', toKeys: 'dcc', context: 'visual' }, + { keys: '', type: 'keyToKey', toKeys: '0' }, + { keys: '', type: 'keyToKey', toKeys: '$' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: '' }, + { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, + { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }}, + { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }}, + { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }}, + { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }}, + { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }}, + { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }}, + { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }}, + { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }}, + { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }}, + { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }}, + { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }}, + { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }}, + { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }}, + { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }}, + { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }}, + { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, + { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, + { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }}, + { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, + { keys: '0', type: 'motion', motion: 'moveToStartOfLine' }, + { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }}, + { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }}, + { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, + { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }}, + { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }}, + { keys: 'f', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }}, + { keys: 'F', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }}, + { keys: 't', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }}, + { keys: 'T', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }}, + { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }}, + { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }}, + { keys: '\'', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}}, + { keys: '`', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}}, + { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, + { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, + { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, + { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, + { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}}, + { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}}, + { keys: ']', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}}, + { keys: '[', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}}, + { keys: '|', type: 'motion', motion: 'moveToColumn'}, + { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'}, + { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, + { keys: 'd', type: 'operator', operator: 'delete' }, + { keys: 'y', type: 'operator', operator: 'yank' }, + { keys: 'c', type: 'operator', operator: 'change' }, + { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }}, + { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }}, + { keys: 'g~', type: 'operator', operator: 'changeCase' }, + { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true }, + { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true }, + { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }}, + { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }}, + { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, + { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, + { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, + { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'}, + { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'}, + { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'}, + { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, + { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }}, + { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }}, + { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, + { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, + { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' }, + { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' }, + { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, + { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, + { keys: 'v', type: 'action', action: 'toggleVisualMode' }, + { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }}, + { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, + { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, + { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, + { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }}, + { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, + { keys: 'r', type: 'action', action: 'replace', isEdit: true }, + { keys: '@', type: 'action', action: 'replayMacro' }, + { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, + { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, + { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, + { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true }, + { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, + { keys: '', type: 'action', action: 'redo' }, + { keys: 'm', type: 'action', action: 'setMark' }, + { keys: '"', type: 'action', action: 'setRegister' }, + { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }}, + { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }}, + { keys: 'z', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }}, + { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, + { keys: '.', type: 'action', action: 'repeatLastEdit' }, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}}, + { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}}, + { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, + { keys: 'i', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }}, + { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, + { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, + { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, + { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, + { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, + { keys: ':', type: 'ex' } + ]; + + var Pos = CodeMirror.Pos; + + var Vim = function() { return vimApi; } //{ + function enterVimMode(cm) { + cm.setOption('disableInput', true); + cm.setOption('showCursorWhenSelecting', false); + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + cm.on('cursorActivity', onCursorActivity); + maybeInitVimState(cm); + CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); + } + + function leaveVimMode(cm) { + cm.setOption('disableInput', false); + cm.off('cursorActivity', onCursorActivity); + CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); + cm.state.vim = null; + } + + function detachVimMap(cm, next) { + if (this == CodeMirror.keyMap.vim) + CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor"); + + if (!next || next.attach != attachVimMap) + leaveVimMode(cm, false); + } + function attachVimMap(cm, prev) { + if (this == CodeMirror.keyMap.vim) + CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); + + if (!prev || prev.attach != attachVimMap) + enterVimMode(cm); + } + CodeMirror.defineOption('vimMode', false, function(cm, val, prev) { + if (val && cm.getOption("keyMap") != "vim") + cm.setOption("keyMap", "vim"); + else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) + cm.setOption("keyMap", "default"); + }); + + function cmKey(key, cm) { + if (!cm) { return undefined; } + var vimKey = cmKeyToVimKey(key); + if (!vimKey) { + return false; + } + var cmd = CodeMirror.Vim.findKey(cm, vimKey); + if (typeof cmd == 'function') { + CodeMirror.signal(cm, 'vim-keypress', vimKey); + } + return cmd; + } + + var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'}; + var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del'}; + function cmKeyToVimKey(key) { + if (key.charAt(0) == '\'') { + return key.charAt(1); + } + var pieces = key.split('-'); + if (/-$/.test(key)) { + pieces.splice(-2, 2, '-'); + } + var lastPiece = pieces[pieces.length - 1]; + if (pieces.length == 1 && pieces[0].length == 1) { + return false; + } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) { + return false; + } + var hasCharacter = false; + for (var i = 0; i < pieces.length; i++) { + var piece = pieces[i]; + if (piece in modifiers) { pieces[i] = modifiers[piece]; } + else { hasCharacter = true; } + if (piece in specialKeys) { pieces[i] = specialKeys[piece]; } + } + if (!hasCharacter) { + return false; + } + if (isUpperCase(lastPiece)) { + pieces[pieces.length - 1] = lastPiece.toLowerCase(); + } + return '<' + pieces.join('-') + '>'; + } + + function getOnPasteFn(cm) { + var vim = cm.state.vim; + if (!vim.onPasteFn) { + vim.onPasteFn = function() { + if (!vim.insertMode) { + cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); + actions.enterInsertMode(cm, {}, vim); + } + }; + } + return vim.onPasteFn; + } + + var numberRegex = /[\d]/; + var wordRegexp = [{test: CodeMirror.isWordChar}, {test: function(ch) { + return !CodeMirror.isWordChar(ch) && !/\s/.test(ch); + }}], bigWordRegexp = [(/\S/)]; + function makeKeyRange(start, size) { + var keys = []; + for (var i = start; i < start + size; i++) { + keys.push(String.fromCharCode(i)); + } + return keys; + } + var upperCaseAlphabet = makeKeyRange(65, 26); + var lowerCaseAlphabet = makeKeyRange(97, 26); + var numbers = makeKeyRange(48, 10); + var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); + var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); + + function isLine(cm, line) { + return line >= cm.firstLine() && line <= cm.lastLine(); + } + function isLowerCase(k) { + return (/^[a-z]$/).test(k); + } + function isMatchableSymbol(k) { + return '()[]{}'.indexOf(k) != -1; + } + function isNumber(k) { + return numberRegex.test(k); + } + function isUpperCase(k) { + return (/^[A-Z]$/).test(k); + } + function isWhiteSpaceString(k) { + return (/^\s*$/).test(k); + } + function inArray(val, arr) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] == val) { + return true; + } + } + return false; + } + + var options = {}; + function defineOption(name, defaultValue, type) { + if (defaultValue === undefined) { throw Error('defaultValue is required'); } + if (!type) { type = 'string'; } + options[name] = { + type: type, + defaultValue: defaultValue + }; + setOption(name, defaultValue); + } + + function setOption(name, value, cm) { + var option = options[name]; + if (!option) { + throw Error('Unknown option: ' + name); + } + if (option.type == 'boolean') { + if (value && value !== true) { + throw Error('Invalid argument: ' + name + '=' + value); + } else if (value !== false) { + value = true; + } + } + option.value = option.type == 'boolean' ? !!value : value; + } + + function getOption(name) { + var option = options[name]; + if (!option) { + throw Error('Unknown option: ' + name); + } + return option.value; + } + + var createCircularJumpList = function() { + var size = 100; + var pointer = -1; + var head = 0; + var tail = 0; + var buffer = new Array(size); + function add(cm, oldCur, newCur) { + var current = pointer % size; + var curMark = buffer[current]; + function useNextSlot(cursor) { + var next = ++pointer % size; + var trashMark = buffer[next]; + if (trashMark) { + trashMark.clear(); + } + buffer[next] = cm.setBookmark(cursor); + } + if (curMark) { + var markPos = curMark.find(); + if (markPos && !cursorEqual(markPos, oldCur)) { + useNextSlot(oldCur); + } + } else { + useNextSlot(oldCur); + } + useNextSlot(newCur); + head = pointer; + tail = pointer - size + 1; + if (tail < 0) { + tail = 0; + } + } + function move(cm, offset) { + pointer += offset; + if (pointer > head) { + pointer = head; + } else if (pointer < tail) { + pointer = tail; + } + var mark = buffer[(size + pointer) % size]; + if (mark && !mark.find()) { + var inc = offset > 0 ? 1 : -1; + var newCur; + var oldCur = cm.getCursor(); + do { + pointer += inc; + mark = buffer[(size + pointer) % size]; + if (mark && + (newCur = mark.find()) && + !cursorEqual(oldCur, newCur)) { + break; + } + } while (pointer < head && pointer > tail); + } + return mark; + } + return { + cachedCursor: undefined, //used for # and * jumps + add: add, + move: move + }; + }; + var createInsertModeChanges = function(c) { + if (c) { + return { + changes: c.changes, + expectCursorActivityForChange: c.expectCursorActivityForChange + }; + } + return { + changes: [], + expectCursorActivityForChange: false + }; + }; + + function MacroModeState() { + this.latestRegister = undefined; + this.isPlaying = false; + this.isRecording = false; + this.replaySearchQueries = []; + this.onRecordingDone = undefined; + this.lastInsertModeChanges = createInsertModeChanges(); + } + MacroModeState.prototype = { + exitMacroRecordMode: function() { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.onRecordingDone) { + macroModeState.onRecordingDone(); // close dialog + } + macroModeState.onRecordingDone = undefined; + macroModeState.isRecording = false; + }, + enterMacroRecordMode: function(cm, registerName) { + var register = + vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.clear(); + this.latestRegister = registerName; + if (cm.openDialog) { + this.onRecordingDone = cm.openDialog( + '(recording)['+registerName+']', null, {bottom:true}); + } + this.isRecording = true; + } + } + }; + + function maybeInitVimState(cm) { + if (!cm.state.vim) { + cm.state.vim = { + inputState: new InputState(), + lastEditInputState: undefined, + lastEditActionCommand: undefined, + lastHPos: -1, + lastHSPos: -1, + lastMotion: null, + marks: {}, + fakeCursor: null, + insertMode: false, + insertModeRepeat: undefined, + visualMode: false, + visualLine: false, + visualBlock: false, + lastSelection: null, + lastPastedText: null, + sel: { + } + }; + } + return cm.state.vim; + } + var vimGlobalState; + function resetVimGlobalState() { + vimGlobalState = { + searchQuery: null, + searchIsReversed: false, + lastSubstituteReplacePart: undefined, + jumpList: createCircularJumpList(), + macroModeState: new MacroModeState, + lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''}, + registerController: new RegisterController({}), + searchHistoryController: new HistoryController({}), + exCommandHistoryController : new HistoryController({}) + }; + for (var optionName in options) { + var option = options[optionName]; + option.value = option.defaultValue; + } + } + + var lastInsertModeKeyTimer; + var vimApi= { + buildKeyMap: function() { + }, + getRegisterController: function() { + return vimGlobalState.registerController; + }, + resetVimGlobalState_: resetVimGlobalState, + getVimGlobalState_: function() { + return vimGlobalState; + }, + maybeInitVimState_: maybeInitVimState, + + InsertModeKey: InsertModeKey, + map: function(lhs, rhs, ctx) { + exCommandDispatcher.map(lhs, rhs, ctx); + }, + unmap: function(lhs, ctx) { + exCommandDispatcher.unmap(lhs, ctx); + }, + setOption: setOption, + getOption: getOption, + defineOption: defineOption, + defineEx: function(name, prefix, func){ + if (name.indexOf(prefix) !== 0) { + throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered'); + } + exCommands[name]=func; + exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'}; + }, + handleKey: function (cm, key, origin) { + var command = this.findKey(cm, key, origin); + if (typeof command === 'function') { + return command(); + } + }, + findKey: function(cm, key, origin) { + var vim = maybeInitVimState(cm); + function handleMacroRecording() { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isRecording) { + if (key == 'q') { + macroModeState.exitMacroRecordMode(); + clearInputState(cm); + return true; + } + if (origin != 'mapping') { + logKey(macroModeState, key); + } + } + } + function handleEsc() { + if (key == '') { + clearInputState(cm); + if (vim.visualMode) { + exitVisualMode(cm); + } else if (vim.insertMode) { + exitInsertMode(cm); + } + return true; + } + } + function doKeyToKey(keys) { + var match; + while (keys) { + match = (/<\w+-.+?>|<\w+>|./).exec(keys); + key = match[0]; + keys = keys.substring(match.index + key.length); + CodeMirror.Vim.handleKey(cm, key, 'mapping'); + } + } + + function handleKeyInsertMode() { + if (handleEsc()) { return true; } + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + var keysAreChars = key.length == 1; + var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + while (keys.length > 1 && match.type != 'full') { + var keys = vim.inputState.keyBuffer = keys.slice(1); + var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); + if (thisMatch.type != 'none') { match = thisMatch; } + } + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + lastInsertModeKeyTimer = window.setTimeout( + function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } }, + getOption('insertModeEscKeysTimeout')); + return !keysAreChars; + } + + if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } + if (keysAreChars) { + var here = cm.getCursor(); + cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); + } + clearInputState(cm); + return match.command; + } + + function handleKeyNonInsertMode() { + if (handleMacroRecording() || handleEsc()) { return true; }; + + var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; + if (/^[1-9]\d*$/.test(keys)) { return true; } + + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (!keysMatcher) { clearInputState(cm); return false; } + var context = vim.visualMode ? 'visual' : + 'normal'; + var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); + if (match.type == 'none') { clearInputState(cm); return false; } + else if (match.type == 'partial') { return true; } + + vim.inputState.keyBuffer = ''; + var keysMatcher = /^(\d*)(.*)$/.exec(keys); + if (keysMatcher[1] && keysMatcher[1] != '0') { + vim.inputState.pushRepeatDigit(keysMatcher[1]); + } + return match.command; + } + + var command; + if (vim.insertMode) { command = handleKeyInsertMode(); } + else { command = handleKeyNonInsertMode(); } + if (command === false) { + return undefined; + } else if (command === true) { + return function() {}; + } else { + return function() { + return cm.operation(function() { + cm.curOp.isVimOp = true; + try { + if (command.type == 'keyToKey') { + doKeyToKey(command.toKeys); + } else { + commandDispatcher.processCommand(cm, vim, command); + } + } catch (e) { + cm.state.vim = undefined; + maybeInitVimState(cm); + console['log'](e); + throw e; + } + return true; + }); + }; + } + }, + handleEx: function(cm, input) { + exCommandDispatcher.processCommand(cm, input); + } + }; + function InputState() { + this.prefixRepeat = []; + this.motionRepeat = []; + + this.operator = null; + this.operatorArgs = null; + this.motion = null; + this.motionArgs = null; + this.keyBuffer = []; // For matching multi-key commands. + this.registerName = null; // Defaults to the unnamed register. + } + InputState.prototype.pushRepeatDigit = function(n) { + if (!this.operator) { + this.prefixRepeat = this.prefixRepeat.concat(n); + } else { + this.motionRepeat = this.motionRepeat.concat(n); + } + }; + InputState.prototype.getRepeat = function() { + var repeat = 0; + if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) { + repeat = 1; + if (this.prefixRepeat.length > 0) { + repeat *= parseInt(this.prefixRepeat.join(''), 10); + } + if (this.motionRepeat.length > 0) { + repeat *= parseInt(this.motionRepeat.join(''), 10); + } + } + return repeat; + }; + + function clearInputState(cm, reason) { + cm.state.vim.inputState = new InputState(); + CodeMirror.signal(cm, 'vim-command-done', reason); + } + function Register(text, linewise, blockwise) { + this.clear(); + this.keyBuffer = [text || '']; + this.insertModeChanges = []; + this.searchQueries = []; + this.linewise = !!linewise; + this.blockwise = !!blockwise; + } + Register.prototype = { + setText: function(text, linewise, blockwise) { + this.keyBuffer = [text || '']; + this.linewise = !!linewise; + this.blockwise = !!blockwise; + }, + pushText: function(text, linewise) { + if (linewise) { + if (!this.linewise) { + this.keyBuffer.push('\n'); + } + this.linewise = true; + } + this.keyBuffer.push(text); + }, + pushInsertModeChanges: function(changes) { + this.insertModeChanges.push(createInsertModeChanges(changes)); + }, + pushSearchQuery: function(query) { + this.searchQueries.push(query); + }, + clear: function() { + this.keyBuffer = []; + this.insertModeChanges = []; + this.searchQueries = []; + this.linewise = false; + }, + toString: function() { + return this.keyBuffer.join(''); + } + }; + function RegisterController(registers) { + this.registers = registers; + this.unnamedRegister = registers['"'] = new Register(); + registers['.'] = new Register(); + registers[':'] = new Register(); + registers['/'] = new Register(); + } + RegisterController.prototype = { + pushText: function(registerName, operator, text, linewise, blockwise) { + if (linewise && text.charAt(0) == '\n') { + text = text.slice(1) + '\n'; + } + if (linewise && text.charAt(text.length - 1) !== '\n'){ + text += '\n'; + } + var register = this.isValidRegister(registerName) ? + this.getRegister(registerName) : null; + if (!register) { + switch (operator) { + case 'yank': + this.registers['0'] = new Register(text, linewise, blockwise); + break; + case 'delete': + case 'change': + if (text.indexOf('\n') == -1) { + this.registers['-'] = new Register(text, linewise); + } else { + this.shiftNumericRegisters_(); + this.registers['1'] = new Register(text, linewise); + } + break; + } + this.unnamedRegister.setText(text, linewise, blockwise); + return; + } + var append = isUpperCase(registerName); + if (append) { + register.pushText(text, linewise); + } else { + register.setText(text, linewise, blockwise); + } + this.unnamedRegister.setText(register.toString(), linewise); + }, + getRegister: function(name) { + if (!this.isValidRegister(name)) { + return this.unnamedRegister; + } + name = name.toLowerCase(); + if (!this.registers[name]) { + this.registers[name] = new Register(); + } + return this.registers[name]; + }, + isValidRegister: function(name) { + return name && inArray(name, validRegisters); + }, + shiftNumericRegisters_: function() { + for (var i = 9; i >= 2; i--) { + this.registers[i] = this.getRegister('' + (i - 1)); + } + } + }; + function HistoryController() { + this.historyBuffer = []; + this.iterator; + this.initialPrefix = null; + } + HistoryController.prototype = { + nextMatch: function (input, up) { + var historyBuffer = this.historyBuffer; + var dir = up ? -1 : 1; + if (this.initialPrefix === null) this.initialPrefix = input; + for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) { + var element = historyBuffer[i]; + for (var j = 0; j <= element.length; j++) { + if (this.initialPrefix == element.substring(0, j)) { + this.iterator = i; + return element; + } + } + } + if (i >= historyBuffer.length) { + this.iterator = historyBuffer.length; + return this.initialPrefix; + } + if (i < 0 ) return input; + }, + pushInput: function(input) { + var index = this.historyBuffer.indexOf(input); + if (index > -1) this.historyBuffer.splice(index, 1); + if (input.length) this.historyBuffer.push(input); + }, + reset: function() { + this.initialPrefix = null; + this.iterator = this.historyBuffer.length; + } + }; + var commandDispatcher = { + matchCommand: function(keys, keyMap, inputState, context) { + var matches = commandMatches(keys, keyMap, context, inputState); + if (!matches.full && !matches.partial) { + return {type: 'none'}; + } else if (!matches.full && matches.partial) { + return {type: 'partial'}; + } + + var bestMatch; + for (var i = 0; i < matches.full.length; i++) { + var match = matches.full[i]; + if (!bestMatch) { + bestMatch = match; + } + } + if (bestMatch.keys.slice(-11) == '') { + inputState.selectedCharacter = lastChar(keys); + } + return {type: 'full', command: bestMatch}; + }, + processCommand: function(cm, vim, command) { + vim.inputState.repeatOverride = command.repeatOverride; + switch (command.type) { + case 'motion': + this.processMotion(cm, vim, command); + break; + case 'operator': + this.processOperator(cm, vim, command); + break; + case 'operatorMotion': + this.processOperatorMotion(cm, vim, command); + break; + case 'action': + this.processAction(cm, vim, command); + break; + case 'search': + this.processSearch(cm, vim, command); + clearInputState(cm); + break; + case 'ex': + case 'keyToEx': + this.processEx(cm, vim, command); + clearInputState(cm); + break; + default: + break; + } + }, + processMotion: function(cm, vim, command) { + vim.inputState.motion = command.motion; + vim.inputState.motionArgs = copyArgs(command.motionArgs); + this.evalInput(cm, vim); + }, + processOperator: function(cm, vim, command) { + var inputState = vim.inputState; + if (inputState.operator) { + if (inputState.operator == command.operator) { + inputState.motion = 'expandToLine'; + inputState.motionArgs = { linewise: true }; + this.evalInput(cm, vim); + return; + } else { + clearInputState(cm); + } + } + inputState.operator = command.operator; + inputState.operatorArgs = copyArgs(command.operatorArgs); + if (vim.visualMode) { + this.evalInput(cm, vim); + } + }, + processOperatorMotion: function(cm, vim, command) { + var visualMode = vim.visualMode; + var operatorMotionArgs = copyArgs(command.operatorMotionArgs); + if (operatorMotionArgs) { + if (visualMode && operatorMotionArgs.visualLine) { + vim.visualLine = true; + } + } + this.processOperator(cm, vim, command); + if (!visualMode) { + this.processMotion(cm, vim, command); + } + }, + processAction: function(cm, vim, command) { + var inputState = vim.inputState; + var repeat = inputState.getRepeat(); + var repeatIsExplicit = !!repeat; + var actionArgs = copyArgs(command.actionArgs) || {}; + if (inputState.selectedCharacter) { + actionArgs.selectedCharacter = inputState.selectedCharacter; + } + if (command.operator) { + this.processOperator(cm, vim, command); + } + if (command.motion) { + this.processMotion(cm, vim, command); + } + if (command.motion || command.operator) { + this.evalInput(cm, vim); + } + actionArgs.repeat = repeat || 1; + actionArgs.repeatIsExplicit = repeatIsExplicit; + actionArgs.registerName = inputState.registerName; + clearInputState(cm); + vim.lastMotion = null; + if (command.isEdit) { + this.recordLastEdit(vim, inputState, command); + } + actions[command.action](cm, actionArgs, vim); + }, + processSearch: function(cm, vim, command) { + if (!cm.getSearchCursor) { + return; + } + var forward = command.searchArgs.forward; + var wholeWordOnly = command.searchArgs.wholeWordOnly; + getSearchState(cm).setReversed(!forward); + var promptPrefix = (forward) ? '/' : '?'; + var originalQuery = getSearchState(cm).getQuery(); + var originalScrollPos = cm.getScrollInfo(); + function handleQuery(query, ignoreCase, smartCase) { + vimGlobalState.searchHistoryController.pushInput(query); + vimGlobalState.searchHistoryController.reset(); + try { + updateSearchQuery(cm, query, ignoreCase, smartCase); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + query); + return; + } + commandDispatcher.processMotion(cm, vim, { + type: 'motion', + motion: 'findNext', + motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist } + }); + } + function onPromptClose(query) { + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + handleQuery(query, true /** ignoreCase */, true /** smartCase */); + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isRecording) { + logSearchQuery(macroModeState, query); + } + } + function onPromptKeyUp(e, query, close) { + var keyName = CodeMirror.keyName(e), up; + if (keyName == 'Up' || keyName == 'Down') { + up = keyName == 'Up' ? true : false; + query = vimGlobalState.searchHistoryController.nextMatch(query, up) || ''; + close(query); + } else { + if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') + vimGlobalState.searchHistoryController.reset(); + } + var parsedQuery; + try { + parsedQuery = updateSearchQuery(cm, query, + true /** ignoreCase */, true /** smartCase */); + } catch (e) { + } + if (parsedQuery) { + cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30); + } else { + clearSearchHighlight(cm); + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + } + } + function onPromptKeyDown(e, query, close) { + var keyName = CodeMirror.keyName(e); + if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') { + vimGlobalState.searchHistoryController.pushInput(query); + vimGlobalState.searchHistoryController.reset(); + updateSearchQuery(cm, originalQuery); + clearSearchHighlight(cm); + cm.scrollTo(originalScrollPos.left, originalScrollPos.top); + CodeMirror.e_stop(e); + close(); + cm.focus(); + } + } + switch (command.searchArgs.querySrc) { + case 'prompt': + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { + var query = macroModeState.replaySearchQueries.shift(); + handleQuery(query, true /** ignoreCase */, false /** smartCase */); + } else { + showPrompt(cm, { + onClose: onPromptClose, + prefix: promptPrefix, + desc: searchPromptDesc, + onKeyUp: onPromptKeyUp, + onKeyDown: onPromptKeyDown + }); + } + break; + case 'wordUnderCursor': + var word = expandWordUnderCursor(cm, false /** inclusive */, + true /** forward */, false /** bigWord */, + true /** noSymbol */); + var isKeyword = true; + if (!word) { + word = expandWordUnderCursor(cm, false /** inclusive */, + true /** forward */, false /** bigWord */, + false /** noSymbol */); + isKeyword = false; + } + if (!word) { + return; + } + var query = cm.getLine(word.start.line).substring(word.start.ch, + word.end.ch); + if (isKeyword && wholeWordOnly) { + query = '\\b' + query + '\\b'; + } else { + query = escapeRegex(query); + } + vimGlobalState.jumpList.cachedCursor = cm.getCursor(); + cm.setCursor(word.start); + + handleQuery(query, true /** ignoreCase */, false /** smartCase */); + break; + } + }, + processEx: function(cm, vim, command) { + function onPromptClose(input) { + vimGlobalState.exCommandHistoryController.pushInput(input); + vimGlobalState.exCommandHistoryController.reset(); + exCommandDispatcher.processCommand(cm, input); + } + function onPromptKeyDown(e, input, close) { + var keyName = CodeMirror.keyName(e), up; + if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[') { + vimGlobalState.exCommandHistoryController.pushInput(input); + vimGlobalState.exCommandHistoryController.reset(); + CodeMirror.e_stop(e); + close(); + cm.focus(); + } + if (keyName == 'Up' || keyName == 'Down') { + up = keyName == 'Up' ? true : false; + input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || ''; + close(input); + } else { + if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') + vimGlobalState.exCommandHistoryController.reset(); + } + } + if (command.type == 'keyToEx') { + exCommandDispatcher.processCommand(cm, command.exArgs.input); + } else { + if (vim.visualMode) { + showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>', + onKeyDown: onPromptKeyDown}); + } else { + showPrompt(cm, { onClose: onPromptClose, prefix: ':', + onKeyDown: onPromptKeyDown}); + } + } + }, + evalInput: function(cm, vim) { + var inputState = vim.inputState; + var motion = inputState.motion; + var motionArgs = inputState.motionArgs || {}; + var operator = inputState.operator; + var operatorArgs = inputState.operatorArgs || {}; + var registerName = inputState.registerName; + var sel = vim.sel; + var origHead = copyCursor(vim.visualMode ? sel.head: cm.getCursor('head')); + var origAnchor = copyCursor(vim.visualMode ? sel.anchor : cm.getCursor('anchor')); + var oldHead = copyCursor(origHead); + var oldAnchor = copyCursor(origAnchor); + var newHead, newAnchor; + var repeat; + if (operator) { + this.recordLastEdit(vim, inputState); + } + if (inputState.repeatOverride !== undefined) { + repeat = inputState.repeatOverride; + } else { + repeat = inputState.getRepeat(); + } + if (repeat > 0 && motionArgs.explicitRepeat) { + motionArgs.repeatIsExplicit = true; + } else if (motionArgs.noRepeat || + (!motionArgs.explicitRepeat && repeat === 0)) { + repeat = 1; + motionArgs.repeatIsExplicit = false; + } + if (inputState.selectedCharacter) { + motionArgs.selectedCharacter = operatorArgs.selectedCharacter = + inputState.selectedCharacter; + } + motionArgs.repeat = repeat; + clearInputState(cm); + if (motion) { + var motionResult = motions[motion](cm, origHead, motionArgs, vim); + vim.lastMotion = motions[motion]; + if (!motionResult) { + return; + } + if (motionArgs.toJumplist) { + var jumpList = vimGlobalState.jumpList; + var cachedCursor = jumpList.cachedCursor; + if (cachedCursor) { + recordJumpPosition(cm, cachedCursor, motionResult); + delete jumpList.cachedCursor; + } else { + recordJumpPosition(cm, origHead, motionResult); + } + } + if (motionResult instanceof Array) { + newAnchor = motionResult[0]; + newHead = motionResult[1]; + } else { + newHead = motionResult; + } + if (!newHead) { + newHead = copyCursor(origHead); + } + if (vim.visualMode) { + if (!(vim.visualBlock && newHead.ch === Infinity)) { + newHead = clipCursorToContent(cm, newHead, vim.visualBlock); + } + if (newAnchor) { + newAnchor = clipCursorToContent(cm, newAnchor, true); + } + newAnchor = newAnchor || oldAnchor; + sel.anchor = newAnchor; + sel.head = newHead; + updateCmSelection(cm); + updateMark(cm, vim, '<', + cursorIsBefore(newAnchor, newHead) ? newAnchor + : newHead); + updateMark(cm, vim, '>', + cursorIsBefore(newAnchor, newHead) ? newHead + : newAnchor); + } else if (!operator) { + newHead = clipCursorToContent(cm, newHead); + cm.setCursor(newHead.line, newHead.ch); + } + } + if (operator) { + if (operatorArgs.lastSel) { + newAnchor = oldAnchor; + var lastSel = operatorArgs.lastSel; + var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line); + var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch); + if (lastSel.visualLine) { + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); + } else if (lastSel.visualBlock) { + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset); + } else if (lastSel.head.line == lastSel.anchor.line) { + newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset); + } else { + newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); + } + vim.visualMode = true; + vim.visualLine = lastSel.visualLine; + vim.visualBlock = lastSel.visualBlock; + sel = vim.sel = { + anchor: newAnchor, + head: newHead + }; + updateCmSelection(cm); + } else if (vim.visualMode) { + operatorArgs.lastSel = { + anchor: copyCursor(sel.anchor), + head: copyCursor(sel.head), + visualBlock: vim.visualBlock, + visualLine: vim.visualLine + }; + } + var curStart, curEnd, linewise, mode; + var cmSel; + if (vim.visualMode) { + curStart = cursorMin(sel.head, sel.anchor); + curEnd = cursorMax(sel.head, sel.anchor); + linewise = vim.visualLine || operatorArgs.linewise; + mode = vim.visualBlock ? 'block' : + linewise ? 'line' : + 'char'; + cmSel = makeCmSelection(cm, { + anchor: curStart, + head: curEnd + }, mode); + if (linewise) { + var ranges = cmSel.ranges; + if (mode == 'block') { + for (var i = 0; i < ranges.length; i++) { + ranges[i].head.ch = lineLength(cm, ranges[i].head.line); + } + } else if (mode == 'line') { + ranges[0].head = Pos(ranges[0].head.line + 1, 0); + } + } + } else { + curStart = copyCursor(newAnchor || oldAnchor); + curEnd = copyCursor(newHead || oldHead); + if (cursorIsBefore(curEnd, curStart)) { + var tmp = curStart; + curStart = curEnd; + curEnd = tmp; + } + linewise = motionArgs.linewise || operatorArgs.linewise; + if (linewise) { + expandSelectionToLine(cm, curStart, curEnd); + } else if (motionArgs.forward) { + clipToLine(cm, curStart, curEnd); + } + mode = 'char'; + var exclusive = !motionArgs.inclusive || linewise; + cmSel = makeCmSelection(cm, { + anchor: curStart, + head: curEnd + }, mode, exclusive); + } + cm.setSelections(cmSel.ranges, cmSel.primary); + vim.lastMotion = null; + operatorArgs.repeat = repeat; // For indent in visual mode. + operatorArgs.registerName = registerName; + operatorArgs.linewise = linewise; + var operatorMoveTo = operators[operator]( + cm, operatorArgs, cmSel.ranges, oldAnchor, newHead); + if (vim.visualMode) { + exitVisualMode(cm); + } + if (operatorMoveTo) { + cm.setCursor(operatorMoveTo); + } + } + }, + recordLastEdit: function(vim, inputState, actionCommand) { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { return; } + vim.lastEditInputState = inputState; + vim.lastEditActionCommand = actionCommand; + macroModeState.lastInsertModeChanges.changes = []; + macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false; + } + }; + var motions = { + moveToTopLine: function(cm, _head, motionArgs) { + var line = getUserVisibleLines(cm).top + motionArgs.repeat -1; + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + moveToMiddleLine: function(cm) { + var range = getUserVisibleLines(cm); + var line = Math.floor((range.top + range.bottom) * 0.5); + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + moveToBottomLine: function(cm, _head, motionArgs) { + var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1; + return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); + }, + expandToLine: function(_cm, head, motionArgs) { + var cur = head; + return Pos(cur.line + motionArgs.repeat - 1, Infinity); + }, + findNext: function(cm, _head, motionArgs) { + var state = getSearchState(cm); + var query = state.getQuery(); + if (!query) { + return; + } + var prev = !motionArgs.forward; + prev = (state.isReversed()) ? !prev : prev; + highlightSearchMatches(cm, query); + return findNext(cm, prev/** prev */, query, motionArgs.repeat); + }, + goToMark: function(cm, _head, motionArgs, vim) { + var mark = vim.marks[motionArgs.selectedCharacter]; + if (mark) { + var pos = mark.find(); + return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos; + } + return null; + }, + moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) { + if (vim.visualBlock && motionArgs.sameLine) { + var sel = vim.sel; + return [ + clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)), + clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch)) + ]; + } else { + return ([vim.sel.head, vim.sel.anchor]); + } + }, + jumpToMark: function(cm, head, motionArgs, vim) { + var best = head; + for (var i = 0; i < motionArgs.repeat; i++) { + var cursor = best; + for (var key in vim.marks) { + if (!isLowerCase(key)) { + continue; + } + var mark = vim.marks[key].find(); + var isWrongDirection = (motionArgs.forward) ? + cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark); + + if (isWrongDirection) { + continue; + } + if (motionArgs.linewise && (mark.line == cursor.line)) { + continue; + } + + var equal = cursorEqual(cursor, best); + var between = (motionArgs.forward) ? + cursorIsBetween(cursor, mark, best) : + cursorIsBetween(best, mark, cursor); + + if (equal || between) { + best = mark; + } + } + } + + if (motionArgs.linewise) { + best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line))); + } + return best; + }, + moveByCharacters: function(_cm, head, motionArgs) { + var cur = head; + var repeat = motionArgs.repeat; + var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; + return Pos(cur.line, ch); + }, + moveByLines: function(cm, head, motionArgs, vim) { + var cur = head; + var endCh = cur.ch; + switch (vim.lastMotion) { + case this.moveByLines: + case this.moveByDisplayLines: + case this.moveByScroll: + case this.moveToColumn: + case this.moveToEol: + endCh = vim.lastHPos; + break; + default: + vim.lastHPos = endCh; + } + var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0); + var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; + var first = cm.firstLine(); + var last = cm.lastLine(); + if ((line < first && cur.line == first) || + (line > last && cur.line == last)) { + return; + } + var fold = cm.ace.session.getFoldAt(line, endCh); + if (fold) { + if (motionArgs.forward) + line = fold.end.row + 1; + else + line = fold.start.row - 1; + } + if (motionArgs.toFirstChar){ + endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line)); + vim.lastHPos = endCh; + } + vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left; + return Pos(line, endCh); + }, + moveByDisplayLines: function(cm, head, motionArgs, vim) { + var cur = head; + switch (vim.lastMotion) { + case this.moveByDisplayLines: + case this.moveByScroll: + case this.moveByLines: + case this.moveToColumn: + case this.moveToEol: + break; + default: + vim.lastHSPos = cm.charCoords(cur,'div').left; + } + var repeat = motionArgs.repeat; + var res=cm.findPosV(cur,(motionArgs.forward ? repeat : -repeat),'line',vim.lastHSPos); + if (res.hitSide) { + if (motionArgs.forward) { + var lastCharCoords = cm.charCoords(res, 'div'); + var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos }; + var res = cm.coordsChar(goalCoords, 'div'); + } else { + var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div'); + resCoords.left = vim.lastHSPos; + res = cm.coordsChar(resCoords, 'div'); + } + } + vim.lastHPos = res.ch; + return res; + }, + moveByPage: function(cm, head, motionArgs) { + var curStart = head; + var repeat = motionArgs.repeat; + return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); + }, + moveByParagraph: function(cm, head, motionArgs) { + var dir = motionArgs.forward ? 1 : -1; + return findParagraph(cm, head, motionArgs.repeat, dir); + }, + moveByScroll: function(cm, head, motionArgs, vim) { + var scrollbox = cm.getScrollInfo(); + var curEnd = null; + var repeat = motionArgs.repeat; + if (!repeat) { + repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); + } + var orig = cm.charCoords(head, 'local'); + motionArgs.repeat = repeat; + var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim); + if (!curEnd) { + return null; + } + var dest = cm.charCoords(curEnd, 'local'); + cm.scrollTo(null, scrollbox.top + dest.top - orig.top); + return curEnd; + }, + moveByWords: function(cm, head, motionArgs) { + return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward, + !!motionArgs.wordEnd, !!motionArgs.bigWord); + }, + moveTillCharacter: function(cm, _head, motionArgs) { + var repeat = motionArgs.repeat; + var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter); + var increment = motionArgs.forward ? -1 : 1; + recordLastCharacterSearch(increment, motionArgs); + if (!curEnd) return null; + curEnd.ch += increment; + return curEnd; + }, + moveToCharacter: function(cm, head, motionArgs) { + var repeat = motionArgs.repeat; + recordLastCharacterSearch(0, motionArgs); + return moveToCharacter(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter) || head; + }, + moveToSymbol: function(cm, head, motionArgs) { + var repeat = motionArgs.repeat; + return findSymbol(cm, repeat, motionArgs.forward, + motionArgs.selectedCharacter) || head; + }, + moveToColumn: function(cm, head, motionArgs, vim) { + var repeat = motionArgs.repeat; + vim.lastHPos = repeat - 1; + vim.lastHSPos = cm.charCoords(head,'div').left; + return moveToColumn(cm, repeat); + }, + moveToEol: function(cm, head, motionArgs, vim) { + var cur = head; + vim.lastHPos = Infinity; + var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); + var end=cm.clipPos(retval); + end.ch--; + vim.lastHSPos = cm.charCoords(end,'div').left; + return retval; + }, + moveToFirstNonWhiteSpaceCharacter: function(cm, head) { + var cursor = head; + return Pos(cursor.line, + findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); + }, + moveToMatchedSymbol: function(cm, head) { + var cursor = head; + var line = cursor.line; + var ch = cursor.ch; + var lineText = cm.getLine(line); + var symbol; + do { + symbol = lineText.charAt(ch++); + if (symbol && isMatchableSymbol(symbol)) { + var style = cm.getTokenTypeAt(Pos(line, ch)); + if (style !== "string" && style !== "comment") { + break; + } + } + } while (symbol); + if (symbol) { + var matched = cm.findMatchingBracket(Pos(line, ch)); + return matched.to; + } else { + return cursor; + } + }, + moveToStartOfLine: function(_cm, head) { + return Pos(head.line, 0); + }, + moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) { + var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); + if (motionArgs.repeatIsExplicit) { + lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); + } + return Pos(lineNum, + findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); + }, + textObjectManipulation: function(cm, head, motionArgs, vim) { + var mirroredPairs = {'(': ')', ')': '(', + '{': '}', '}': '{', + '[': ']', ']': '['}; + var selfPaired = {'\'': true, '"': true}; + + var character = motionArgs.selectedCharacter; + if (character == 'b') { + character = '('; + } else if (character == 'B') { + character = '{'; + } + var inclusive = !motionArgs.textObjectInner; + + var tmp; + if (mirroredPairs[character]) { + tmp = selectCompanionObject(cm, head, character, inclusive); + } else if (selfPaired[character]) { + tmp = findBeginningAndEnd(cm, head, character, inclusive); + } else if (character === 'W') { + tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, + true /** bigWord */); + } else if (character === 'w') { + tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, + false /** bigWord */); + } else if (character === 'p') { + tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive); + motionArgs.linewise = true; + if (vim.visualMode) { + if (!vim.visualLine) { vim.visualLine = true; } + } else { + var operatorArgs = vim.inputState.operatorArgs; + if (operatorArgs) { operatorArgs.linewise = true; } + tmp.end.line--; + } + } else { + return null; + } + + if (!cm.state.vim.visualMode) { + return [tmp.start, tmp.end]; + } else { + return expandSelection(cm, tmp.start, tmp.end); + } + }, + + repeatLastCharacterSearch: function(cm, head, motionArgs) { + var lastSearch = vimGlobalState.lastChararacterSearch; + var repeat = motionArgs.repeat; + var forward = motionArgs.forward === lastSearch.forward; + var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1); + cm.moveH(-increment, 'char'); + motionArgs.inclusive = forward ? true : false; + var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); + if (!curEnd) { + cm.moveH(increment, 'char'); + return head; + } + curEnd.ch += increment; + return curEnd; + } + }; + + function fillArray(val, times) { + var arr = []; + for (var i = 0; i < times; i++) { + arr.push(val); + } + return arr; + } + var operators = { + change: function(cm, args, ranges) { + var finalHead, text; + var vim = cm.state.vim; + vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock; + if (!vim.visualMode) { + var anchor = ranges[0].anchor, + head = ranges[0].head; + text = cm.getRange(anchor, head); + if (!isWhiteSpaceString(text)) { + var match = (/\s+$/).exec(text); + if (match) { + head = offsetCursor(head, 0, - match[0].length); + text = text.slice(0, - match[0].length); + } + } + var wasLastLine = head.line - 1 == cm.lastLine(); + cm.replaceRange('', anchor, head); + if (args.linewise && !wasLastLine) { + CodeMirror.commands.newlineAndIndent(cm); + anchor.ch = null; + } + finalHead = anchor; + } else { + text = cm.getSelection(); + var replacement = fillArray('', ranges.length); + cm.replaceSelections(replacement); + finalHead = cursorMin(ranges[0].head, ranges[0].anchor); + } + vimGlobalState.registerController.pushText( + args.registerName, 'change', text, + args.linewise, ranges.length > 1); + actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim); + }, + 'delete': function(cm, args, ranges) { + var finalHead, text; + var vim = cm.state.vim; + if (!vim.visualBlock) { + var anchor = ranges[0].anchor, + head = ranges[0].head; + if (args.linewise && + head.line != cm.firstLine() && + anchor.line == cm.lastLine() && + anchor.line == head.line - 1) { + if (anchor.line == cm.firstLine()) { + anchor.ch = 0; + } else { + anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1)); + } + } + text = cm.getRange(anchor, head); + cm.replaceRange('', anchor, head); + finalHead = anchor; + if (args.linewise) { + finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor); + } + } else { + text = cm.getSelection(); + var replacement = fillArray('', ranges.length); + cm.replaceSelections(replacement); + finalHead = ranges[0].anchor; + } + vimGlobalState.registerController.pushText( + args.registerName, 'delete', text, + args.linewise, vim.visualBlock); + return finalHead; + }, + indent: function(cm, args, ranges) { + var vim = cm.state.vim; + var startLine = ranges[0].anchor.line; + var endLine = vim.visualBlock ? + ranges[ranges.length - 1].anchor.line : + ranges[0].head.line; + var repeat = (vim.visualMode) ? args.repeat : 1; + if (args.linewise) { + endLine--; + } + for (var i = startLine; i <= endLine; i++) { + for (var j = 0; j < repeat; j++) { + cm.indentLine(i, args.indentRight); + } + } + return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor); + }, + changeCase: function(cm, args, ranges, oldAnchor, newHead) { + var selections = cm.getSelections(); + var swapped = []; + var toLower = args.toLower; + for (var j = 0; j < selections.length; j++) { + var toSwap = selections[j]; + var text = ''; + if (toLower === true) { + text = toSwap.toLowerCase(); + } else if (toLower === false) { + text = toSwap.toUpperCase(); + } else { + for (var i = 0; i < toSwap.length; i++) { + var character = toSwap.charAt(i); + text += isUpperCase(character) ? character.toLowerCase() : + character.toUpperCase(); + } + } + swapped.push(text); + } + cm.replaceSelections(swapped); + if (args.shouldMoveCursor){ + return newHead; + } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) { + return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor); + } else if (args.linewise){ + return oldAnchor; + } else { + return cursorMin(ranges[0].anchor, ranges[0].head); + } + }, + yank: function(cm, args, ranges, oldAnchor) { + var vim = cm.state.vim; + var text = cm.getSelection(); + var endPos = vim.visualMode + ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor) + : oldAnchor; + vimGlobalState.registerController.pushText( + args.registerName, 'yank', + text, args.linewise, vim.visualBlock); + return endPos; + } + }; + + var actions = { + jumpListWalk: function(cm, actionArgs, vim) { + if (vim.visualMode) { + return; + } + var repeat = actionArgs.repeat; + var forward = actionArgs.forward; + var jumpList = vimGlobalState.jumpList; + + var mark = jumpList.move(cm, forward ? repeat : -repeat); + var markPos = mark ? mark.find() : undefined; + markPos = markPos ? markPos : cm.getCursor(); + cm.setCursor(markPos); + }, + scroll: function(cm, actionArgs, vim) { + if (vim.visualMode) { + return; + } + var repeat = actionArgs.repeat || 1; + var lineHeight = cm.defaultTextHeight(); + var top = cm.getScrollInfo().top; + var delta = lineHeight * repeat; + var newPos = actionArgs.forward ? top + delta : top - delta; + var cursor = copyCursor(cm.getCursor()); + var cursorCoords = cm.charCoords(cursor, 'local'); + if (actionArgs.forward) { + if (newPos > cursorCoords.top) { + cursor.line += (newPos - cursorCoords.top) / lineHeight; + cursor.line = Math.ceil(cursor.line); + cm.setCursor(cursor); + cursorCoords = cm.charCoords(cursor, 'local'); + cm.scrollTo(null, cursorCoords.top); + } else { + cm.scrollTo(null, newPos); + } + } else { + var newBottom = newPos + cm.getScrollInfo().clientHeight; + if (newBottom < cursorCoords.bottom) { + cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight; + cursor.line = Math.floor(cursor.line); + cm.setCursor(cursor); + cursorCoords = cm.charCoords(cursor, 'local'); + cm.scrollTo( + null, cursorCoords.bottom - cm.getScrollInfo().clientHeight); + } else { + cm.scrollTo(null, newPos); + } + } + }, + scrollToCursor: function(cm, actionArgs) { + var lineNum = cm.getCursor().line; + var charCoords = cm.charCoords(Pos(lineNum, 0), 'local'); + var height = cm.getScrollInfo().clientHeight; + var y = charCoords.top; + var lineHeight = charCoords.bottom - y; + switch (actionArgs.position) { + case 'center': y = y - (height / 2) + lineHeight; + break; + case 'bottom': y = y - height + lineHeight*1.4; + break; + case 'top': y = y + lineHeight*0.4; + break; + } + cm.scrollTo(null, y); + }, + replayMacro: function(cm, actionArgs, vim) { + var registerName = actionArgs.selectedCharacter; + var repeat = actionArgs.repeat; + var macroModeState = vimGlobalState.macroModeState; + if (registerName == '@') { + registerName = macroModeState.latestRegister; + } + while(repeat--){ + executeMacroRegister(cm, vim, macroModeState, registerName); + } + }, + enterMacroRecordMode: function(cm, actionArgs) { + var macroModeState = vimGlobalState.macroModeState; + var registerName = actionArgs.selectedCharacter; + macroModeState.enterMacroRecordMode(cm, registerName); + }, + enterInsertMode: function(cm, actionArgs, vim) { + if (cm.getOption('readOnly')) { return; } + vim.insertMode = true; + vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; + var insertAt = (actionArgs) ? actionArgs.insertAt : null; + var sel = vim.sel; + var head = actionArgs.head || cm.getCursor('head'); + var height = cm.listSelections().length; + if (insertAt == 'eol') { + head = Pos(head.line, lineLength(cm, head.line)); + } else if (insertAt == 'charAfter') { + head = offsetCursor(head, 0, 1); + } else if (insertAt == 'firstNonBlank') { + head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head); + } else if (insertAt == 'startOfSelectedArea') { + if (!vim.visualBlock) { + if (sel.head.line < sel.anchor.line) { + head = sel.head; + } else { + head = Pos(sel.anchor.line, 0); + } + } else { + head = Pos( + Math.min(sel.head.line, sel.anchor.line), + Math.min(sel.head.ch, sel.anchor.ch)); + height = Math.abs(sel.head.line - sel.anchor.line) + 1; + } + } else if (insertAt == 'endOfSelectedArea') { + if (!vim.visualBlock) { + if (sel.head.line >= sel.anchor.line) { + head = offsetCursor(sel.head, 0, 1); + } else { + head = Pos(sel.anchor.line, 0); + } + } else { + head = Pos( + Math.min(sel.head.line, sel.anchor.line), + Math.max(sel.head.ch + 1, sel.anchor.ch)); + height = Math.abs(sel.head.line - sel.anchor.line) + 1; + } + } else if (insertAt == 'inplace') { + if (vim.visualMode){ + return; + } + } + cm.setOption('keyMap', 'vim-insert'); + cm.setOption('disableInput', false); + if (actionArgs && actionArgs.replace) { + cm.toggleOverwrite(true); + cm.setOption('keyMap', 'vim-replace'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); + } else { + cm.setOption('keyMap', 'vim-insert'); + CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); + } + if (!vimGlobalState.macroModeState.isPlaying) { + cm.on('change', onChange); + CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); + } + if (vim.visualMode) { + exitVisualMode(cm); + } + selectForInsert(cm, head, height); + }, + toggleVisualMode: function(cm, actionArgs, vim) { + var repeat = actionArgs.repeat; + var anchor = cm.getCursor(); + var head; + if (!vim.visualMode) { + vim.visualMode = true; + vim.visualLine = !!actionArgs.linewise; + vim.visualBlock = !!actionArgs.blockwise; + head = clipCursorToContent( + cm, Pos(anchor.line, anchor.ch + repeat - 1), + true /** includeLineBreak */); + vim.sel = { + anchor: anchor, + head: head + }; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); + updateCmSelection(cm); + updateMark(cm, vim, '<', cursorMin(anchor, head)); + updateMark(cm, vim, '>', cursorMax(anchor, head)); + } else if (vim.visualLine ^ actionArgs.linewise || + vim.visualBlock ^ actionArgs.blockwise) { + vim.visualLine = !!actionArgs.linewise; + vim.visualBlock = !!actionArgs.blockwise; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); + updateCmSelection(cm); + } else { + exitVisualMode(cm); + } + }, + reselectLastSelection: function(cm, _actionArgs, vim) { + var lastSelection = vim.lastSelection; + if (vim.visualMode) { + updateLastSelection(cm, vim); + } + if (lastSelection) { + var anchor = lastSelection.anchorMark.find(); + var head = lastSelection.headMark.find(); + if (!anchor || !head) { + return; + } + vim.sel = { + anchor: anchor, + head: head + }; + vim.visualMode = true; + vim.visualLine = lastSelection.visualLine; + vim.visualBlock = lastSelection.visualBlock; + updateCmSelection(cm); + updateMark(cm, vim, '<', cursorMin(anchor, head)); + updateMark(cm, vim, '>', cursorMax(anchor, head)); + CodeMirror.signal(cm, 'vim-mode-change', { + mode: 'visual', + subMode: vim.visualLine ? 'linewise' : + vim.visualBlock ? 'blockwise' : ''}); + } + }, + joinLines: function(cm, actionArgs, vim) { + var curStart, curEnd; + if (vim.visualMode) { + curStart = cm.getCursor('anchor'); + curEnd = cm.getCursor('head'); + curEnd.ch = lineLength(cm, curEnd.line) - 1; + } else { + var repeat = Math.max(actionArgs.repeat, 2); + curStart = cm.getCursor(); + curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1, + Infinity)); + } + var finalCh = 0; + for (var i = curStart.line; i < curEnd.line; i++) { + finalCh = lineLength(cm, curStart.line); + var tmp = Pos(curStart.line + 1, + lineLength(cm, curStart.line + 1)); + var text = cm.getRange(curStart, tmp); + text = text.replace(/\n\s*/g, ' '); + cm.replaceRange(text, curStart, tmp); + } + var curFinalPos = Pos(curStart.line, finalCh); + cm.setCursor(curFinalPos); + if (vim.visualMode) { + exitVisualMode(cm); + } + }, + newLineAndEnterInsertMode: function(cm, actionArgs, vim) { + vim.insertMode = true; + var insertAt = copyCursor(cm.getCursor()); + if (insertAt.line === cm.firstLine() && !actionArgs.after) { + cm.replaceRange('\n', Pos(cm.firstLine(), 0)); + cm.setCursor(cm.firstLine(), 0); + } else { + insertAt.line = (actionArgs.after) ? insertAt.line : + insertAt.line - 1; + insertAt.ch = lineLength(cm, insertAt.line); + cm.setCursor(insertAt); + var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment || + CodeMirror.commands.newlineAndIndent; + newlineFn(cm); + } + this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim); + }, + paste: function(cm, actionArgs, vim) { + var cur = copyCursor(cm.getCursor()); + var register = vimGlobalState.registerController.getRegister( + actionArgs.registerName); + var text = register.toString(); + if (!text) { + return; + } + if (actionArgs.matchIndent) { + var tabSize = cm.getOption("tabSize"); + var whitespaceLength = function(str) { + var tabs = (str.split("\t").length - 1); + var spaces = (str.split(" ").length - 1); + return tabs * tabSize + spaces * 1; + }; + var currentLine = cm.getLine(cm.getCursor().line); + var indent = whitespaceLength(currentLine.match(/^\s*/)[0]); + var chompedText = text.replace(/\n$/, ''); + var wasChomped = text !== chompedText; + var firstIndent = whitespaceLength(text.match(/^\s*/)[0]); + var text = chompedText.replace(/^\s*/gm, function(wspace) { + var newIndent = indent + (whitespaceLength(wspace) - firstIndent); + if (newIndent < 0) { + return ""; + } + else if (cm.getOption("indentWithTabs")) { + var quotient = Math.floor(newIndent / tabSize); + return Array(quotient + 1).join('\t'); + } + else { + return Array(newIndent + 1).join(' '); + } + }); + text += wasChomped ? "\n" : ""; + } + if (actionArgs.repeat > 1) { + var text = Array(actionArgs.repeat + 1).join(text); + } + var linewise = register.linewise; + var blockwise = register.blockwise; + if (linewise) { + if(vim.visualMode) { + text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; + } else if (actionArgs.after) { + text = '\n' + text.slice(0, text.length - 1); + cur.ch = lineLength(cm, cur.line); + } else { + cur.ch = 0; + } + } else { + if (blockwise) { + text = text.split('\n'); + for (var i = 0; i < text.length; i++) { + text[i] = (text[i] == '') ? ' ' : text[i]; + } + } + cur.ch += actionArgs.after ? 1 : 0; + } + var curPosFinal; + var idx; + if (vim.visualMode) { + vim.lastPastedText = text; + var lastSelectionCurEnd; + var selectedArea = getSelectedAreaRange(cm, vim); + var selectionStart = selectedArea[0]; + var selectionEnd = selectedArea[1]; + var selectedText = cm.getSelection(); + var selections = cm.listSelections(); + var emptyStrings = new Array(selections.length).join('1').split('1'); + if (vim.lastSelection) { + lastSelectionCurEnd = vim.lastSelection.headMark.find(); + } + vimGlobalState.registerController.unnamedRegister.setText(selectedText); + if (blockwise) { + cm.replaceSelections(emptyStrings); + selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch); + cm.setCursor(selectionStart); + selectBlock(cm, selectionEnd); + cm.replaceSelections(text); + curPosFinal = selectionStart; + } else if (vim.visualBlock) { + cm.replaceSelections(emptyStrings); + cm.setCursor(selectionStart); + cm.replaceRange(text, selectionStart, selectionStart); + curPosFinal = selectionStart; + } else { + cm.replaceRange(text, selectionStart, selectionEnd); + curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1); + } + if(lastSelectionCurEnd) { + vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd); + } + if (linewise) { + curPosFinal.ch=0; + } + } else { + if (blockwise) { + cm.setCursor(cur); + for (var i = 0; i < text.length; i++) { + var line = cur.line+i; + if (line > cm.lastLine()) { + cm.replaceRange('\n', Pos(line, 0)); + } + var lastCh = lineLength(cm, line); + if (lastCh < cur.ch) { + extendLineToColumn(cm, line, cur.ch); + } + } + cm.setCursor(cur); + selectBlock(cm, Pos(cur.line + text.length-1, cur.ch)); + cm.replaceSelections(text); + curPosFinal = cur; + } else { + cm.replaceRange(text, cur); + if (linewise && actionArgs.after) { + curPosFinal = Pos( + cur.line + 1, + findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))); + } else if (linewise && !actionArgs.after) { + curPosFinal = Pos( + cur.line, + findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))); + } else if (!linewise && actionArgs.after) { + idx = cm.indexFromPos(cur); + curPosFinal = cm.posFromIndex(idx + text.length - 1); + } else { + idx = cm.indexFromPos(cur); + curPosFinal = cm.posFromIndex(idx + text.length); + } + } + } + if (vim.visualMode) { + exitVisualMode(cm); + } + cm.setCursor(curPosFinal); + }, + undo: function(cm, actionArgs) { + cm.operation(function() { + repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)(); + cm.setCursor(cm.getCursor('anchor')); + }); + }, + redo: function(cm, actionArgs) { + repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)(); + }, + setRegister: function(_cm, actionArgs, vim) { + vim.inputState.registerName = actionArgs.selectedCharacter; + }, + setMark: function(cm, actionArgs, vim) { + var markName = actionArgs.selectedCharacter; + updateMark(cm, vim, markName, cm.getCursor()); + }, + replace: function(cm, actionArgs, vim) { + var replaceWith = actionArgs.selectedCharacter; + var curStart = cm.getCursor(); + var replaceTo; + var curEnd; + var selections = cm.listSelections(); + if (vim.visualMode) { + curStart = cm.getCursor('start'); + curEnd = cm.getCursor('end'); + } else { + var line = cm.getLine(curStart.line); + replaceTo = curStart.ch + actionArgs.repeat; + if (replaceTo > line.length) { + replaceTo=line.length; + } + curEnd = Pos(curStart.line, replaceTo); + } + if (replaceWith=='\n') { + if (!vim.visualMode) cm.replaceRange('', curStart, curEnd); + (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm); + } else { + var replaceWithStr = cm.getRange(curStart, curEnd); + replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith); + if (vim.visualBlock) { + var spaces = new Array(cm.getOption("tabSize")+1).join(' '); + replaceWithStr = cm.getSelection(); + replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); + cm.replaceSelections(replaceWithStr); + } else { + cm.replaceRange(replaceWithStr, curStart, curEnd); + } + if (vim.visualMode) { + curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ? + selections[0].anchor : selections[0].head; + cm.setCursor(curStart); + exitVisualMode(cm); + } else { + cm.setCursor(offsetCursor(curEnd, 0, -1)); + } + } + }, + incrementNumberToken: function(cm, actionArgs) { + var cur = cm.getCursor(); + var lineStr = cm.getLine(cur.line); + var re = /-?\d+/g; + var match; + var start; + var end; + var numberStr; + var token; + while ((match = re.exec(lineStr)) !== null) { + token = match[0]; + start = match.index; + end = start + token.length; + if (cur.ch < end)break; + } + if (!actionArgs.backtrack && (end <= cur.ch))return; + if (token) { + var increment = actionArgs.increase ? 1 : -1; + var number = parseInt(token) + (increment * actionArgs.repeat); + var from = Pos(cur.line, start); + var to = Pos(cur.line, end); + numberStr = number.toString(); + cm.replaceRange(numberStr, from, to); + } else { + return; + } + cm.setCursor(Pos(cur.line, start + numberStr.length - 1)); + }, + repeatLastEdit: function(cm, actionArgs, vim) { + var lastEditInputState = vim.lastEditInputState; + if (!lastEditInputState) { return; } + var repeat = actionArgs.repeat; + if (repeat && actionArgs.repeatIsExplicit) { + vim.lastEditInputState.repeatOverride = repeat; + } else { + repeat = vim.lastEditInputState.repeatOverride || repeat; + } + repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); + }, + exitInsertMode: exitInsertMode + }; + function clipCursorToContent(cm, cur, includeLineBreak) { + var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() ); + var maxCh = lineLength(cm, line) - 1; + maxCh = (includeLineBreak) ? maxCh + 1 : maxCh; + var ch = Math.min(Math.max(0, cur.ch), maxCh); + return Pos(line, ch); + } + function copyArgs(args) { + var ret = {}; + for (var prop in args) { + if (args.hasOwnProperty(prop)) { + ret[prop] = args[prop]; + } + } + return ret; + } + function offsetCursor(cur, offsetLine, offsetCh) { + if (typeof offsetLine === 'object') { + offsetCh = offsetLine.ch; + offsetLine = offsetLine.line; + } + return Pos(cur.line + offsetLine, cur.ch + offsetCh); + } + function getOffset(anchor, head) { + return { + line: head.line - anchor.line, + ch: head.line - anchor.line + }; + } + function commandMatches(keys, keyMap, context, inputState) { + var match, partial = [], full = []; + for (var i = 0; i < keyMap.length; i++) { + var command = keyMap[i]; + if (context == 'insert' && command.context != 'insert' || + command.context && command.context != context || + inputState.operator && command.type == 'action' || + !(match = commandMatch(keys, command.keys))) { continue; } + if (match == 'partial') { partial.push(command); } + if (match == 'full') { full.push(command); } + } + return { + partial: partial.length && partial, + full: full.length && full + }; + } + function commandMatch(pressed, mapped) { + if (mapped.slice(-11) == '') { + var prefixLen = mapped.length - 11; + var pressedPrefix = pressed.slice(0, prefixLen); + var mappedPrefix = mapped.slice(0, prefixLen); + return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' : + mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false; + } else { + return pressed == mapped ? 'full' : + mapped.indexOf(pressed) == 0 ? 'partial' : false; + } + } + function lastChar(keys) { + var match = /^.*(<[\w\-]+>)$/.exec(keys); + var selectedCharacter = match ? match[1] : keys.slice(-1); + if (selectedCharacter.length > 1){ + switch(selectedCharacter){ + case '': + selectedCharacter='\n'; + break; + case '': + selectedCharacter=' '; + break; + default: + break; + } + } + return selectedCharacter; + } + function repeatFn(cm, fn, repeat) { + return function() { + for (var i = 0; i < repeat; i++) { + fn(cm); + } + }; + } + function copyCursor(cur) { + return Pos(cur.line, cur.ch); + } + function cursorEqual(cur1, cur2) { + return cur1.ch == cur2.ch && cur1.line == cur2.line; + } + function cursorIsBefore(cur1, cur2) { + if (cur1.line < cur2.line) { + return true; + } + if (cur1.line == cur2.line && cur1.ch < cur2.ch) { + return true; + } + return false; + } + function cursorMin(cur1, cur2) { + if (arguments.length > 2) { + cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1)); + } + return cursorIsBefore(cur1, cur2) ? cur1 : cur2; + } + function cursorMax(cur1, cur2) { + if (arguments.length > 2) { + cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1)); + } + return cursorIsBefore(cur1, cur2) ? cur2 : cur1; + } + function cursorIsBetween(cur1, cur2, cur3) { + var cur1before2 = cursorIsBefore(cur1, cur2); + var cur2before3 = cursorIsBefore(cur2, cur3); + return cur1before2 && cur2before3; + } + function lineLength(cm, lineNum) { + return cm.getLine(lineNum).length; + } + function reverse(s){ + return s.split('').reverse().join(''); + } + function trim(s) { + if (s.trim) { + return s.trim(); + } + return s.replace(/^\s+|\s+$/g, ''); + } + function escapeRegex(s) { + return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1'); + } + function extendLineToColumn(cm, lineNum, column) { + var endCh = lineLength(cm, lineNum); + var spaces = new Array(column-endCh+1).join(' '); + cm.setCursor(Pos(lineNum, endCh)); + cm.replaceRange(spaces, cm.getCursor()); + } + function selectBlock(cm, selectionEnd) { + var selections = [], ranges = cm.listSelections(); + var head = copyCursor(cm.clipPos(selectionEnd)); + var isClipped = !cursorEqual(selectionEnd, head); + var curHead = cm.getCursor('head'); + var primIndex = getIndex(ranges, curHead); + var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor); + var max = ranges.length - 1; + var index = max - primIndex > primIndex ? max : 0; + var base = ranges[index].anchor; + + var firstLine = Math.min(base.line, head.line); + var lastLine = Math.max(base.line, head.line); + var baseCh = base.ch, headCh = head.ch; + + var dir = ranges[index].head.ch - baseCh; + var newDir = headCh - baseCh; + if (dir > 0 && newDir <= 0) { + baseCh++; + if (!isClipped) { headCh--; } + } else if (dir < 0 && newDir >= 0) { + baseCh--; + if (!wasClipped) { headCh++; } + } else if (dir < 0 && newDir == -1) { + baseCh--; + headCh++; + } + for (var line = firstLine; line <= lastLine; line++) { + var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)}; + selections.push(range); + } + primIndex = head.line == lastLine ? selections.length - 1 : 0; + cm.setSelections(selections); + selectionEnd.ch = headCh; + base.ch = baseCh; + return base; + } + function selectForInsert(cm, head, height) { + var sel = []; + for (var i = 0; i < height; i++) { + var lineHead = offsetCursor(head, i, 0); + sel.push({anchor: lineHead, head: lineHead}); + } + cm.setSelections(sel, 0); + } + function getIndex(ranges, cursor, end) { + for (var i = 0; i < ranges.length; i++) { + var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor); + var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor); + if (atAnchor || atHead) { + return i; + } + } + return -1; + } + function getSelectedAreaRange(cm, vim) { + var lastSelection = vim.lastSelection; + var getCurrentSelectedAreaRange = function() { + var selections = cm.listSelections(); + var start = selections[0]; + var end = selections[selections.length-1]; + var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; + var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; + return [selectionStart, selectionEnd]; + }; + var getLastSelectedAreaRange = function() { + var selectionStart = cm.getCursor(); + var selectionEnd = cm.getCursor(); + var block = lastSelection.visualBlock; + if (block) { + var width = block.width; + var height = block.height; + selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width); + var selections = []; + for (var i = selectionStart.line; i < selectionEnd.line; i++) { + var anchor = Pos(i, selectionStart.ch); + var head = Pos(i, selectionEnd.ch); + var range = {anchor: anchor, head: head}; + selections.push(range); + } + cm.setSelections(selections); + } else { + var start = lastSelection.anchorMark.find(); + var end = lastSelection.headMark.find(); + var line = end.line - start.line; + var ch = end.ch - start.ch; + selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; + if (lastSelection.visualLine) { + selectionStart = Pos(selectionStart.line, 0); + selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line)); + } + cm.setSelection(selectionStart, selectionEnd); + } + return [selectionStart, selectionEnd]; + }; + if (!vim.visualMode) { + return getLastSelectedAreaRange(); + } else { + return getCurrentSelectedAreaRange(); + } + } + function updateLastSelection(cm, vim) { + var anchor = vim.sel.anchor; + var head = vim.sel.head; + if (vim.lastPastedText) { + head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length); + vim.lastPastedText = null; + } + vim.lastSelection = {'anchorMark': cm.setBookmark(anchor), + 'headMark': cm.setBookmark(head), + 'anchor': copyCursor(anchor), + 'head': copyCursor(head), + 'visualMode': vim.visualMode, + 'visualLine': vim.visualLine, + 'visualBlock': vim.visualBlock}; + } + function expandSelection(cm, start, end) { + var sel = cm.state.vim.sel; + var head = sel.head; + var anchor = sel.anchor; + var tmp; + if (cursorIsBefore(end, start)) { + tmp = end; + end = start; + start = tmp; + } + if (cursorIsBefore(head, anchor)) { + head = cursorMin(start, head); + anchor = cursorMax(anchor, end); + } else { + anchor = cursorMin(start, anchor); + head = cursorMax(head, end); + head = offsetCursor(head, 0, -1); + if (head.ch == -1 && head.line != cm.firstLine()) { + head = Pos(head.line - 1, lineLength(cm, head.line - 1)); + } + } + return [anchor, head]; + } + function updateCmSelection(cm, sel, mode) { + var vim = cm.state.vim; + sel = sel || vim.sel; + var mode = mode || + vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char'; + var cmSel = makeCmSelection(cm, sel, mode); + cm.setSelections(cmSel.ranges, cmSel.primary); + updateFakeCursor(cm); + } + function makeCmSelection(cm, sel, mode, exclusive) { + var head = copyCursor(sel.head); + var anchor = copyCursor(sel.anchor); + if (mode == 'char') { + var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; + var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; + head = offsetCursor(sel.head, 0, headOffset); + anchor = offsetCursor(sel.anchor, 0, anchorOffset); + return { + ranges: [{anchor: anchor, head: head}], + primary: 0 + }; + } else if (mode == 'line') { + if (!cursorIsBefore(sel.head, sel.anchor)) { + anchor.ch = 0; + + var lastLine = cm.lastLine(); + if (head.line > lastLine) { + head.line = lastLine; + } + head.ch = lineLength(cm, head.line); + } else { + head.ch = 0; + anchor.ch = lineLength(cm, anchor.line); + } + return { + ranges: [{anchor: anchor, head: head}], + primary: 0 + }; + } else if (mode == 'block') { + var top = Math.min(anchor.line, head.line), + left = Math.min(anchor.ch, head.ch), + bottom = Math.max(anchor.line, head.line), + right = Math.max(anchor.ch, head.ch) + 1; + var height = bottom - top + 1; + var primary = head.line == top ? 0 : height - 1; + var ranges = []; + for (var i = 0; i < height; i++) { + ranges.push({ + anchor: Pos(top + i, left), + head: Pos(top + i, right) + }); + } + return { + ranges: ranges, + primary: primary + }; + } + } + function getHead(cm) { + var cur = cm.getCursor('head'); + if (cm.getSelection().length == 1) { + cur = cursorMin(cur, cm.getCursor('anchor')); + } + return cur; + } + function exitVisualMode(cm, moveHead) { + var vim = cm.state.vim; + if (moveHead !== false) { + cm.setCursor(clipCursorToContent(cm, vim.sel.head)); + } + updateLastSelection(cm, vim); + vim.visualMode = false; + vim.visualLine = false; + vim.visualBlock = false; + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + if (vim.fakeCursor) { + vim.fakeCursor.clear(); + } + } + function clipToLine(cm, curStart, curEnd) { + var selection = cm.getRange(curStart, curEnd); + if (/\n\s*$/.test(selection)) { + var lines = selection.split('\n'); + lines.pop(); + var line; + for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) { + curEnd.line--; + curEnd.ch = 0; + } + if (line) { + curEnd.line--; + curEnd.ch = lineLength(cm, curEnd.line); + } else { + curEnd.ch = 0; + } + } + } + function expandSelectionToLine(_cm, curStart, curEnd) { + curStart.ch = 0; + curEnd.ch = 0; + curEnd.line++; + } + + function findFirstNonWhiteSpaceCharacter(text) { + if (!text) { + return 0; + } + var firstNonWS = text.search(/\S/); + return firstNonWS == -1 ? text.length : firstNonWS; + } + + function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { + var cur = getHead(cm); + var line = cm.getLine(cur.line); + var idx = cur.ch; + var textAfterIdx = line.substring(idx); + var firstMatchedChar; + if (noSymbol) { + firstMatchedChar = textAfterIdx.search(/\w/); + } else { + firstMatchedChar = textAfterIdx.search(/\S/); + } + if (firstMatchedChar == -1) { + return null; + } + idx += firstMatchedChar; + textAfterIdx = line.substring(idx); + var textBeforeIdx = line.substring(0, idx); + + var matchRegex; + if (bigWord) { + matchRegex = /^\S+/; + } else { + if ((/\w/).test(line.charAt(idx))) { + matchRegex = /^\w+/; + } else { + matchRegex = /^[^\w\s]+/; + } + } + + var wordAfterRegex = matchRegex.exec(textAfterIdx); + var wordStart = idx; + var wordEnd = idx + wordAfterRegex[0].length; + var revTextBeforeIdx = reverse(textBeforeIdx); + var wordBeforeRegex = matchRegex.exec(revTextBeforeIdx); + if (wordBeforeRegex) { + wordStart -= wordBeforeRegex[0].length; + } + + if (inclusive) { + var textAfterWordEnd = line.substring(wordEnd); + var whitespacesAfterWord = textAfterWordEnd.match(/^\s*/)[0].length; + if (whitespacesAfterWord > 0) { + wordEnd += whitespacesAfterWord; + } else { + var revTrim = revTextBeforeIdx.length - wordStart; + var textBeforeWordStart = revTextBeforeIdx.substring(revTrim); + var whitespacesBeforeWord = textBeforeWordStart.match(/^\s*/)[0].length; + wordStart -= whitespacesBeforeWord; + } + } + + return { start: Pos(cur.line, wordStart), + end: Pos(cur.line, wordEnd) }; + } + + function recordJumpPosition(cm, oldCur, newCur) { + if (!cursorEqual(oldCur, newCur)) { + vimGlobalState.jumpList.add(cm, oldCur, newCur); + } + } + + function recordLastCharacterSearch(increment, args) { + vimGlobalState.lastChararacterSearch.increment = increment; + vimGlobalState.lastChararacterSearch.forward = args.forward; + vimGlobalState.lastChararacterSearch.selectedCharacter = args.selectedCharacter; + } + + var symbolToMode = { + '(': 'bracket', ')': 'bracket', '{': 'bracket', '}': 'bracket', + '[': 'section', ']': 'section', + '*': 'comment', '/': 'comment', + 'm': 'method', 'M': 'method', + '#': 'preprocess' + }; + var findSymbolModes = { + bracket: { + isComplete: function(state) { + if (state.nextCh === state.symb) { + state.depth++; + if (state.depth >= 1)return true; + } else if (state.nextCh === state.reverseSymb) { + state.depth--; + } + return false; + } + }, + section: { + init: function(state) { + state.curMoveThrough = true; + state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}'; + }, + isComplete: function(state) { + return state.index === 0 && state.nextCh === state.symb; + } + }, + comment: { + isComplete: function(state) { + var found = state.lastCh === '*' && state.nextCh === '/'; + state.lastCh = state.nextCh; + return found; + } + }, + method: { + init: function(state) { + state.symb = (state.symb === 'm' ? '{' : '}'); + state.reverseSymb = state.symb === '{' ? '}' : '{'; + }, + isComplete: function(state) { + if (state.nextCh === state.symb)return true; + return false; + } + }, + preprocess: { + init: function(state) { + state.index = 0; + }, + isComplete: function(state) { + if (state.nextCh === '#') { + var token = state.lineText.match(/#(\w+)/)[1]; + if (token === 'endif') { + if (state.forward && state.depth === 0) { + return true; + } + state.depth++; + } else if (token === 'if') { + if (!state.forward && state.depth === 0) { + return true; + } + state.depth--; + } + if (token === 'else' && state.depth === 0)return true; + } + return false; + } + } + }; + function findSymbol(cm, repeat, forward, symb) { + var cur = copyCursor(cm.getCursor()); + var increment = forward ? 1 : -1; + var endLine = forward ? cm.lineCount() : -1; + var curCh = cur.ch; + var line = cur.line; + var lineText = cm.getLine(line); + var state = { + lineText: lineText, + nextCh: lineText.charAt(curCh), + lastCh: null, + index: curCh, + symb: symb, + reverseSymb: (forward ? { ')': '(', '}': '{' } : { '(': ')', '{': '}' })[symb], + forward: forward, + depth: 0, + curMoveThrough: false + }; + var mode = symbolToMode[symb]; + if (!mode)return cur; + var init = findSymbolModes[mode].init; + var isComplete = findSymbolModes[mode].isComplete; + if (init) { init(state); } + while (line !== endLine && repeat) { + state.index += increment; + state.nextCh = state.lineText.charAt(state.index); + if (!state.nextCh) { + line += increment; + state.lineText = cm.getLine(line) || ''; + if (increment > 0) { + state.index = 0; + } else { + var lineLen = state.lineText.length; + state.index = (lineLen > 0) ? (lineLen-1) : 0; + } + state.nextCh = state.lineText.charAt(state.index); + } + if (isComplete(state)) { + cur.line = line; + cur.ch = state.index; + repeat--; + } + } + if (state.nextCh || state.curMoveThrough) { + return Pos(line, state.index); + } + return cur; + } + function findWord(cm, cur, forward, bigWord, emptyLineIsWord) { + var lineNum = cur.line; + var pos = cur.ch; + var line = cm.getLine(lineNum); + var dir = forward ? 1 : -1; + var regexps = bigWord ? bigWordRegexp : wordRegexp; + + if (emptyLineIsWord && line == '') { + lineNum += dir; + line = cm.getLine(lineNum); + if (!isLine(cm, lineNum)) { + return null; + } + pos = (forward) ? 0 : line.length; + } + + while (true) { + if (emptyLineIsWord && line == '') { + return { from: 0, to: 0, line: lineNum }; + } + var stop = (dir > 0) ? line.length : -1; + var wordStart = stop, wordEnd = stop; + while (pos != stop) { + var foundWord = false; + for (var i = 0; i < regexps.length && !foundWord; ++i) { + if (regexps[i].test(line.charAt(pos))) { + wordStart = pos; + while (pos != stop && regexps[i].test(line.charAt(pos))) { + pos += dir; + } + wordEnd = pos; + foundWord = wordStart != wordEnd; + if (wordStart == cur.ch && lineNum == cur.line && + wordEnd == wordStart + dir) { + continue; + } else { + return { + from: Math.min(wordStart, wordEnd + 1), + to: Math.max(wordStart, wordEnd), + line: lineNum }; + } + } + } + if (!foundWord) { + pos += dir; + } + } + lineNum += dir; + if (!isLine(cm, lineNum)) { + return null; + } + line = cm.getLine(lineNum); + pos = (dir > 0) ? 0 : line.length; + } + throw new Error('The impossible happened.'); + } + function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) { + var curStart = copyCursor(cur); + var words = []; + if (forward && !wordEnd || !forward && wordEnd) { + repeat++; + } + var emptyLineIsWord = !(forward && wordEnd); + for (var i = 0; i < repeat; i++) { + var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord); + if (!word) { + var eodCh = lineLength(cm, cm.lastLine()); + words.push(forward + ? {line: cm.lastLine(), from: eodCh, to: eodCh} + : {line: 0, from: 0, to: 0}); + break; + } + words.push(word); + cur = Pos(word.line, forward ? (word.to - 1) : word.from); + } + var shortCircuit = words.length != repeat; + var firstWord = words[0]; + var lastWord = words.pop(); + if (forward && !wordEnd) { + if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) { + lastWord = words.pop(); + } + return Pos(lastWord.line, lastWord.from); + } else if (forward && wordEnd) { + return Pos(lastWord.line, lastWord.to - 1); + } else if (!forward && wordEnd) { + if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) { + lastWord = words.pop(); + } + return Pos(lastWord.line, lastWord.to); + } else { + return Pos(lastWord.line, lastWord.from); + } + } + + function moveToCharacter(cm, repeat, forward, character) { + var cur = cm.getCursor(); + var start = cur.ch; + var idx; + for (var i = 0; i < repeat; i ++) { + var line = cm.getLine(cur.line); + idx = charIdxInLine(start, line, character, forward, true); + if (idx == -1) { + return null; + } + start = idx; + } + return Pos(cm.getCursor().line, idx); + } + + function moveToColumn(cm, repeat) { + var line = cm.getCursor().line; + return clipCursorToContent(cm, Pos(line, repeat - 1)); + } + + function updateMark(cm, vim, markName, pos) { + if (!inArray(markName, validMarks)) { + return; + } + if (vim.marks[markName]) { + vim.marks[markName].clear(); + } + vim.marks[markName] = cm.setBookmark(pos); + } + + function charIdxInLine(start, line, character, forward, includeChar) { + var idx; + if (forward) { + idx = line.indexOf(character, start + 1); + if (idx != -1 && !includeChar) { + idx -= 1; + } + } else { + idx = line.lastIndexOf(character, start - 1); + if (idx != -1 && !includeChar) { + idx += 1; + } + } + return idx; + } + + function findParagraph(cm, head, repeat, dir, inclusive) { + var line = head.line; + var min = cm.firstLine(); + var max = cm.lastLine(); + var start, end, i = line; + function isEmpty(i) { return !/\S/.test(cm.getLine(i)); } + function isBoundary(i, dir, any) { + if (any) { return isEmpty(i) != isEmpty(i + dir); } + return !isEmpty(i) && isEmpty(i + dir); + } + if (dir) { + while (min <= i && i <= max && repeat > 0) { + if (isBoundary(i, dir)) { repeat--; } + i += dir; + } + return new Pos(i, 0); + } + + var vim = cm.state.vim; + if (vim.visualLine && isBoundary(line, 1, true)) { + var anchor = vim.sel.anchor; + if (isBoundary(anchor.line, -1, true)) { + if (!inclusive || anchor.line != line) { + line += 1; + } + } + } + var startState = isEmpty(line); + for (i = line; i <= max && repeat; i++) { + if (isBoundary(i, 1, true)) { + if (!inclusive || isEmpty(i) != startState) { + repeat--; + } + } + } + end = new Pos(i, 0); + if (i > max && !startState) { startState = true; } + else { inclusive = false; } + for (i = line; i > min; i--) { + if (!inclusive || isEmpty(i) == startState || i == line) { + if (isBoundary(i, -1, true)) { break; } + } + } + start = new Pos(i, 0); + return { start: start, end: end }; + } + function selectCompanionObject(cm, head, symb, inclusive) { + var cur = head, start, end; + + var bracketRegexp = ({ + '(': /[()]/, ')': /[()]/, + '[': /[[\]]/, ']': /[[\]]/, + '{': /[{}]/, '}': /[{}]/})[symb]; + var openSym = ({ + '(': '(', ')': '(', + '[': '[', ']': '[', + '{': '{', '}': '{'})[symb]; + var curChar = cm.getLine(cur.line).charAt(cur.ch); + var offset = curChar === openSym ? 1 : 0; + + start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp}); + end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp}); + + if (!start || !end) { + return { start: cur, end: cur }; + } + + start = start.pos; + end = end.pos; + + if ((start.line == end.line && start.ch > end.ch) + || (start.line > end.line)) { + var tmp = start; + start = end; + end = tmp; + } + + if (inclusive) { + end.ch += 1; + } else { + start.ch += 1; + } + + return { start: start, end: end }; + } + function findBeginningAndEnd(cm, head, symb, inclusive) { + var cur = copyCursor(head); + var line = cm.getLine(cur.line); + var chars = line.split(''); + var start, end, i, len; + var firstIndex = chars.indexOf(symb); + if (cur.ch < firstIndex) { + cur.ch = firstIndex; + } + else if (firstIndex < cur.ch && chars[cur.ch] == symb) { + end = cur.ch; // assign end to the current cursor + --cur.ch; // make sure to look backwards + } + if (chars[cur.ch] == symb && !end) { + start = cur.ch + 1; // assign start to ahead of the cursor + } else { + for (i = cur.ch; i > -1 && !start; i--) { + if (chars[i] == symb) { + start = i + 1; + } + } + } + if (start && !end) { + for (i = start, len = chars.length; i < len && !end; i++) { + if (chars[i] == symb) { + end = i; + } + } + } + if (!start || !end) { + return { start: cur, end: cur }; + } + if (inclusive) { + --start; ++end; + } + + return { + start: Pos(cur.line, start), + end: Pos(cur.line, end) + }; + } + defineOption('pcre', true, 'boolean'); + function SearchState() {} + SearchState.prototype = { + getQuery: function() { + return vimGlobalState.query; + }, + setQuery: function(query) { + vimGlobalState.query = query; + }, + getOverlay: function() { + return this.searchOverlay; + }, + setOverlay: function(overlay) { + this.searchOverlay = overlay; + }, + isReversed: function() { + return vimGlobalState.isReversed; + }, + setReversed: function(reversed) { + vimGlobalState.isReversed = reversed; + } + }; + function getSearchState(cm) { + var vim = cm.state.vim; + return vim.searchState_ || (vim.searchState_ = new SearchState()); + } + function dialog(cm, template, shortText, onClose, options) { + if (cm.openDialog) { + cm.openDialog(template, onClose, { bottom: true, value: options.value, + onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp }); + } + else { + onClose(prompt(shortText, '')); + } + } + function splitBySlash(argString) { + var slashes = findUnescapedSlashes(argString) || []; + if (!slashes.length) return []; + var tokens = []; + if (slashes[0] !== 0) return; + for (var i = 0; i < slashes.length; i++) { + if (typeof slashes[i] == 'number') + tokens.push(argString.substring(slashes[i] + 1, slashes[i+1])); + } + return tokens; + } + + function findUnescapedSlashes(str) { + var escapeNextChar = false; + var slashes = []; + for (var i = 0; i < str.length; i++) { + var c = str.charAt(i); + if (!escapeNextChar && c == '/') { + slashes.push(i); + } + escapeNextChar = !escapeNextChar && (c == '\\'); + } + return slashes; + } + function translateRegex(str) { + var specials = '|(){'; + var unescape = '}'; + var escapeNextChar = false; + var out = []; + for (var i = -1; i < str.length; i++) { + var c = str.charAt(i) || ''; + var n = str.charAt(i+1) || ''; + var specialComesNext = (n && specials.indexOf(n) != -1); + if (escapeNextChar) { + if (c !== '\\' || !specialComesNext) { + out.push(c); + } + escapeNextChar = false; + } else { + if (c === '\\') { + escapeNextChar = true; + if (n && unescape.indexOf(n) != -1) { + specialComesNext = true; + } + if (!specialComesNext || n === '\\') { + out.push(c); + } + } else { + out.push(c); + if (specialComesNext && n !== '\\') { + out.push('\\'); + } + } + } + } + return out.join(''); + } + function translateRegexReplace(str) { + var escapeNextChar = false; + var out = []; + for (var i = -1; i < str.length; i++) { + var c = str.charAt(i) || ''; + var n = str.charAt(i+1) || ''; + if (escapeNextChar) { + out.push(c); + escapeNextChar = false; + } else { + if (c === '\\') { + escapeNextChar = true; + if ((isNumber(n) || n === '$')) { + out.push('$'); + } else if (n !== '/' && n !== '\\') { + out.push('\\'); + } + } else { + if (c === '$') { + out.push('$'); + } + out.push(c); + if (n === '/') { + out.push('\\'); + } + } + } + } + return out.join(''); + } + function unescapeRegexReplace(str) { + var stream = new CodeMirror.StringStream(str); + var output = []; + while (!stream.eol()) { + while (stream.peek() && stream.peek() != '\\') { + output.push(stream.next()); + } + if (stream.match('\\/', true)) { + output.push('/'); + } else if (stream.match('\\\\', true)) { + output.push('\\'); + } else { + output.push(stream.next()); + } + } + return output.join(''); + } + function parseQuery(query, ignoreCase, smartCase) { + var lastSearchRegister = vimGlobalState.registerController.getRegister('/'); + lastSearchRegister.setText(query); + if (query instanceof RegExp) { return query; } + var slashes = findUnescapedSlashes(query); + var regexPart; + var forceIgnoreCase; + if (!slashes.length) { + regexPart = query; + } else { + regexPart = query.substring(0, slashes[0]); + var flagsPart = query.substring(slashes[0]); + forceIgnoreCase = (flagsPart.indexOf('i') != -1); + } + if (!regexPart) { + return null; + } + if (!getOption('pcre')) { + regexPart = translateRegex(regexPart); + } + if (smartCase) { + ignoreCase = (/^[^A-Z]*$/).test(regexPart); + } + var regexp = new RegExp(regexPart, + (ignoreCase || forceIgnoreCase) ? 'i' : undefined); + return regexp; + } + function showConfirm(cm, text) { + if (cm.openNotification) { + cm.openNotification('' + text + '', + {bottom: true, duration: 5000}); + } else { + alert(text); + } + } + function makePrompt(prefix, desc) { + var raw = ''; + if (prefix) { + raw += '' + prefix + ''; + } + raw += ' ' + + ''; + if (desc) { + raw += ''; + raw += desc; + raw += ''; + } + return raw; + } + var searchPromptDesc = '(Javascript regexp)'; + function showPrompt(cm, options) { + var shortText = (options.prefix || '') + ' ' + (options.desc || ''); + var prompt = makePrompt(options.prefix, options.desc); + dialog(cm, prompt, shortText, options.onClose, options); + } + function regexEqual(r1, r2) { + if (r1 instanceof RegExp && r2 instanceof RegExp) { + var props = ['global', 'multiline', 'ignoreCase', 'source']; + for (var i = 0; i < props.length; i++) { + var prop = props[i]; + if (r1[prop] !== r2[prop]) { + return false; + } + } + return true; + } + return false; + } + function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) { + if (!rawQuery) { + return; + } + var state = getSearchState(cm); + var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase); + if (!query) { + return; + } + highlightSearchMatches(cm, query); + if (regexEqual(query, state.getQuery())) { + return query; + } + state.setQuery(query); + return query; + } + function searchOverlay(query) { + if (query.source.charAt(0) == '^') { + var matchSol = true; + } + return { + token: function(stream) { + if (matchSol && !stream.sol()) { + stream.skipToEnd(); + return; + } + var match = stream.match(query, false); + if (match) { + if (match[0].length == 0) { + stream.next(); + return 'searching'; + } + if (!stream.sol()) { + stream.backUp(1); + if (!query.exec(stream.next() + match[0])) { + stream.next(); + return null; + } + } + stream.match(query); + return 'searching'; + } + while (!stream.eol()) { + stream.next(); + if (stream.match(query, false)) break; + } + }, + query: query + }; + } + function highlightSearchMatches(cm, query) { + var overlay = getSearchState(cm).getOverlay(); + if (!overlay || query != overlay.query) { + if (overlay) { + cm.removeOverlay(overlay); + } + overlay = searchOverlay(query); + cm.addOverlay(overlay); + getSearchState(cm).setOverlay(overlay); + } + } + function findNext(cm, prev, query, repeat) { + if (repeat === undefined) { repeat = 1; } + return cm.operation(function() { + var pos = cm.getCursor(); + var cursor = cm.getSearchCursor(query, pos); + for (var i = 0; i < repeat; i++) { + var found = cursor.find(prev); + if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); } + if (!found) { + cursor = cm.getSearchCursor(query, + (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) ); + if (!cursor.find(prev)) { + return; + } + } + } + return cursor.from(); + }); + } + function clearSearchHighlight(cm) { + cm.removeOverlay(getSearchState(cm).getOverlay()); + getSearchState(cm).setOverlay(null); + } + function isInRange(pos, start, end) { + if (typeof pos != 'number') { + pos = pos.line; + } + if (start instanceof Array) { + return inArray(pos, start); + } else { + if (end) { + return (pos >= start && pos <= end); + } else { + return pos == start; + } + } + } + function getUserVisibleLines(cm) { + var renderer = cm.ace.renderer; + return { + top: renderer.getFirstFullyVisibleRow(), + bottom: renderer.getLastFullyVisibleRow() + } + } + var defaultExCommandMap = [ + { name: 'map' }, + { name: 'imap', shortName: 'im' }, + { name: 'nmap', shortName: 'nm' }, + { name: 'vmap', shortName: 'vm' }, + { name: 'unmap' }, + { name: 'write', shortName: 'w' }, + { name: 'undo', shortName: 'u' }, + { name: 'redo', shortName: 'red' }, + { name: 'set', shortName: 'set' }, + { name: 'sort', shortName: 'sor' }, + { name: 'substitute', shortName: 's', possiblyAsync: true }, + { name: 'nohlsearch', shortName: 'noh' }, + { name: 'delmarks', shortName: 'delm' }, + { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, + { name: 'global', shortName: 'g' } + ]; + var ExCommandDispatcher = function() { + this.buildCommandMap_(); + }; + ExCommandDispatcher.prototype = { + processCommand: function(cm, input, opt_params) { + var vim = cm.state.vim; + var commandHistoryRegister = vimGlobalState.registerController.getRegister(':'); + var previousCommand = commandHistoryRegister.toString(); + if (vim.visualMode) { + exitVisualMode(cm); + } + var inputStream = new CodeMirror.StringStream(input); + commandHistoryRegister.setText(input); + var params = opt_params || {}; + params.input = input; + try { + this.parseInput_(cm, inputStream, params); + } catch(e) { + showConfirm(cm, e); + throw e; + } + var command; + var commandName; + if (!params.commandName) { + if (params.line !== undefined) { + commandName = 'move'; + } + } else { + command = this.matchCommand_(params.commandName); + if (command) { + commandName = command.name; + if (command.excludeFromCommandHistory) { + commandHistoryRegister.setText(previousCommand); + } + this.parseCommandArgs_(inputStream, params, command); + if (command.type == 'exToKey') { + for (var i = 0; i < command.toKeys.length; i++) { + CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping'); + } + return; + } else if (command.type == 'exToEx') { + this.processCommand(cm, command.toInput); + return; + } + } + } + if (!commandName) { + showConfirm(cm, 'Not an editor command ":' + input + '"'); + return; + } + try { + exCommands[commandName](cm, params); + if ((!command || !command.possiblyAsync) && params.callback) { + params.callback(); + } + } catch(e) { + showConfirm(cm, e); + throw e; + } + }, + parseInput_: function(cm, inputStream, result) { + inputStream.eatWhile(':'); + if (inputStream.eat('%')) { + result.line = cm.firstLine(); + result.lineEnd = cm.lastLine(); + } else { + result.line = this.parseLineSpec_(cm, inputStream); + if (result.line !== undefined && inputStream.eat(',')) { + result.lineEnd = this.parseLineSpec_(cm, inputStream); + } + } + var commandMatch = inputStream.match(/^(\w+)/); + if (commandMatch) { + result.commandName = commandMatch[1]; + } else { + result.commandName = inputStream.match(/.*/)[0]; + } + + return result; + }, + parseLineSpec_: function(cm, inputStream) { + var numberMatch = inputStream.match(/^(\d+)/); + if (numberMatch) { + return parseInt(numberMatch[1], 10) - 1; + } + switch (inputStream.next()) { + case '.': + return cm.getCursor().line; + case '$': + return cm.lastLine(); + case '\'': + var mark = cm.state.vim.marks[inputStream.next()]; + if (mark && mark.find()) { + return mark.find().line; + } + throw new Error('Mark not set'); + default: + inputStream.backUp(1); + return undefined; + } + }, + parseCommandArgs_: function(inputStream, params, command) { + if (inputStream.eol()) { + return; + } + params.argString = inputStream.match(/.*/)[0]; + var delim = command.argDelimiter || /\s+/; + var args = trim(params.argString).split(delim); + if (args.length && args[0]) { + params.args = args; + } + }, + matchCommand_: function(commandName) { + for (var i = commandName.length; i > 0; i--) { + var prefix = commandName.substring(0, i); + if (this.commandMap_[prefix]) { + var command = this.commandMap_[prefix]; + if (command.name.indexOf(commandName) === 0) { + return command; + } + } + } + return null; + }, + buildCommandMap_: function() { + this.commandMap_ = {}; + for (var i = 0; i < defaultExCommandMap.length; i++) { + var command = defaultExCommandMap[i]; + var key = command.shortName || command.name; + this.commandMap_[key] = command; + } + }, + map: function(lhs, rhs, ctx) { + if (lhs != ':' && lhs.charAt(0) == ':') { + if (ctx) { throw Error('Mode not supported for ex mappings'); } + var commandName = lhs.substring(1); + if (rhs != ':' && rhs.charAt(0) == ':') { + this.commandMap_[commandName] = { + name: commandName, + type: 'exToEx', + toInput: rhs.substring(1), + user: true + }; + } else { + this.commandMap_[commandName] = { + name: commandName, + type: 'exToKey', + toKeys: rhs, + user: true + }; + } + } else { + if (rhs != ':' && rhs.charAt(0) == ':') { + var mapping = { + keys: lhs, + type: 'keyToEx', + exArgs: { input: rhs.substring(1) }, + user: true}; + if (ctx) { mapping.context = ctx; } + defaultKeymap.unshift(mapping); + } else { + var mapping = { + keys: lhs, + type: 'keyToKey', + toKeys: rhs, + user: true + }; + if (ctx) { mapping.context = ctx; } + defaultKeymap.unshift(mapping); + } + } + }, + unmap: function(lhs, ctx) { + if (lhs != ':' && lhs.charAt(0) == ':') { + if (ctx) { throw Error('Mode not supported for ex mappings'); } + var commandName = lhs.substring(1); + if (this.commandMap_[commandName] && this.commandMap_[commandName].user) { + delete this.commandMap_[commandName]; + return; + } + } else { + var keys = lhs; + for (var i = 0; i < defaultKeymap.length; i++) { + if (keys == defaultKeymap[i].keys + && defaultKeymap[i].context === ctx + && defaultKeymap[i].user) { + defaultKeymap.splice(i, 1); + return; + } + } + } + throw Error('No such mapping.'); + } + }; + + var exCommands = { + map: function(cm, params, ctx) { + var mapArgs = params.args; + if (!mapArgs || mapArgs.length < 2) { + if (cm) { + showConfirm(cm, 'Invalid mapping: ' + params.input); + } + return; + } + exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); + }, + imap: function(cm, params) { this.map(cm, params, 'insert'); }, + nmap: function(cm, params) { this.map(cm, params, 'normal'); }, + vmap: function(cm, params) { this.map(cm, params, 'visual'); }, + unmap: function(cm, params, ctx) { + var mapArgs = params.args; + if (!mapArgs || mapArgs.length < 1) { + if (cm) { + showConfirm(cm, 'No such mapping: ' + params.input); + } + return; + } + exCommandDispatcher.unmap(mapArgs[0], ctx); + }, + move: function(cm, params) { + commandDispatcher.processCommand(cm, cm.state.vim, { + type: 'motion', + motion: 'moveToLineOrEdgeOfDocument', + motionArgs: { forward: false, explicitRepeat: true, + linewise: true }, + repeatOverride: params.line+1}); + }, + set: function(cm, params) { + var setArgs = params.args; + if (!setArgs || setArgs.length < 1) { + if (cm) { + showConfirm(cm, 'Invalid mapping: ' + params.input); + } + return; + } + var expr = setArgs[0].split('='); + var optionName = expr[0]; + var value = expr[1]; + var forceGet = false; + + if (optionName.charAt(optionName.length - 1) == '?') { + if (value) { throw Error('Trailing characters: ' + params.argString); } + optionName = optionName.substring(0, optionName.length - 1); + forceGet = true; + } + if (value === undefined && optionName.substring(0, 2) == 'no') { + optionName = optionName.substring(2); + value = false; + } + var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean'; + if (optionIsBoolean && value == undefined) { + value = true; + } + if (!optionIsBoolean && !value || forceGet) { + var oldValue = getOption(optionName); + if (oldValue === true || oldValue === false) { + showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName); + } else { + showConfirm(cm, ' ' + optionName + '=' + oldValue); + } + } else { + setOption(optionName, value, cm); + } + }, + registers: function(cm,params) { + var regArgs = params.args; + var registers = vimGlobalState.registerController.registers; + var regInfo = '----------Registers----------

'; + if (!regArgs) { + for (var registerName in registers) { + var text = registers[registerName].toString(); + if (text.length) { + regInfo += '"' + registerName + ' ' + text + '
'; + } + } + } else { + var registerName; + regArgs = regArgs.join(''); + for (var i = 0; i < regArgs.length; i++) { + registerName = regArgs.charAt(i); + if (!vimGlobalState.registerController.isValidRegister(registerName)) { + continue; + } + var register = registers[registerName] || new Register(); + regInfo += '"' + registerName + ' ' + register.toString() + '
'; + } + } + showConfirm(cm, regInfo); + }, + sort: function(cm, params) { + var reverse, ignoreCase, unique, number; + function parseArgs() { + if (params.argString) { + var args = new CodeMirror.StringStream(params.argString); + if (args.eat('!')) { reverse = true; } + if (args.eol()) { return; } + if (!args.eatSpace()) { return 'Invalid arguments'; } + var opts = args.match(/[a-z]+/); + if (opts) { + opts = opts[0]; + ignoreCase = opts.indexOf('i') != -1; + unique = opts.indexOf('u') != -1; + var decimal = opts.indexOf('d') != -1 && 1; + var hex = opts.indexOf('x') != -1 && 1; + var octal = opts.indexOf('o') != -1 && 1; + if (decimal + hex + octal > 1) { return 'Invalid arguments'; } + number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; + } + if (args.eatSpace() && args.match(/\/.*\//)) { 'patterns not supported'; } + } + } + var err = parseArgs(); + if (err) { + showConfirm(cm, err + ': ' + params.argString); + return; + } + var lineStart = params.line || cm.firstLine(); + var lineEnd = params.lineEnd || params.line || cm.lastLine(); + if (lineStart == lineEnd) { return; } + var curStart = Pos(lineStart, 0); + var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)); + var text = cm.getRange(curStart, curEnd).split('\n'); + var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ : + (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i : + (number == 'octal') ? /([0-7]+)/ : null; + var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null; + var numPart = [], textPart = []; + if (number) { + for (var i = 0; i < text.length; i++) { + if (numberRegex.exec(text[i])) { + numPart.push(text[i]); + } else { + textPart.push(text[i]); + } + } + } else { + textPart = text; + } + function compareFn(a, b) { + if (reverse) { var tmp; tmp = a; a = b; b = tmp; } + if (ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); } + var anum = number && numberRegex.exec(a); + var bnum = number && numberRegex.exec(b); + if (!anum) { return a < b ? -1 : 1; } + anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix); + bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix); + return anum - bnum; + } + numPart.sort(compareFn); + textPart.sort(compareFn); + text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart); + if (unique) { // Remove duplicate lines + var textOld = text; + var lastLine; + text = []; + for (var i = 0; i < textOld.length; i++) { + if (textOld[i] != lastLine) { + text.push(textOld[i]); + } + lastLine = textOld[i]; + } + } + cm.replaceRange(text.join('\n'), curStart, curEnd); + }, + global: function(cm, params) { + var argString = params.argString; + if (!argString) { + showConfirm(cm, 'Regular Expression missing from global'); + return; + } + var lineStart = (params.line !== undefined) ? params.line : cm.firstLine(); + var lineEnd = params.lineEnd || params.line || cm.lastLine(); + var tokens = splitBySlash(argString); + var regexPart = argString, cmd; + if (tokens.length) { + regexPart = tokens[0]; + cmd = tokens.slice(1, tokens.length).join('/'); + } + if (regexPart) { + try { + updateSearchQuery(cm, regexPart, true /** ignoreCase */, + true /** smartCase */); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + regexPart); + return; + } + } + var query = getSearchState(cm).getQuery(); + var matchedLines = [], content = ''; + for (var i = lineStart; i <= lineEnd; i++) { + var matched = query.test(cm.getLine(i)); + if (matched) { + matchedLines.push(i+1); + content+= cm.getLine(i) + '
'; + } + } + if (!cmd) { + showConfirm(cm, content); + return; + } + var index = 0; + var nextCommand = function() { + if (index < matchedLines.length) { + var command = matchedLines[index] + cmd; + exCommandDispatcher.processCommand(cm, command, { + callback: nextCommand + }); + } + index++; + }; + nextCommand(); + }, + substitute: function(cm, params) { + if (!cm.getSearchCursor) { + throw new Error('Search feature not available. Requires searchcursor.js or ' + + 'any other getSearchCursor implementation.'); + } + var argString = params.argString; + var tokens = argString ? splitBySlash(argString) : []; + var regexPart, replacePart = '', trailing, flagsPart, count; + var confirm = false; // Whether to confirm each replace. + var global = false; // True to replace all instances on a line, false to replace only 1. + if (tokens.length) { + regexPart = tokens[0]; + replacePart = tokens[1]; + if (replacePart !== undefined) { + if (getOption('pcre')) { + replacePart = unescapeRegexReplace(replacePart); + } else { + replacePart = translateRegexReplace(replacePart); + } + vimGlobalState.lastSubstituteReplacePart = replacePart; + } + trailing = tokens[2] ? tokens[2].split(' ') : []; + } else { + if (argString && argString.length) { + showConfirm(cm, 'Substitutions should be of the form ' + + ':s/pattern/replace/'); + return; + } + } + if (trailing) { + flagsPart = trailing[0]; + count = parseInt(trailing[1]); + if (flagsPart) { + if (flagsPart.indexOf('c') != -1) { + confirm = true; + flagsPart.replace('c', ''); + } + if (flagsPart.indexOf('g') != -1) { + global = true; + flagsPart.replace('g', ''); + } + regexPart = regexPart + '/' + flagsPart; + } + } + if (regexPart) { + try { + updateSearchQuery(cm, regexPart, true /** ignoreCase */, + true /** smartCase */); + } catch (e) { + showConfirm(cm, 'Invalid regex: ' + regexPart); + return; + } + } + replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart; + if (replacePart === undefined) { + showConfirm(cm, 'No previous substitute regular expression'); + return; + } + var state = getSearchState(cm); + var query = state.getQuery(); + var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line; + var lineEnd = params.lineEnd || lineStart; + if (count) { + lineStart = lineEnd; + lineEnd = lineStart + count - 1; + } + var startPos = clipCursorToContent(cm, Pos(lineStart, 0)); + var cursor = cm.getSearchCursor(query, startPos); + doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback); + }, + redo: CodeMirror.commands.redo, + undo: CodeMirror.commands.undo, + write: function(cm) { + if (CodeMirror.commands.save) { + CodeMirror.commands.save(cm); + } else { + cm.save(); + } + }, + nohlsearch: function(cm) { + clearSearchHighlight(cm); + }, + delmarks: function(cm, params) { + if (!params.argString || !trim(params.argString)) { + showConfirm(cm, 'Argument required'); + return; + } + + var state = cm.state.vim; + var stream = new CodeMirror.StringStream(trim(params.argString)); + while (!stream.eol()) { + stream.eatSpace(); + var count = stream.pos; + + if (!stream.match(/[a-zA-Z]/, false)) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + + var sym = stream.next(); + if (stream.match('-', true)) { + if (!stream.match(/[a-zA-Z]/, false)) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + + var startMark = sym; + var finishMark = stream.next(); + if (isLowerCase(startMark) && isLowerCase(finishMark) || + isUpperCase(startMark) && isUpperCase(finishMark)) { + var start = startMark.charCodeAt(0); + var finish = finishMark.charCodeAt(0); + if (start >= finish) { + showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); + return; + } + for (var j = 0; j <= finish - start; j++) { + var mark = String.fromCharCode(start + j); + delete state.marks[mark]; + } + } else { + showConfirm(cm, 'Invalid argument: ' + startMark + '-'); + return; + } + } else { + delete state.marks[sym]; + } + } + } + }; + + var exCommandDispatcher = new ExCommandDispatcher(); + function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query, + replaceWith, callback) { + cm.state.vim.exMode = true; + var done = false; + var lastPos = searchCursor.from(); + function replaceAll() { + cm.operation(function() { + while (!done) { + replace(); + next(); + } + stop(); + }); + } + function replace() { + var text = cm.getRange(searchCursor.from(), searchCursor.to()); + var newText = text.replace(query, replaceWith); + searchCursor.replace(newText); + } + function next() { + var found; + while(found = searchCursor.findNext() && + isInRange(searchCursor.from(), lineStart, lineEnd)) { + if (!global && lastPos && searchCursor.from().line == lastPos.line) { + continue; + } + cm.scrollIntoView(searchCursor.from(), 30); + cm.setSelection(searchCursor.from(), searchCursor.to()); + lastPos = searchCursor.from(); + done = false; + return; + } + done = true; + } + function stop(close) { + if (close) { close(); } + cm.focus(); + if (lastPos) { + cm.setCursor(lastPos); + var vim = cm.state.vim; + vim.exMode = false; + vim.lastHPos = vim.lastHSPos = lastPos.ch; + } + if (callback) { callback(); } + } + function onPromptKeyDown(e, _value, close) { + CodeMirror.e_stop(e); + var keyName = CodeMirror.keyName(e); + switch (keyName) { + case 'Y': + replace(); next(); break; + case 'N': + next(); break; + case 'A': + var savedCallback = callback; + callback = undefined; + cm.operation(replaceAll); + callback = savedCallback; + break; + case 'L': + replace(); + case 'Q': + case 'Esc': + case 'Ctrl-C': + case 'Ctrl-[': + stop(close); + break; + } + if (done) { stop(close); } + return true; + } + next(); + if (done) { + showConfirm(cm, 'No matches for ' + query.source); + return; + } + if (!confirm) { + replaceAll(); + if (callback) { callback(); }; + return; + } + showPrompt(cm, { + prefix: 'replace with ' + replaceWith + ' (y/n/a/q/l)', + onKeyDown: onPromptKeyDown + }); + } + + CodeMirror.keyMap.vim = { + attach: attachVimMap, + detach: detachVimMap, + call: cmKey + }; + + function exitInsertMode(cm) { + var vim = cm.state.vim; + var macroModeState = vimGlobalState.macroModeState; + var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.'); + var isPlaying = macroModeState.isPlaying; + var lastChange = macroModeState.lastInsertModeChanges; + var text = []; + if (!isPlaying) { + var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1; + var changes = lastChange.changes; + var text = []; + var i = 0; + while (i < changes.length) { + text.push(changes[i]); + if (changes[i] instanceof InsertModeKey) { + i++; + } else { + i+= selLength; + } + } + lastChange.changes = text; + cm.off('change', onChange); + CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); + } + if (!isPlaying && vim.insertModeRepeat > 1) { + repeatLastEdit(cm, vim, vim.insertModeRepeat - 1, + true /** repeatForInsert */); + vim.lastEditInputState.repeatOverride = vim.insertModeRepeat; + } + delete vim.insertModeRepeat; + vim.insertMode = false; + cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1); + cm.setOption('keyMap', 'vim'); + cm.setOption('disableInput', true); + cm.toggleOverwrite(false); // exit replace mode if we were in it. + insertModeChangeRegister.setText(lastChange.changes.join('')); + CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); + if (macroModeState.isRecording) { + logInsertModeChange(macroModeState); + } + } + defineOption('insertModeEscKeysTimeout', 200, 'number'); + + CodeMirror.keyMap['vim-insert'] = { + 'Ctrl-N': 'autocomplete', + 'Ctrl-P': 'autocomplete', + 'Enter': function(cm) { + var fn = CodeMirror.commands.newlineAndIndentContinueComment || + CodeMirror.commands.newlineAndIndent; + fn(cm); + }, + fallthrough: ['default'], + attach: attachVimMap, + detach: detachVimMap, + call: cmKey + }; + + CodeMirror.keyMap['vim-replace'] = { + 'Backspace': 'goCharLeft', + fallthrough: ['vim-insert'], + attach: attachVimMap, + detach: detachVimMap, + call: cmKey + }; + + function executeMacroRegister(cm, vim, macroModeState, registerName) { + var register = vimGlobalState.registerController.getRegister(registerName); + var keyBuffer = register.keyBuffer; + var imc = 0; + macroModeState.isPlaying = true; + macroModeState.replaySearchQueries = register.searchQueries.slice(0); + for (var i = 0; i < keyBuffer.length; i++) { + var text = keyBuffer[i]; + var match, key; + while (text) { + match = (/<\w+-.+?>|<\w+>|./).exec(text); + key = match[0]; + text = text.substring(match.index + key.length); + CodeMirror.Vim.handleKey(cm, key, 'macro'); + if (vim.insertMode) { + var changes = register.insertModeChanges[imc++].changes; + vimGlobalState.macroModeState.lastInsertModeChanges.changes = + changes; + repeatInsertModeChanges(cm, changes, 1); + exitInsertMode(cm); + } + } + }; + macroModeState.isPlaying = false; + } + + function logKey(macroModeState, key) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.pushText(key); + } + } + + function logInsertModeChange(macroModeState) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.pushInsertModeChanges(macroModeState.lastInsertModeChanges); + } + } + + function logSearchQuery(macroModeState, query) { + if (macroModeState.isPlaying) { return; } + var registerName = macroModeState.latestRegister; + var register = vimGlobalState.registerController.getRegister(registerName); + if (register) { + register.pushSearchQuery(query); + } + } + function onChange(_cm, changeObj) { + var macroModeState = vimGlobalState.macroModeState; + var lastChange = macroModeState.lastInsertModeChanges; + if (!macroModeState.isPlaying) { + while(changeObj) { + lastChange.expectCursorActivityForChange = true; + if (changeObj.origin == '+input' || changeObj.origin == 'paste' + || changeObj.origin === undefined /* only in testing */) { + var text = changeObj.text.join('\n'); + lastChange.changes.push(text); + } + changeObj = changeObj.next; + } + } + } + function onCursorActivity(cm) { + var vim = cm.state.vim; + if (vim.insertMode) { + var macroModeState = vimGlobalState.macroModeState; + if (macroModeState.isPlaying) { return; } + var lastChange = macroModeState.lastInsertModeChanges; + if (lastChange.expectCursorActivityForChange) { + lastChange.expectCursorActivityForChange = false; + } else { + lastChange.changes = []; + } + } else if (!cm.curOp.isVimOp) { + handleExternalSelection(cm, vim); + } + if (vim.visualMode) { + updateFakeCursor(cm); + } + } + function updateFakeCursor(cm) { + var vim = cm.state.vim; + var from = copyCursor(vim.sel.head); + var to = offsetCursor(from, 0, 1); + if (vim.fakeCursor) { + vim.fakeCursor.clear(); + } + vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); + } + function handleExternalSelection(cm, vim) { + var anchor = cm.getCursor('anchor'); + var head = cm.getCursor('head'); + if (vim.visualMode && cursorEqual(head, anchor) && lineLength(cm, head.line) > head.ch) { + exitVisualMode(cm, false); + } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) { + vim.visualMode = true; + vim.visualLine = false; + CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); + } + if (vim.visualMode) { + var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; + var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; + head = offsetCursor(head, 0, headOffset); + anchor = offsetCursor(anchor, 0, anchorOffset); + vim.sel = { + anchor: anchor, + head: head + }; + updateMark(cm, vim, '<', cursorMin(head, anchor)); + updateMark(cm, vim, '>', cursorMax(head, anchor)); + } else if (!vim.insertMode) { + vim.lastHPos = cm.getCursor().ch; + } + } + function InsertModeKey(keyName) { + this.keyName = keyName; + } + function onKeyEventTargetKeyDown(e) { + var macroModeState = vimGlobalState.macroModeState; + var lastChange = macroModeState.lastInsertModeChanges; + var keyName = CodeMirror.keyName(e); + function onKeyFound() { + lastChange.changes.push(new InsertModeKey(keyName)); + return true; + } + if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) { + CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound); + } + } + function repeatLastEdit(cm, vim, repeat, repeatForInsert) { + var macroModeState = vimGlobalState.macroModeState; + macroModeState.isPlaying = true; + var isAction = !!vim.lastEditActionCommand; + var cachedInputState = vim.inputState; + function repeatCommand() { + if (isAction) { + commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand); + } else { + commandDispatcher.evalInput(cm, vim); + } + } + function repeatInsert(repeat) { + if (macroModeState.lastInsertModeChanges.changes.length > 0) { + repeat = !vim.lastEditActionCommand ? 1 : repeat; + var changeObject = macroModeState.lastInsertModeChanges; + repeatInsertModeChanges(cm, changeObject.changes, repeat); + } + } + vim.inputState = vim.lastEditInputState; + if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) { + for (var i = 0; i < repeat; i++) { + repeatCommand(); + repeatInsert(1); + } + } else { + if (!repeatForInsert) { + repeatCommand(); + } + repeatInsert(repeat); + } + vim.inputState = cachedInputState; + if (vim.insertMode && !repeatForInsert) { + exitInsertMode(cm); + } + macroModeState.isPlaying = false; + }; + + function repeatInsertModeChanges(cm, changes, repeat) { + function keyHandler(binding) { + if (typeof binding == 'string') { + CodeMirror.commands[binding](cm); + } else { + binding(cm); + } + return true; + } + var head = cm.getCursor('head'); + var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; + if (inVisualBlock) { + var vim = cm.state.vim; + var lastSel = vim.lastSelection; + var offset = getOffset(lastSel.anchor, lastSel.head); + selectForInsert(cm, head, offset.line + 1); + repeat = cm.listSelections().length; + cm.setCursor(head); + } + for (var i = 0; i < repeat; i++) { + if (inVisualBlock) { + cm.setCursor(offsetCursor(head, i, 0)); + } + for (var j = 0; j < changes.length; j++) { + var change = changes[j]; + if (change instanceof InsertModeKey) { + CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); + } else { + var cur = cm.getCursor(); + cm.replaceRange(change, cur, cur); + } + } + } + if (inVisualBlock) { + cm.setCursor(offsetCursor(head, 0, 1)); + } + } + + resetVimGlobalState(); + CodeMirror.Vim = Vim(); + + Vim = CodeMirror.Vim; + + var specialKey = {'return':'CR',backspace:'BS','delete':'Del',esc:'Esc', + left:'Left',right:'Right',up:'Up',down:'Down',space: 'Space', + home:'Home',end:'End',pageup:'PageUp',pagedown:'PageDown', enter: 'CR' + }; + function lookupKey(hashId, key, e) { + if (key.length > 1 && key[0] == "n") { + key = key.replace("numpad", ""); + } + key = specialKey[key] || key; + var name = ''; + if (e.ctrlKey) { name += 'C-'; } + if (e.altKey) { name += 'A-'; } + if (e.shiftKey) { name += 'S-'; } + + name += key; + if (name.length > 1) { name = '<' + name + '>'; } + return name; + } + var handleKey = Vim.handleKey.bind(Vim); + Vim.handleKey = function(cm, key, origin) { + return cm.operation(function() { + return handleKey(cm, key, origin); + }, true); + } + function cloneVimState(state) { + var n = new state.constructor(); + Object.keys(state).forEach(function(key) { + var o = state[key]; + if (Array.isArray(o)) + o = o.slice(); + else if (o && typeof o == "object" && o.constructor != Object) + o = cloneVimState(o); + n[key] = o; + }); + if (state.sel) { + n.sel = { + head: state.sel.head && copyCursor(state.sel.head), + anchor: state.sel.anchor && copyCursor(state.sel.anchor) + }; + } + return n; + } + function multiSelectHandleKey(cm, key, origin) { + var isHandled = false; + var vim = Vim.maybeInitVimState_(cm); + var visualBlock = vim.visualBlock || vim.wasInVisualBlock; + if (vim.wasInVisualBlock && !cm.ace.inMultiSelectMode) { + vim.wasInVisualBlock = false; + } else if (cm.ace.inMultiSelectMode && vim.visualBlock) { + vim.wasInVisualBlock = true; + } + + if (key == '' && !vim.insertMode && !vim.visualMode && cm.ace.inMultiSelectMode) { + cm.ace.exitMultiSelectMode(); + } else if (visualBlock || !cm.ace.inMultiSelectMode || cm.ace.inVirtualSelectionMode) { + isHandled = Vim.handleKey(cm, key, origin); + } else { + var old = cloneVimState(vim); + cm.operation(function() { + cm.ace.forEachSelection(function() { + var sel = cm.ace.selection; + cm.state.vim.lastHPos = sel.$desiredColumn == null ? sel.lead.column : sel.$desiredColumn; + var head = cm.getCursor("head"); + var anchor = cm.getCursor("anchor"); + var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; + var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; + head = offsetCursor(head, 0, headOffset); + anchor = offsetCursor(anchor, 0, anchorOffset); + cm.state.vim.sel.head = head; + cm.state.vim.sel.anchor = anchor; + + isHandled = handleKey(cm, key, origin); + sel.$desiredColumn = cm.state.vim.lastHPos == -1 ? null : cm.state.vim.lastHPos; + if (cm.virtualSelectionMode()) { + cm.state.vim = cloneVimState(old); + } + }); + if (cm.curOp.cursorActivity && !isHandled) + cm.curOp.cursorActivity = false; + }, true); + } + return isHandled; + }; + exports.CodeMirror = CodeMirror; + var getVim = Vim.maybeInitVimState_; + exports.handler = { + $id: "ace/keyboard/vim", + drawCursor: function(style, pixelPos, config, sel, session) { + var vim = this.state.vim || {}; + var w = config.characterWidth; + var h = config.lineHeight; + var top = pixelPos.top; + var left = pixelPos.left; + if (!vim.insertMode) { + var isbackwards = !sel.cursor + ? session.selection.isBackwards() || session.selection.isEmpty() + : Range.comparePoints(sel.cursor, sel.start) <= 0 + if (!isbackwards && left > w) + left -= w + } + if (!vim.insertMode && vim.status) { + h = h / 2; + top += h; + } + style.left = left + "px"; + style.top = top + "px"; + style.width = w + "px"; + style.height = h + "px"; + }, + handleKeyboard: function(data, hashId, key, keyCode, e) { + var editor = data.editor; + var cm = editor.state.cm; + var vim = getVim(cm); + if (keyCode == -1) return; + + if (key == "c" && hashId == 1) { // key == "ctrl-c" + if (!useragent.isMac && editor.getCopyText()) { + editor.once("copy", function() { + editor.selection.clearSelection(); + }); + return {command: "null", passEvent: true}; + } + } else if (!vim.insertMode) { + if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) { + hashId = -1; + key = data.inputChar; + } + } + + if (hashId == -1 || hashId & 1 || hashId === 0 && key.length > 1) { + var insertMode = vim.insertMode; + var name = lookupKey(hashId, key, e || {}); + if (vim.status == null) + vim.status = ""; + var isHandled = multiSelectHandleKey(cm, name, 'user'); + vim = getVim(cm); // may be changed by multiSelectHandleKey + if (isHandled && vim.status != null) + vim.status += name; + else if (vim.status == null) + vim.status = ""; + cm._signal("changeStatus"); + if (!isHandled && (hashId != -1 || insertMode)) + return; + return {command: "null", passEvent: !isHandled}; + } + }, + attach: function(editor) { + if (!editor.state) editor.state = {}; + var cm = new CodeMirror(editor); + editor.state.cm = cm; + editor.$vimModeHandler = this; + CodeMirror.keyMap.vim.attach(cm); + getVim(cm).status = null; + cm.on('vim-command-done', function() { + if (cm.virtualSelectionMode()) return; + getVim(cm).status = null; + cm.ace._signal("changeStatus"); + cm.ace.session.markUndoGroup(); + }); + cm.on("changeStatus", function() { + cm.ace.renderer.updateCursor(); + cm.ace._signal("changeStatus"); + }); + cm.on("vim-mode-change", function() { + if (cm.virtualSelectionMode()) return; + cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); + cm._signal("changeStatus"); + }); + cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); + editor.renderer.$cursorLayer.drawCursor = this.drawCursor.bind(cm); + this.updateMacCompositionHandlers(editor, true); + }, + detach: function(editor) { + var cm = editor.state.cm; + CodeMirror.keyMap.vim.detach(cm); + cm.destroy(); + editor.state.cm = null; + editor.$vimModeHandler = null; + editor.renderer.$cursorLayer.drawCursor = null; + editor.renderer.setStyle("normal-mode", false); + this.updateMacCompositionHandlers(editor, false); + }, + getStatusText: function(editor) { + var cm = editor.state.cm; + var vim = getVim(cm); + if (vim.insertMode) + return "INSERT"; + var status = ""; + if (vim.visualMode) { + status += "VISUAL"; + if (vim.visualLine) + status += " LINE"; + if (vim.visualBlock) + status += " BLOCK"; + } + if (vim.status) + status += (status ? " " : "") + vim.status; + return status; + }, + handleMacRepeat: function(data, hashId, key) { + if (hashId == -1) { + data.inputChar = key; + data.lastEvent = "input"; + } else if (data.inputChar && data.$lastHash == hashId && data.$lastKey == key) { + if (data.lastEvent == "input") { + data.lastEvent = "input1"; + } else if (data.lastEvent == "input1") { + return true; + } + } else { + data.$lastHash = hashId; + data.$lastKey = key; + data.lastEvent = "keypress"; + } + }, + updateMacCompositionHandlers: function(editor, enable) { + var onCompositionUpdateOverride = function(text) { + var cm = editor.state.cm; + var vim = getVim(cm); + if (!vim.insertMode) { + var el = this.textInput.getElement(); + el.blur(); + el.focus(); + el.value = text; + } else { + this.onCompositionUpdateOrig(text); + } + }; + var onCompositionStartOverride = function(text) { + var cm = editor.state.cm; + var vim = getVim(cm); + if (!vim.insertMode) { + this.onCompositionStartOrig(text); + } + }; + if (enable) { + if (!editor.onCompositionUpdateOrig) { + editor.onCompositionUpdateOrig = editor.onCompositionUpdate; + editor.onCompositionUpdate = onCompositionUpdateOverride; + editor.onCompositionStartOrig = editor.onCompositionStart; + editor.onCompositionStart = onCompositionStartOverride; + } + } else { + if (editor.onCompositionUpdateOrig) { + editor.onCompositionUpdate = editor.onCompositionUpdateOrig; + editor.onCompositionUpdateOrig = null; + editor.onCompositionStart = editor.onCompositionStartOrig; + editor.onCompositionStartOrig = null; + } + } + } + }; + var renderVirtualNumbers = { + getText: function(session, row) { + return (Math.abs(session.selection.lead.row - row) || (row + 1 + (row < 9? "\xb7" : "" ))) + "" + }, + getWidth: function(session, lastLineNumber, config) { + return session.getLength().toString().length * config.characterWidth; + }, + update: function(e, editor) { + editor.renderer.$loop.schedule(editor.renderer.CHANGE_GUTTER) + }, + attach: function(editor) { + editor.renderer.$gutterLayer.$renderer = this; + editor.on("changeSelection", this.update); + }, + detach: function(editor) { + editor.renderer.$gutterLayer.$renderer = null; + editor.off("changeSelection", this.update); + } + }; + Vim.defineOption({ + name: "wrap", + set: function(value, cm) { + if (cm) {cm.ace.setOption("wrap", value)} + }, + type: "boolean" + }, false); + Vim.defineEx('write', 'w', function() { + console.log(':write is not implemented') + }); + defaultKeymap.push( + { keys: 'zc', type: 'action', action: 'fold', actionArgs: { open: false } }, + { keys: 'zC', type: 'action', action: 'fold', actionArgs: { open: false, all: true } }, + { keys: 'zo', type: 'action', action: 'fold', actionArgs: { open: true, } }, + { keys: 'zO', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, + { keys: 'za', type: 'action', action: 'fold', actionArgs: { toggle: true } }, + { keys: 'zA', type: 'action', action: 'fold', actionArgs: { toggle: true, all: true } }, + { keys: 'zf', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, + { keys: 'zd', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, + + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAbove" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelow" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAboveSkipCurrent" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelowSkipCurrent" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreBefore" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreAfter" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextBefore" } }, + { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextAfter" } } + ); + actions.aceCommand = function(cm, actionArgs, vim) { + cm.vimCmd = actionArgs; + if (cm.ace.inVirtualSelectionMode) + cm.ace.on("beforeEndOperation", delayedExecAceCommand); + else + delayedExecAceCommand(null, cm.ace) + }; + function delayedExecAceCommand(op, ace) { + ace.off("beforeEndOperation", delayedExecAceCommand); + var cmd = ace.state.cm.vimCmd; + if (cmd) { + ace.execCommand(cmd.exec ? cmd : cmd.name, cmd.args); + } + ace.curOp = ace.prevOp; + } + actions.fold = function(cm, actionArgs, vim) { + cm.ace.execCommand(['toggleFoldWidget', 'toggleFoldWidget', 'foldOther', 'unfoldall' + ][(actionArgs.all ? 2 : 0) + (actionArgs.open ? 1 : 0)]); + }, + + exports.handler.defaultKeymap = defaultKeymap; + exports.handler.actions = actions; + exports.Vim = Vim; + + Vim.map("Y", "yy"); +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/mode-asciidoc.js b/Patent2Net/media/graph-recipes/app/assets/ace/mode-asciidoc.js new file mode 100644 index 00000000..e8086823 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/mode-asciidoc.js @@ -0,0 +1,342 @@ +define("ace/mode/asciidoc_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var AsciidocHighlightRules = function() { + var identifierRe = "[a-zA-Z\u00a1-\uffff]+\\b"; + + this.$rules = { + "start": [ + {token: "empty", regex: /$/}, + {token: "literal", regex: /^\.{4,}\s*$/, next: "listingBlock"}, + {token: "literal", regex: /^-{4,}\s*$/, next: "literalBlock"}, + {token: "string", regex: /^\+{4,}\s*$/, next: "passthroughBlock"}, + {token: "keyword", regex: /^={4,}\s*$/}, + {token: "text", regex: /^\s*$/}, + {token: "empty", regex: "", next: "dissallowDelimitedBlock"} + ], + + "dissallowDelimitedBlock": [ + {include: "paragraphEnd"}, + {token: "comment", regex: '^//.+$'}, + {token: "keyword", regex: "^(?:NOTE|TIP|IMPORTANT|WARNING|CAUTION):"}, + + {include: "listStart"}, + {token: "literal", regex: /^\s+.+$/, next: "indentedBlock"}, + {token: "empty", regex: "", next: "text"} + ], + + "paragraphEnd": [ + {token: "doc.comment", regex: /^\/{4,}\s*$/, next: "commentBlock"}, + {token: "tableBlock", regex: /^\s*[|!]=+\s*$/, next: "tableBlock"}, + {token: "keyword", regex: /^(?:--|''')\s*$/, next: "start"}, + {token: "option", regex: /^\[.*\]\s*$/, next: "start"}, + {token: "pageBreak", regex: /^>{3,}$/, next: "start"}, + {token: "literal", regex: /^\.{4,}\s*$/, next: "listingBlock"}, + {token: "titleUnderline", regex: /^(?:={2,}|-{2,}|~{2,}|\^{2,}|\+{2,})\s*$/, next: "start"}, + {token: "singleLineTitle", regex: /^={1,5}\s+\S.*$/, next: "start"}, + + {token: "otherBlock", regex: /^(?:\*{2,}|_{2,})\s*$/, next: "start"}, + {token: "optionalTitle", regex: /^\.[^.\s].+$/, next: "start"} + ], + + "listStart": [ + {token: "keyword", regex: /^\s*(?:\d+\.|[a-zA-Z]\.|[ixvmIXVM]+\)|\*{1,5}|-|\.{1,5})\s/, next: "listText"}, + {token: "meta.tag", regex: /^.+(?::{2,4}|;;)(?: |$)/, next: "listText"}, + {token: "support.function.list.callout", regex: /^(?:<\d+>|\d+>|>) /, next: "text"}, + {token: "keyword", regex: /^\+\s*$/, next: "start"} + ], + + "text": [ + {token: ["link", "variable.language"], regex: /((?:https?:\/\/|ftp:\/\/|file:\/\/|mailto:|callto:)[^\s\[]+)(\[.*?\])/}, + {token: "link", regex: /(?:https?:\/\/|ftp:\/\/|file:\/\/|mailto:|callto:)[^\s\[]+/}, + {token: "link", regex: /\b[\w\.\/\-]+@[\w\.\/\-]+\b/}, + {include: "macros"}, + {include: "paragraphEnd"}, + {token: "literal", regex:/\+{3,}/, next:"smallPassthrough"}, + {token: "escape", regex: /\((?:C|TM|R)\)|\.{3}|->|<-|=>|<=|&#(?:\d+|x[a-fA-F\d]+);|(?: |^)--(?=\s+\S)/}, + {token: "escape", regex: /\\[_*'`+#]|\\{2}[_*'`+#]{2}/}, + {token: "keyword", regex: /\s\+$/}, + {token: "text", regex: identifierRe}, + {token: ["keyword", "string", "keyword"], + regex: /(<<[\w\d\-$]+,)(.*?)(>>|$)/}, + {token: "keyword", regex: /<<[\w\d\-$]+,?|>>/}, + {token: "constant.character", regex: /\({2,3}.*?\){2,3}/}, + {token: "keyword", regex: /\[\[.+?\]\]/}, + {token: "support", regex: /^\[{3}[\w\d =\-]+\]{3}/}, + + {include: "quotes"}, + {token: "empty", regex: /^\s*$/, next: "start"} + ], + + "listText": [ + {include: "listStart"}, + {include: "text"} + ], + + "indentedBlock": [ + {token: "literal", regex: /^[\s\w].+$/, next: "indentedBlock"}, + {token: "literal", regex: "", next: "start"} + ], + + "listingBlock": [ + {token: "literal", regex: /^\.{4,}\s*$/, next: "dissallowDelimitedBlock"}, + {token: "constant.numeric", regex: '<\\d+>'}, + {token: "literal", regex: '[^<]+'}, + {token: "literal", regex: '<'} + ], + "literalBlock": [ + {token: "literal", regex: /^-{4,}\s*$/, next: "dissallowDelimitedBlock"}, + {token: "constant.numeric", regex: '<\\d+>'}, + {token: "literal", regex: '[^<]+'}, + {token: "literal", regex: '<'} + ], + "passthroughBlock": [ + {token: "literal", regex: /^\+{4,}\s*$/, next: "dissallowDelimitedBlock"}, + {token: "literal", regex: identifierRe + "|\\d+"}, + {include: "macros"}, + {token: "literal", regex: "."} + ], + + "smallPassthrough": [ + {token: "literal", regex: /[+]{3,}/, next: "dissallowDelimitedBlock"}, + {token: "literal", regex: /^\s*$/, next: "dissallowDelimitedBlock"}, + {token: "literal", regex: identifierRe + "|\\d+"}, + {include: "macros"} + ], + + "commentBlock": [ + {token: "doc.comment", regex: /^\/{4,}\s*$/, next: "dissallowDelimitedBlock"}, + {token: "doc.comment", regex: '^.*$'} + ], + "tableBlock": [ + {token: "tableBlock", regex: /^\s*\|={3,}\s*$/, next: "dissallowDelimitedBlock"}, + {token: "tableBlock", regex: /^\s*!={3,}\s*$/, next: "innerTableBlock"}, + {token: "tableBlock", regex: /\|/}, + {include: "text", noEscape: true} + ], + "innerTableBlock": [ + {token: "tableBlock", regex: /^\s*!={3,}\s*$/, next: "tableBlock"}, + {token: "tableBlock", regex: /^\s*|={3,}\s*$/, next: "dissallowDelimitedBlock"}, + {token: "tableBlock", regex: /\!/} + ], + "macros": [ + {token: "macro", regex: /{[\w\-$]+}/}, + {token: ["text", "string", "text", "constant.character", "text"], regex: /({)([\w\-$]+)(:)?(.+)?(})/}, + {token: ["text", "markup.list.macro", "keyword", "string"], regex: /(\w+)(footnote(?:ref)?::?)([^\s\[]+)?(\[.*?\])?/}, + {token: ["markup.list.macro", "keyword", "string"], regex: /([a-zA-Z\-][\w\.\/\-]*::?)([^\s\[]+)(\[.*?\])?/}, + {token: ["markup.list.macro", "keyword"], regex: /([a-zA-Z\-][\w\.\/\-]+::?)(\[.*?\])/}, + {token: "keyword", regex: /^:.+?:(?= |$)/} + ], + + "quotes": [ + {token: "string.italic", regex: /__[^_\s].*?__/}, + {token: "string.italic", regex: quoteRule("_")}, + + {token: "keyword.bold", regex: /\*\*[^*\s].*?\*\*/}, + {token: "keyword.bold", regex: quoteRule("\\*")}, + + {token: "literal", regex: quoteRule("\\+")}, + {token: "literal", regex: /\+\+[^+\s].*?\+\+/}, + {token: "literal", regex: /\$\$.+?\$\$/}, + {token: "literal", regex: quoteRule("`")}, + + {token: "keyword", regex: quoteRule("^")}, + {token: "keyword", regex: quoteRule("~")}, + {token: "keyword", regex: /##?/}, + {token: "keyword", regex: /(?:\B|^)``|\b''/} + ] + + }; + + function quoteRule(ch) { + var prefix = /\w/.test(ch) ? "\\b" : "(?:\\B|^)"; + return prefix + ch + "[^" + ch + "].*?" + ch + "(?![\\w*])"; + } + + var tokenMap = { + macro: "constant.character", + tableBlock: "doc.comment", + titleUnderline: "markup.heading", + singleLineTitle: "markup.heading", + pageBreak: "string", + option: "string.regexp", + otherBlock: "markup.list", + literal: "support.function", + optionalTitle: "constant.numeric", + escape: "constant.language.escape", + link: "markup.underline.list" + }; + + for (var state in this.$rules) { + var stateRules = this.$rules[state]; + for (var i = stateRules.length; i--; ) { + var rule = stateRules[i]; + if (rule.include || typeof rule == "string") { + var args = [i, 1].concat(this.$rules[rule.include || rule]); + if (rule.noEscape) { + args = args.filter(function(x) { + return !x.next; + }); + } + stateRules.splice.apply(stateRules, args); + } else if (rule.token in tokenMap) { + rule.token = tokenMap[rule.token]; + } + } + } +}; +oop.inherits(AsciidocHighlightRules, TextHighlightRules); + +exports.AsciidocHighlightRules = AsciidocHighlightRules; +}); + +define("ace/mode/folding/asciidoc",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var BaseFoldMode = require("./fold_mode").FoldMode; +var Range = require("../../range").Range; + +var FoldMode = exports.FoldMode = function() {}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + this.foldingStartMarker = /^(?:\|={10,}|[\.\/=\-~^+]{4,}\s*$|={1,5} )/; + this.singleLineHeadingRe = /^={1,5}(?=\s+\S)/; + + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + if (!this.foldingStartMarker.test(line)) + return "" + + if (line[0] == "=") { + if (this.singleLineHeadingRe.test(line)) + return "start"; + if (session.getLine(row - 1).length != session.getLine(row).length) + return ""; + return "start"; + } + if (session.bgTokenizer.getState(row) == "dissallowDelimitedBlock") + return "end"; + return "start"; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var line = session.getLine(row); + var startColumn = line.length; + var maxRow = session.getLength(); + var startRow = row; + var endRow = row; + if (!line.match(this.foldingStartMarker)) + return; + + var token; + function getTokenType(row) { + token = session.getTokens(row)[0]; + return token && token.type; + } + + var levels = ["=","-","~","^","+"]; + var heading = "markup.heading"; + var singleLineHeadingRe = this.singleLineHeadingRe; + function getLevel() { + var match = token.value.match(singleLineHeadingRe); + if (match) + return match[0].length; + var level = levels.indexOf(token.value[0]) + 1; + if (level == 1) { + if (session.getLine(row - 1).length != session.getLine(row).length) + return Infinity; + } + return level; + } + + if (getTokenType(row) == heading) { + var startHeadingLevel = getLevel(); + while (++row < maxRow) { + if (getTokenType(row) != heading) + continue; + var level = getLevel(); + if (level <= startHeadingLevel) + break; + } + + var isSingleLineHeading = token && token.value.match(this.singleLineHeadingRe); + endRow = isSingleLineHeading ? row - 1 : row - 2; + + if (endRow > startRow) { + while (endRow > startRow && (!getTokenType(endRow) || token.value[0] == "[")) + endRow--; + } + + if (endRow > startRow) { + var endColumn = session.getLine(endRow).length; + return new Range(startRow, startColumn, endRow, endColumn); + } + } else { + var state = session.bgTokenizer.getState(row); + if (state == "dissallowDelimitedBlock") { + while (row -- > 0) { + if (session.bgTokenizer.getState(row).lastIndexOf("Block") == -1) + break; + } + endRow = row + 1; + if (endRow < startRow) { + var endColumn = session.getLine(row).length; + return new Range(endRow, 5, startRow, startColumn - 5); + } + } else { + while (++row < maxRow) { + if (session.bgTokenizer.getState(row) == "dissallowDelimitedBlock") + break; + } + endRow = row; + if (endRow > startRow) { + var endColumn = session.getLine(row).length; + return new Range(startRow, 5, endRow, endColumn - 5); + } + } + } + }; + +}).call(FoldMode.prototype); + +}); + +define("ace/mode/asciidoc",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/asciidoc_highlight_rules","ace/mode/folding/asciidoc"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var AsciidocHighlightRules = require("./asciidoc_highlight_rules").AsciidocHighlightRules; +var AsciidocFoldMode = require("./folding/asciidoc").FoldMode; + +var Mode = function() { + this.HighlightRules = AsciidocHighlightRules; + + this.foldingRules = new AsciidocFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + this.type = "text"; + this.getNextLineIndent = function(state, line, tab) { + if (state == "listblock") { + var match = /^((?:.+)?)([-+*][ ]+)/.exec(line); + if (match) { + return new Array(match[1].length + 1).join(" ") + match[2]; + } else { + return ""; + } + } else { + return this.$getIndent(line); + } + }; + this.$id = "ace/mode/asciidoc"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/mode-javascript.js b/Patent2Net/media/graph-recipes/app/assets/ace/mode-javascript.js new file mode 100644 index 00000000..42d72c32 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/mode-javascript.js @@ -0,0 +1,1025 @@ +define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var DocCommentHighlightRules = function() { + this.$rules = { + "start" : [ { + token : "comment.doc.tag", + regex : "@[\\w\\d_]+" // TODO: fix email addresses + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true + }] + }; +}; + +oop.inherits(DocCommentHighlightRules, TextHighlightRules); + +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + +DocCommentHighlightRules.getStartRule = function(start) { + return { + token : "comment.doc", // doc comment + regex : "\\/\\*(?=\\*)", + next : start + }; +}; + +DocCommentHighlightRules.getEndRule = function (start) { + return { + token : "comment.doc", // closing comment + regex : "\\*\\/", + next : start + }; +}; + + +exports.DocCommentHighlightRules = DocCommentHighlightRules; + +}); + +define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules; +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var JavaScriptHighlightRules = function(options) { + var keywordMapper = this.createKeywordMapper({ + "variable.language": + "Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|" + // Constructors + "Namespace|QName|XML|XMLList|" + // E4X + "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|" + + "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|" + + "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|" + // Errors + "SyntaxError|TypeError|URIError|" + + "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" + // Non-constructor functions + "isNaN|parseFloat|parseInt|" + + "JSON|Math|" + // Other + "this|arguments|prototype|window|document" , // Pseudo + "keyword": + "const|yield|import|get|set|" + + "break|case|catch|continue|default|delete|do|else|finally|for|function|" + + "if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|" + + "__parent__|__count__|escape|unescape|with|__proto__|" + + "class|enum|extends|super|export|implements|private|public|interface|package|protected|static", + "storage.type": + "const|let|var|function", + "constant.language": + "null|Infinity|NaN|undefined", + "support.function": + "alert", + "constant.language.boolean": "true|false" + }, "identifier"); + var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void"; + var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b"; + + var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex + "u[0-9a-fA-F]{4}|" + // unicode + "[0-2][0-7]{0,2}|" + // oct + "3[0-6][0-7]?|" + // oct + "37[0-7]?|" + // oct + "[4-7][0-7]?|" + //oct + ".)"; + + this.$rules = { + "no_regex" : [ + { + token : "comment", + regex : "\\/\\/", + next : "line_comment" + }, + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + regex : /\/\*/, + next : "comment" + }, { + token : "string", + regex : "'(?=.)", + next : "qstring" + }, { + token : "string", + regex : '"(?=.)', + next : "qqstring" + }, { + token : "constant.numeric", // hex + regex : /0[xX][0-9a-fA-F]+\b/ + }, { + token : "constant.numeric", // float + regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/ + }, { + token : [ + "storage.type", "punctuation.operator", "support.function", + "punctuation.operator", "entity.name.function", "text","keyword.operator" + ], + regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)", + next: "function_arguments" + }, { + token : [ + "storage.type", "punctuation.operator", "entity.name.function", "text", + "keyword.operator", "text", "storage.type", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "entity.name.function", "text", "keyword.operator", "text", "storage.type", + "text", "paren.lparen" + ], + regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "storage.type", "punctuation.operator", "entity.name.function", "text", + "keyword.operator", "text", + "storage.type", "text", "entity.name.function", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "storage.type", "text", "entity.name.function", "text", "paren.lparen" + ], + regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "entity.name.function", "text", "punctuation.operator", + "text", "storage.type", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "text", "text", "storage.type", "text", "paren.lparen" + ], + regex : "(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : "keyword", + regex : "(?:" + kwBeforeRe + ")\\b", + next : "start" + }, { + token : ["punctuation.operator", "support.function"], + regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/ + }, { + token : ["punctuation.operator", "support.function.dom"], + regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/ + }, { + token : ["punctuation.operator", "support.constant"], + regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/ + }, { + token : ["support.constant"], + regex : /that\b/ + }, { + token : ["storage.type", "punctuation.operator", "support.function.firebug"], + regex : /(console)(\.)(warn|info|log|error|time|trace|timeEnd|assert)\b/ + }, { + token : keywordMapper, + regex : identifierRe + }, { + token : "keyword.operator", + regex : /--|\+\+|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|[!$%&*+\-~\/^]=?/, + next : "start" + }, { + token : "punctuation.operator", + regex : /[?:,;.]/, + next : "start" + }, { + token : "paren.lparen", + regex : /[\[({]/, + next : "start" + }, { + token : "paren.rparen", + regex : /[\])}]/ + }, { + token: "comment", + regex: /^#!.*$/ + } + ], + "start": [ + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + regex : "\\/\\*", + next : "comment_regex_allowed" + }, { + token : "comment", + regex : "\\/\\/", + next : "line_comment_regex_allowed" + }, { + token: "string.regexp", + regex: "\\/", + next: "regex" + }, { + token : "text", + regex : "\\s+|^$", + next : "start" + }, { + token: "empty", + regex: "", + next: "no_regex" + } + ], + "regex": [ + { + token: "regexp.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + token: "string.regexp", + regex: "/[sxngimy]*", + next: "no_regex" + }, { + token : "invalid", + regex: /\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/ + }, { + token : "constant.language.escape", + regex: /\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/ + }, { + token : "constant.language.delimiter", + regex: /\|/ + }, { + token: "constant.language.escape", + regex: /\[\^?/, + next: "regex_character_class" + }, { + token: "empty", + regex: "$", + next: "no_regex" + }, { + defaultToken: "string.regexp" + } + ], + "regex_character_class": [ + { + token: "regexp.charclass.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + token: "constant.language.escape", + regex: "]", + next: "regex" + }, { + token: "constant.language.escape", + regex: "-" + }, { + token: "empty", + regex: "$", + next: "no_regex" + }, { + defaultToken: "string.regexp.charachterclass" + } + ], + "function_arguments": [ + { + token: "variable.parameter", + regex: identifierRe + }, { + token: "punctuation.operator", + regex: "[, ]+" + }, { + token: "punctuation.operator", + regex: "$" + }, { + token: "empty", + regex: "", + next: "no_regex" + } + ], + "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "\\*\\/", next : "start"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "comment" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "\\*\\/", next : "no_regex"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "$|^", next : "start"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "line_comment" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "$|^", next : "no_regex"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "qqstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : "\\\\$", + next : "qqstring" + }, { + token : "string", + regex : '"|$', + next : "no_regex" + }, { + defaultToken: "string" + } + ], + "qstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : "\\\\$", + next : "qstring" + }, { + token : "string", + regex : "'|$", + next : "no_regex" + }, { + defaultToken: "string" + } + ] + }; + + + if (!options || !options.noES6) { + this.$rules.no_regex.unshift({ + regex: "[{}]", onMatch: function(val, state, stack) { + this.next = val == "{" ? this.nextState : ""; + if (val == "{" && stack.length) { + stack.unshift("start", state); + return "paren"; + } + if (val == "}" && stack.length) { + stack.shift(); + this.next = stack.shift(); + if (this.next.indexOf("string") != -1) + return "paren.quasi.end"; + } + return val == "{" ? "paren.lparen" : "paren.rparen"; + }, + nextState: "start" + }, { + token : "string.quasi.start", + regex : /`/, + push : [{ + token : "constant.language.escape", + regex : escapedRe + }, { + token : "paren.quasi.start", + regex : /\${/, + push : "start" + }, { + token : "string.quasi.end", + regex : /`/, + next : "pop" + }, { + defaultToken: "string.quasi" + }] + }); + } + + this.embedRules(DocCommentHighlightRules, "doc-", + [ DocCommentHighlightRules.getEndRule("no_regex") ]); + + this.normalizeRules(); +}; + +oop.inherits(JavaScriptHighlightRules, TextHighlightRules); + +exports.JavaScriptHighlightRules = JavaScriptHighlightRules; +}); + +define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(require, exports, module) { +"use strict"; + +var Range = require("../range").Range; + +var MatchingBraceOutdent = function() {}; + +(function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + +}).call(MatchingBraceOutdent.prototype); + +exports.MatchingBraceOutdent = MatchingBraceOutdent; +}); + +define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); + +var SAFE_INSERT_IN_TOKENS = + ["text", "paren.rparen", "punctuation.operator"]; +var SAFE_INSERT_BEFORE_TOKENS = + ["text", "paren.rparen", "punctuation.operator", "comment"]; + +var context; +var contextCache = {}; +var initContext = function(editor) { + var id = -1; + if (editor.multiSelect) { + id = editor.selection.index; + if (contextCache.rangeCount != editor.multiSelect.rangeCount) + contextCache = {rangeCount: editor.multiSelect.rangeCount}; + } + if (contextCache[id]) + return context = contextCache[id]; + context = contextCache[id] = { + autoInsertedBrackets: 0, + autoInsertedRow: -1, + autoInsertedLineEnd: "", + maybeInsertedBrackets: 0, + maybeInsertedRow: -1, + maybeInsertedLineStart: "", + maybeInsertedLineEnd: "" + }; +}; + +var CstyleBehaviour = function() { + this.add("braces", "insertion", function(state, action, editor, session, text) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (text == '{') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { + return { + text: '{' + selected + '}', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode) { + CstyleBehaviour.recordAutoInsert(editor, session, "}"); + return { + text: '{}', + selection: [1, 1] + }; + } else { + CstyleBehaviour.recordMaybeInsert(editor, session, "{"); + return { + text: '{', + selection: [1, 1] + }; + } + } + } else if (text == '}') { + initContext(editor); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } else if (text == "\n" || text == "\r\n") { + initContext(editor); + var closing = ""; + if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { + closing = lang.stringRepeat("}", context.maybeInsertedBrackets); + CstyleBehaviour.clearMaybeInsertedClosing(); + } + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === '}') { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column+1}, '}'); + if (!openBracePos) + return null; + var next_indent = this.$getIndent(session.getLine(openBracePos.row)); + } else if (closing) { + var next_indent = this.$getIndent(line); + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + return; + } + var indent = next_indent + session.getTabString(); + + return { + text: '\n' + indent + '\n' + next_indent + closing, + selection: [1, indent.length, 1, indent.length] + }; + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + } + }); + + this.add("braces", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar == '}') { + range.end.column++; + return range; + } else { + context.maybeInsertedBrackets--; + } + } + }); + + this.add("parens", "insertion", function(state, action, editor, session, text) { + if (text == '(') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '(' + selected + ')', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, ")"); + return { + text: '()', + selection: [1, 1] + }; + } + } else if (text == ')') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ')') { + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("parens", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ')') { + range.end.column++; + return range; + } + } + }); + + this.add("brackets", "insertion", function(state, action, editor, session, text) { + if (text == '[') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '[' + selected + ']', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, "]"); + return { + text: '[]', + selection: [1, 1] + }; + } + } else if (text == ']') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ']') { + var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("brackets", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '[') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ']') { + range.end.column++; + return range; + } + } + }); + + this.add("string_dquotes", "insertion", function(state, action, editor, session, text) { + if (text == '"' || text == "'") { + initContext(editor); + var quote = text; + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { + return { + text: quote + selected + quote, + selection: false + }; + } else if (!selected) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + var rightChar = line.substring(cursor.column, cursor.column + 1); + + var token = session.getTokenAt(cursor.row, cursor.column); + var rightToken = session.getTokenAt(cursor.row, cursor.column + 1); + if (leftChar == "\\" && token && /escape/.test(token.type)) + return null; + + var stringBefore = token && /string/.test(token.type); + var stringAfter = !rightToken || /string/.test(rightToken.type); + + var pair; + if (rightChar == quote) { + pair = stringBefore !== stringAfter; + } else { + if (stringBefore && !stringAfter) + return null; // wrap string with different quote + if (stringBefore && stringAfter) + return null; // do not pair quotes inside strings + var wordRe = session.$mode.tokenRe; + wordRe.lastIndex = 0; + var isWordBefore = wordRe.test(leftChar); + wordRe.lastIndex = 0; + var isWordAfter = wordRe.test(leftChar); + if (isWordBefore || isWordAfter) + return null; // before or after alphanumeric + if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) + return null; // there is rightChar and it isn't closing + pair = true; + } + return { + text: pair ? quote + quote : "", + selection: [1,1] + }; + } + } + }); + + this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + +}; + + +CstyleBehaviour.isSaneInsertion = function(editor, session) { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { + var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); + if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) + return false; + } + iterator.stepForward(); + return iterator.getCurrentTokenRow() !== cursor.row || + this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); +}; + +CstyleBehaviour.$matchTokenType = function(token, types) { + return types.indexOf(token.type || token) > -1; +}; + +CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0])) + context.autoInsertedBrackets = 0; + context.autoInsertedRow = cursor.row; + context.autoInsertedLineEnd = bracket + line.substr(cursor.column); + context.autoInsertedBrackets++; +}; + +CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isMaybeInsertedClosing(cursor, line)) + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = cursor.row; + context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; + context.maybeInsertedLineEnd = line.substr(cursor.column); + context.maybeInsertedBrackets++; +}; + +CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { + return context.autoInsertedBrackets > 0 && + cursor.row === context.autoInsertedRow && + bracket === context.autoInsertedLineEnd[0] && + line.substr(cursor.column) === context.autoInsertedLineEnd; +}; + +CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { + return context.maybeInsertedBrackets > 0 && + cursor.row === context.maybeInsertedRow && + line.substr(cursor.column) === context.maybeInsertedLineEnd && + line.substr(0, cursor.column) == context.maybeInsertedLineStart; +}; + +CstyleBehaviour.popAutoInsertedClosing = function() { + context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1); + context.autoInsertedBrackets--; +}; + +CstyleBehaviour.clearMaybeInsertedClosing = function() { + if (context) { + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = -1; + } +}; + + + +oop.inherits(CstyleBehaviour, Behaviour); + +exports.CstyleBehaviour = CstyleBehaviour; +}); + +define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Range = require("../../range").Range; +var BaseFoldMode = require("./fold_mode").FoldMode; + +var FoldMode = exports.FoldMode = function(commentRegex) { + if (commentRegex) { + this.foldingStartMarker = new RegExp( + this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start) + ); + this.foldingStopMarker = new RegExp( + this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end) + ); + } +}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; + this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/; + this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; + this.startRegionRe = /^\s*(\/\*|\/\/)#region\b/; + this._getFoldWidgetBase = this.getFoldWidget; + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + + if (this.singleLineBlockCommentRe.test(line)) { + if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) + return ""; + } + + var fw = this._getFoldWidgetBase(session, foldStyle, row); + + if (!fw && this.startRegionRe.test(line)) + return "start"; // lineCommentRegionStart + + return fw; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { + var line = session.getLine(row); + + if (this.startRegionRe.test(line)) + return this.getCommentRegionBlock(session, line, row); + + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + + if (match[1]) + return this.openingBracketBlock(session, match[1], row, i); + + var range = session.getCommentFoldRange(row, i + match[0].length, 1); + + if (range && !range.isMultiLine()) { + if (forceMultiline) { + range = this.getSectionRange(session, row); + } else if (foldStyle != "all") + range = null; + } + + return range; + } + + if (foldStyle === "markbegin") + return; + + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + + if (match[1]) + return this.closingBracketBlock(session, match[1], row, i); + + return session.getCommentFoldRange(row, i, -1); + } + }; + + this.getSectionRange = function(session, row) { + var line = session.getLine(row); + var startIndent = line.search(/\S/); + var startRow = row; + var startColumn = line.length; + row = row + 1; + var endRow = row; + var maxRow = session.getLength(); + while (++row < maxRow) { + line = session.getLine(row); + var indent = line.search(/\S/); + if (indent === -1) + continue; + if (startIndent > indent) + break; + var subRange = this.getFoldWidgetRange(session, "all", row); + + if (subRange) { + if (subRange.start.row <= startRow) { + break; + } else if (subRange.isMultiLine()) { + row = subRange.end.row; + } else if (startIndent == indent) { + break; + } + } + endRow = row; + } + + return new Range(startRow, startColumn, endRow, session.getLine(endRow).length); + }; + + this.getCommentRegionBlock = function(session, line, row) { + var startColumn = line.search(/\s*$/); + var maxRow = session.getLength(); + var startRow = row; + + var re = /^\s*(?:\/\*|\/\/)#(end)?region\b/; + var depth = 1; + while (++row < maxRow) { + line = session.getLine(row); + var m = re.exec(line); + if (!m) continue; + if (m[1]) depth--; + else depth++; + + if (!depth) break; + } + + var endRow = row; + if (endRow > startRow) { + return new Range(startRow, startColumn, endRow, line.length); + } + }; + +}).call(FoldMode.prototype); + +}); + +define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var Range = require("../range").Range; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = JavaScriptHighlightRules; + + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.lineCommentStart = "//"; + this.blockComment = {start: "/*", end: "*/"}; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + var endState = tokenizedLine.state; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start" || state == "no_regex") { + var match = line.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/); + if (match) { + indent += tab; + } + } else if (state == "doc-start") { + if (endState == "start" || endState == "no_regex") { + return ""; + } + var match = line.match(/^\s*(\/?)\*/); + if (match) { + if (match[1]) { + indent += " "; + } + indent += "* "; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker"); + worker.attachToDocument(session.getDocument()); + + worker.on("annotate", function(results) { + session.setAnnotations(results.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + this.$id = "ace/mode/javascript"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/mode-json.js b/Patent2Net/media/graph-recipes/app/assets/ace/mode-json.js new file mode 100644 index 00000000..bde95b39 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/mode-json.js @@ -0,0 +1,668 @@ +define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var JsonHighlightRules = function() { + this.$rules = { + "start" : [ + { + token : "variable", // single line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)' + }, { + token : "string", // single line + regex : '"', + next : "string" + }, { + token : "constant.numeric", // hex + regex : "0[xX][0-9a-fA-F]+\\b" + }, { + token : "constant.numeric", // float + regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b" + }, { + token : "constant.language.boolean", + regex : "(?:true|false)\\b" + }, { + token : "invalid.illegal", // single quoted strings are not allowed + regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" + }, { + token : "invalid.illegal", // comments are not allowed + regex : "\\/\\/.*$" + }, { + token : "paren.lparen", + regex : "[[({]" + }, { + token : "paren.rparen", + regex : "[\\])}]" + }, { + token : "text", + regex : "\\s+" + } + ], + "string" : [ + { + token : "constant.language.escape", + regex : /\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/ + }, { + token : "string", + regex : '[^"\\\\]+' + }, { + token : "string", + regex : '"', + next : "start" + }, { + token : "string", + regex : "", + next : "start" + } + ] + }; + +}; + +oop.inherits(JsonHighlightRules, TextHighlightRules); + +exports.JsonHighlightRules = JsonHighlightRules; +}); + +define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(require, exports, module) { +"use strict"; + +var Range = require("../range").Range; + +var MatchingBraceOutdent = function() {}; + +(function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + +}).call(MatchingBraceOutdent.prototype); + +exports.MatchingBraceOutdent = MatchingBraceOutdent; +}); + +define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); + +var SAFE_INSERT_IN_TOKENS = + ["text", "paren.rparen", "punctuation.operator"]; +var SAFE_INSERT_BEFORE_TOKENS = + ["text", "paren.rparen", "punctuation.operator", "comment"]; + +var context; +var contextCache = {}; +var initContext = function(editor) { + var id = -1; + if (editor.multiSelect) { + id = editor.selection.index; + if (contextCache.rangeCount != editor.multiSelect.rangeCount) + contextCache = {rangeCount: editor.multiSelect.rangeCount}; + } + if (contextCache[id]) + return context = contextCache[id]; + context = contextCache[id] = { + autoInsertedBrackets: 0, + autoInsertedRow: -1, + autoInsertedLineEnd: "", + maybeInsertedBrackets: 0, + maybeInsertedRow: -1, + maybeInsertedLineStart: "", + maybeInsertedLineEnd: "" + }; +}; + +var CstyleBehaviour = function() { + this.add("braces", "insertion", function(state, action, editor, session, text) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (text == '{') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { + return { + text: '{' + selected + '}', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode) { + CstyleBehaviour.recordAutoInsert(editor, session, "}"); + return { + text: '{}', + selection: [1, 1] + }; + } else { + CstyleBehaviour.recordMaybeInsert(editor, session, "{"); + return { + text: '{', + selection: [1, 1] + }; + } + } + } else if (text == '}') { + initContext(editor); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } else if (text == "\n" || text == "\r\n") { + initContext(editor); + var closing = ""; + if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { + closing = lang.stringRepeat("}", context.maybeInsertedBrackets); + CstyleBehaviour.clearMaybeInsertedClosing(); + } + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === '}') { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column+1}, '}'); + if (!openBracePos) + return null; + var next_indent = this.$getIndent(session.getLine(openBracePos.row)); + } else if (closing) { + var next_indent = this.$getIndent(line); + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + return; + } + var indent = next_indent + session.getTabString(); + + return { + text: '\n' + indent + '\n' + next_indent + closing, + selection: [1, indent.length, 1, indent.length] + }; + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + } + }); + + this.add("braces", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar == '}') { + range.end.column++; + return range; + } else { + context.maybeInsertedBrackets--; + } + } + }); + + this.add("parens", "insertion", function(state, action, editor, session, text) { + if (text == '(') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '(' + selected + ')', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, ")"); + return { + text: '()', + selection: [1, 1] + }; + } + } else if (text == ')') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ')') { + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("parens", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ')') { + range.end.column++; + return range; + } + } + }); + + this.add("brackets", "insertion", function(state, action, editor, session, text) { + if (text == '[') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '[' + selected + ']', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, "]"); + return { + text: '[]', + selection: [1, 1] + }; + } + } else if (text == ']') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ']') { + var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("brackets", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '[') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ']') { + range.end.column++; + return range; + } + } + }); + + this.add("string_dquotes", "insertion", function(state, action, editor, session, text) { + if (text == '"' || text == "'") { + initContext(editor); + var quote = text; + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { + return { + text: quote + selected + quote, + selection: false + }; + } else if (!selected) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + var rightChar = line.substring(cursor.column, cursor.column + 1); + + var token = session.getTokenAt(cursor.row, cursor.column); + var rightToken = session.getTokenAt(cursor.row, cursor.column + 1); + if (leftChar == "\\" && token && /escape/.test(token.type)) + return null; + + var stringBefore = token && /string/.test(token.type); + var stringAfter = !rightToken || /string/.test(rightToken.type); + + var pair; + if (rightChar == quote) { + pair = stringBefore !== stringAfter; + } else { + if (stringBefore && !stringAfter) + return null; // wrap string with different quote + if (stringBefore && stringAfter) + return null; // do not pair quotes inside strings + var wordRe = session.$mode.tokenRe; + wordRe.lastIndex = 0; + var isWordBefore = wordRe.test(leftChar); + wordRe.lastIndex = 0; + var isWordAfter = wordRe.test(leftChar); + if (isWordBefore || isWordAfter) + return null; // before or after alphanumeric + if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) + return null; // there is rightChar and it isn't closing + pair = true; + } + return { + text: pair ? quote + quote : "", + selection: [1,1] + }; + } + } + }); + + this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + +}; + + +CstyleBehaviour.isSaneInsertion = function(editor, session) { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { + var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); + if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) + return false; + } + iterator.stepForward(); + return iterator.getCurrentTokenRow() !== cursor.row || + this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); +}; + +CstyleBehaviour.$matchTokenType = function(token, types) { + return types.indexOf(token.type || token) > -1; +}; + +CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0])) + context.autoInsertedBrackets = 0; + context.autoInsertedRow = cursor.row; + context.autoInsertedLineEnd = bracket + line.substr(cursor.column); + context.autoInsertedBrackets++; +}; + +CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isMaybeInsertedClosing(cursor, line)) + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = cursor.row; + context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; + context.maybeInsertedLineEnd = line.substr(cursor.column); + context.maybeInsertedBrackets++; +}; + +CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { + return context.autoInsertedBrackets > 0 && + cursor.row === context.autoInsertedRow && + bracket === context.autoInsertedLineEnd[0] && + line.substr(cursor.column) === context.autoInsertedLineEnd; +}; + +CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { + return context.maybeInsertedBrackets > 0 && + cursor.row === context.maybeInsertedRow && + line.substr(cursor.column) === context.maybeInsertedLineEnd && + line.substr(0, cursor.column) == context.maybeInsertedLineStart; +}; + +CstyleBehaviour.popAutoInsertedClosing = function() { + context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1); + context.autoInsertedBrackets--; +}; + +CstyleBehaviour.clearMaybeInsertedClosing = function() { + if (context) { + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = -1; + } +}; + + + +oop.inherits(CstyleBehaviour, Behaviour); + +exports.CstyleBehaviour = CstyleBehaviour; +}); + +define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Range = require("../../range").Range; +var BaseFoldMode = require("./fold_mode").FoldMode; + +var FoldMode = exports.FoldMode = function(commentRegex) { + if (commentRegex) { + this.foldingStartMarker = new RegExp( + this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start) + ); + this.foldingStopMarker = new RegExp( + this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end) + ); + } +}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; + this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/; + this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; + this.startRegionRe = /^\s*(\/\*|\/\/)#region\b/; + this._getFoldWidgetBase = this.getFoldWidget; + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + + if (this.singleLineBlockCommentRe.test(line)) { + if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) + return ""; + } + + var fw = this._getFoldWidgetBase(session, foldStyle, row); + + if (!fw && this.startRegionRe.test(line)) + return "start"; // lineCommentRegionStart + + return fw; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { + var line = session.getLine(row); + + if (this.startRegionRe.test(line)) + return this.getCommentRegionBlock(session, line, row); + + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + + if (match[1]) + return this.openingBracketBlock(session, match[1], row, i); + + var range = session.getCommentFoldRange(row, i + match[0].length, 1); + + if (range && !range.isMultiLine()) { + if (forceMultiline) { + range = this.getSectionRange(session, row); + } else if (foldStyle != "all") + range = null; + } + + return range; + } + + if (foldStyle === "markbegin") + return; + + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + + if (match[1]) + return this.closingBracketBlock(session, match[1], row, i); + + return session.getCommentFoldRange(row, i, -1); + } + }; + + this.getSectionRange = function(session, row) { + var line = session.getLine(row); + var startIndent = line.search(/\S/); + var startRow = row; + var startColumn = line.length; + row = row + 1; + var endRow = row; + var maxRow = session.getLength(); + while (++row < maxRow) { + line = session.getLine(row); + var indent = line.search(/\S/); + if (indent === -1) + continue; + if (startIndent > indent) + break; + var subRange = this.getFoldWidgetRange(session, "all", row); + + if (subRange) { + if (subRange.start.row <= startRow) { + break; + } else if (subRange.isMultiLine()) { + row = subRange.end.row; + } else if (startIndent == indent) { + break; + } + } + endRow = row; + } + + return new Range(startRow, startColumn, endRow, session.getLine(endRow).length); + }; + + this.getCommentRegionBlock = function(session, line, row) { + var startColumn = line.search(/\s*$/); + var maxRow = session.getLength(); + var startRow = row; + + var re = /^\s*(?:\/\*|\/\/)#(end)?region\b/; + var depth = 1; + while (++row < maxRow) { + line = session.getLine(row); + var m = re.exec(line); + if (!m) continue; + if (m[1]) depth--; + else depth++; + + if (!depth) break; + } + + var endRow = row; + if (endRow > startRow) { + return new Range(startRow, startColumn, endRow, line.length); + } + }; + +}).call(FoldMode.prototype); + +}); + +define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var HighlightRules = require("./json_highlight_rules").JsonHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; +var WorkerClient = require("../worker/worker_client").WorkerClient; + +var Mode = function() { + this.HighlightRules = HighlightRules; + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + if (state == "start") { + var match = line.match(/^.*[\{\(\[]\s*$/); + if (match) { + indent += tab; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/json_worker", "JsonWorker"); + worker.attachToDocument(session.getDocument()); + + worker.on("annotate", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + + this.$id = "ace/mode/json"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/mode-markdown.js b/Patent2Net/media/graph-recipes/app/assets/ace/mode-markdown.js new file mode 100644 index 00000000..574042c0 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/mode-markdown.js @@ -0,0 +1,2820 @@ +define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var DocCommentHighlightRules = function() { + this.$rules = { + "start" : [ { + token : "comment.doc.tag", + regex : "@[\\w\\d_]+" // TODO: fix email addresses + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true + }] + }; +}; + +oop.inherits(DocCommentHighlightRules, TextHighlightRules); + +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + +DocCommentHighlightRules.getStartRule = function(start) { + return { + token : "comment.doc", // doc comment + regex : "\\/\\*(?=\\*)", + next : start + }; +}; + +DocCommentHighlightRules.getEndRule = function (start) { + return { + token : "comment.doc", // closing comment + regex : "\\*\\/", + next : start + }; +}; + + +exports.DocCommentHighlightRules = DocCommentHighlightRules; + +}); + +define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules; +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var JavaScriptHighlightRules = function(options) { + var keywordMapper = this.createKeywordMapper({ + "variable.language": + "Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|" + // Constructors + "Namespace|QName|XML|XMLList|" + // E4X + "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|" + + "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|" + + "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|" + // Errors + "SyntaxError|TypeError|URIError|" + + "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" + // Non-constructor functions + "isNaN|parseFloat|parseInt|" + + "JSON|Math|" + // Other + "this|arguments|prototype|window|document" , // Pseudo + "keyword": + "const|yield|import|get|set|" + + "break|case|catch|continue|default|delete|do|else|finally|for|function|" + + "if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|" + + "__parent__|__count__|escape|unescape|with|__proto__|" + + "class|enum|extends|super|export|implements|private|public|interface|package|protected|static", + "storage.type": + "const|let|var|function", + "constant.language": + "null|Infinity|NaN|undefined", + "support.function": + "alert", + "constant.language.boolean": "true|false" + }, "identifier"); + var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void"; + var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b"; + + var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex + "u[0-9a-fA-F]{4}|" + // unicode + "[0-2][0-7]{0,2}|" + // oct + "3[0-6][0-7]?|" + // oct + "37[0-7]?|" + // oct + "[4-7][0-7]?|" + //oct + ".)"; + + this.$rules = { + "no_regex" : [ + { + token : "comment", + regex : "\\/\\/", + next : "line_comment" + }, + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + regex : /\/\*/, + next : "comment" + }, { + token : "string", + regex : "'(?=.)", + next : "qstring" + }, { + token : "string", + regex : '"(?=.)', + next : "qqstring" + }, { + token : "constant.numeric", // hex + regex : /0[xX][0-9a-fA-F]+\b/ + }, { + token : "constant.numeric", // float + regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/ + }, { + token : [ + "storage.type", "punctuation.operator", "support.function", + "punctuation.operator", "entity.name.function", "text","keyword.operator" + ], + regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)", + next: "function_arguments" + }, { + token : [ + "storage.type", "punctuation.operator", "entity.name.function", "text", + "keyword.operator", "text", "storage.type", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "entity.name.function", "text", "keyword.operator", "text", "storage.type", + "text", "paren.lparen" + ], + regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "storage.type", "punctuation.operator", "entity.name.function", "text", + "keyword.operator", "text", + "storage.type", "text", "entity.name.function", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "storage.type", "text", "entity.name.function", "text", "paren.lparen" + ], + regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "entity.name.function", "text", "punctuation.operator", + "text", "storage.type", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "text", "text", "storage.type", "text", "paren.lparen" + ], + regex : "(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : "keyword", + regex : "(?:" + kwBeforeRe + ")\\b", + next : "start" + }, { + token : ["punctuation.operator", "support.function"], + regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/ + }, { + token : ["punctuation.operator", "support.function.dom"], + regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/ + }, { + token : ["punctuation.operator", "support.constant"], + regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/ + }, { + token : ["support.constant"], + regex : /that\b/ + }, { + token : ["storage.type", "punctuation.operator", "support.function.firebug"], + regex : /(console)(\.)(warn|info|log|error|time|trace|timeEnd|assert)\b/ + }, { + token : keywordMapper, + regex : identifierRe + }, { + token : "keyword.operator", + regex : /--|\+\+|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|[!$%&*+\-~\/^]=?/, + next : "start" + }, { + token : "punctuation.operator", + regex : /[?:,;.]/, + next : "start" + }, { + token : "paren.lparen", + regex : /[\[({]/, + next : "start" + }, { + token : "paren.rparen", + regex : /[\])}]/ + }, { + token: "comment", + regex: /^#!.*$/ + } + ], + "start": [ + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + regex : "\\/\\*", + next : "comment_regex_allowed" + }, { + token : "comment", + regex : "\\/\\/", + next : "line_comment_regex_allowed" + }, { + token: "string.regexp", + regex: "\\/", + next: "regex" + }, { + token : "text", + regex : "\\s+|^$", + next : "start" + }, { + token: "empty", + regex: "", + next: "no_regex" + } + ], + "regex": [ + { + token: "regexp.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + token: "string.regexp", + regex: "/[sxngimy]*", + next: "no_regex" + }, { + token : "invalid", + regex: /\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/ + }, { + token : "constant.language.escape", + regex: /\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/ + }, { + token : "constant.language.delimiter", + regex: /\|/ + }, { + token: "constant.language.escape", + regex: /\[\^?/, + next: "regex_character_class" + }, { + token: "empty", + regex: "$", + next: "no_regex" + }, { + defaultToken: "string.regexp" + } + ], + "regex_character_class": [ + { + token: "regexp.charclass.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + token: "constant.language.escape", + regex: "]", + next: "regex" + }, { + token: "constant.language.escape", + regex: "-" + }, { + token: "empty", + regex: "$", + next: "no_regex" + }, { + defaultToken: "string.regexp.charachterclass" + } + ], + "function_arguments": [ + { + token: "variable.parameter", + regex: identifierRe + }, { + token: "punctuation.operator", + regex: "[, ]+" + }, { + token: "punctuation.operator", + regex: "$" + }, { + token: "empty", + regex: "", + next: "no_regex" + } + ], + "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "\\*\\/", next : "start"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "comment" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "\\*\\/", next : "no_regex"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "$|^", next : "start"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "line_comment" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "$|^", next : "no_regex"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "qqstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : "\\\\$", + next : "qqstring" + }, { + token : "string", + regex : '"|$', + next : "no_regex" + }, { + defaultToken: "string" + } + ], + "qstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : "\\\\$", + next : "qstring" + }, { + token : "string", + regex : "'|$", + next : "no_regex" + }, { + defaultToken: "string" + } + ] + }; + + + if (!options || !options.noES6) { + this.$rules.no_regex.unshift({ + regex: "[{}]", onMatch: function(val, state, stack) { + this.next = val == "{" ? this.nextState : ""; + if (val == "{" && stack.length) { + stack.unshift("start", state); + return "paren"; + } + if (val == "}" && stack.length) { + stack.shift(); + this.next = stack.shift(); + if (this.next.indexOf("string") != -1) + return "paren.quasi.end"; + } + return val == "{" ? "paren.lparen" : "paren.rparen"; + }, + nextState: "start" + }, { + token : "string.quasi.start", + regex : /`/, + push : [{ + token : "constant.language.escape", + regex : escapedRe + }, { + token : "paren.quasi.start", + regex : /\${/, + push : "start" + }, { + token : "string.quasi.end", + regex : /`/, + next : "pop" + }, { + defaultToken: "string.quasi" + }] + }); + } + + this.embedRules(DocCommentHighlightRules, "doc-", + [ DocCommentHighlightRules.getEndRule("no_regex") ]); + + this.normalizeRules(); +}; + +oop.inherits(JavaScriptHighlightRules, TextHighlightRules); + +exports.JavaScriptHighlightRules = JavaScriptHighlightRules; +}); + +define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(require, exports, module) { +"use strict"; + +var Range = require("../range").Range; + +var MatchingBraceOutdent = function() {}; + +(function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + +}).call(MatchingBraceOutdent.prototype); + +exports.MatchingBraceOutdent = MatchingBraceOutdent; +}); + +define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); + +var SAFE_INSERT_IN_TOKENS = + ["text", "paren.rparen", "punctuation.operator"]; +var SAFE_INSERT_BEFORE_TOKENS = + ["text", "paren.rparen", "punctuation.operator", "comment"]; + +var context; +var contextCache = {}; +var initContext = function(editor) { + var id = -1; + if (editor.multiSelect) { + id = editor.selection.index; + if (contextCache.rangeCount != editor.multiSelect.rangeCount) + contextCache = {rangeCount: editor.multiSelect.rangeCount}; + } + if (contextCache[id]) + return context = contextCache[id]; + context = contextCache[id] = { + autoInsertedBrackets: 0, + autoInsertedRow: -1, + autoInsertedLineEnd: "", + maybeInsertedBrackets: 0, + maybeInsertedRow: -1, + maybeInsertedLineStart: "", + maybeInsertedLineEnd: "" + }; +}; + +var CstyleBehaviour = function() { + this.add("braces", "insertion", function(state, action, editor, session, text) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (text == '{') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { + return { + text: '{' + selected + '}', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode) { + CstyleBehaviour.recordAutoInsert(editor, session, "}"); + return { + text: '{}', + selection: [1, 1] + }; + } else { + CstyleBehaviour.recordMaybeInsert(editor, session, "{"); + return { + text: '{', + selection: [1, 1] + }; + } + } + } else if (text == '}') { + initContext(editor); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } else if (text == "\n" || text == "\r\n") { + initContext(editor); + var closing = ""; + if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { + closing = lang.stringRepeat("}", context.maybeInsertedBrackets); + CstyleBehaviour.clearMaybeInsertedClosing(); + } + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === '}') { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column+1}, '}'); + if (!openBracePos) + return null; + var next_indent = this.$getIndent(session.getLine(openBracePos.row)); + } else if (closing) { + var next_indent = this.$getIndent(line); + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + return; + } + var indent = next_indent + session.getTabString(); + + return { + text: '\n' + indent + '\n' + next_indent + closing, + selection: [1, indent.length, 1, indent.length] + }; + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + } + }); + + this.add("braces", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar == '}') { + range.end.column++; + return range; + } else { + context.maybeInsertedBrackets--; + } + } + }); + + this.add("parens", "insertion", function(state, action, editor, session, text) { + if (text == '(') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '(' + selected + ')', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, ")"); + return { + text: '()', + selection: [1, 1] + }; + } + } else if (text == ')') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ')') { + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("parens", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ')') { + range.end.column++; + return range; + } + } + }); + + this.add("brackets", "insertion", function(state, action, editor, session, text) { + if (text == '[') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '[' + selected + ']', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, "]"); + return { + text: '[]', + selection: [1, 1] + }; + } + } else if (text == ']') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ']') { + var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("brackets", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '[') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ']') { + range.end.column++; + return range; + } + } + }); + + this.add("string_dquotes", "insertion", function(state, action, editor, session, text) { + if (text == '"' || text == "'") { + initContext(editor); + var quote = text; + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { + return { + text: quote + selected + quote, + selection: false + }; + } else if (!selected) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + var rightChar = line.substring(cursor.column, cursor.column + 1); + + var token = session.getTokenAt(cursor.row, cursor.column); + var rightToken = session.getTokenAt(cursor.row, cursor.column + 1); + if (leftChar == "\\" && token && /escape/.test(token.type)) + return null; + + var stringBefore = token && /string/.test(token.type); + var stringAfter = !rightToken || /string/.test(rightToken.type); + + var pair; + if (rightChar == quote) { + pair = stringBefore !== stringAfter; + } else { + if (stringBefore && !stringAfter) + return null; // wrap string with different quote + if (stringBefore && stringAfter) + return null; // do not pair quotes inside strings + var wordRe = session.$mode.tokenRe; + wordRe.lastIndex = 0; + var isWordBefore = wordRe.test(leftChar); + wordRe.lastIndex = 0; + var isWordAfter = wordRe.test(leftChar); + if (isWordBefore || isWordAfter) + return null; // before or after alphanumeric + if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) + return null; // there is rightChar and it isn't closing + pair = true; + } + return { + text: pair ? quote + quote : "", + selection: [1,1] + }; + } + } + }); + + this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + +}; + + +CstyleBehaviour.isSaneInsertion = function(editor, session) { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { + var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); + if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) + return false; + } + iterator.stepForward(); + return iterator.getCurrentTokenRow() !== cursor.row || + this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); +}; + +CstyleBehaviour.$matchTokenType = function(token, types) { + return types.indexOf(token.type || token) > -1; +}; + +CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0])) + context.autoInsertedBrackets = 0; + context.autoInsertedRow = cursor.row; + context.autoInsertedLineEnd = bracket + line.substr(cursor.column); + context.autoInsertedBrackets++; +}; + +CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isMaybeInsertedClosing(cursor, line)) + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = cursor.row; + context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; + context.maybeInsertedLineEnd = line.substr(cursor.column); + context.maybeInsertedBrackets++; +}; + +CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { + return context.autoInsertedBrackets > 0 && + cursor.row === context.autoInsertedRow && + bracket === context.autoInsertedLineEnd[0] && + line.substr(cursor.column) === context.autoInsertedLineEnd; +}; + +CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { + return context.maybeInsertedBrackets > 0 && + cursor.row === context.maybeInsertedRow && + line.substr(cursor.column) === context.maybeInsertedLineEnd && + line.substr(0, cursor.column) == context.maybeInsertedLineStart; +}; + +CstyleBehaviour.popAutoInsertedClosing = function() { + context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1); + context.autoInsertedBrackets--; +}; + +CstyleBehaviour.clearMaybeInsertedClosing = function() { + if (context) { + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = -1; + } +}; + + + +oop.inherits(CstyleBehaviour, Behaviour); + +exports.CstyleBehaviour = CstyleBehaviour; +}); + +define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Range = require("../../range").Range; +var BaseFoldMode = require("./fold_mode").FoldMode; + +var FoldMode = exports.FoldMode = function(commentRegex) { + if (commentRegex) { + this.foldingStartMarker = new RegExp( + this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start) + ); + this.foldingStopMarker = new RegExp( + this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end) + ); + } +}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; + this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/; + this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; + this.startRegionRe = /^\s*(\/\*|\/\/)#region\b/; + this._getFoldWidgetBase = this.getFoldWidget; + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + + if (this.singleLineBlockCommentRe.test(line)) { + if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) + return ""; + } + + var fw = this._getFoldWidgetBase(session, foldStyle, row); + + if (!fw && this.startRegionRe.test(line)) + return "start"; // lineCommentRegionStart + + return fw; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { + var line = session.getLine(row); + + if (this.startRegionRe.test(line)) + return this.getCommentRegionBlock(session, line, row); + + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + + if (match[1]) + return this.openingBracketBlock(session, match[1], row, i); + + var range = session.getCommentFoldRange(row, i + match[0].length, 1); + + if (range && !range.isMultiLine()) { + if (forceMultiline) { + range = this.getSectionRange(session, row); + } else if (foldStyle != "all") + range = null; + } + + return range; + } + + if (foldStyle === "markbegin") + return; + + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + + if (match[1]) + return this.closingBracketBlock(session, match[1], row, i); + + return session.getCommentFoldRange(row, i, -1); + } + }; + + this.getSectionRange = function(session, row) { + var line = session.getLine(row); + var startIndent = line.search(/\S/); + var startRow = row; + var startColumn = line.length; + row = row + 1; + var endRow = row; + var maxRow = session.getLength(); + while (++row < maxRow) { + line = session.getLine(row); + var indent = line.search(/\S/); + if (indent === -1) + continue; + if (startIndent > indent) + break; + var subRange = this.getFoldWidgetRange(session, "all", row); + + if (subRange) { + if (subRange.start.row <= startRow) { + break; + } else if (subRange.isMultiLine()) { + row = subRange.end.row; + } else if (startIndent == indent) { + break; + } + } + endRow = row; + } + + return new Range(startRow, startColumn, endRow, session.getLine(endRow).length); + }; + + this.getCommentRegionBlock = function(session, line, row) { + var startColumn = line.search(/\s*$/); + var maxRow = session.getLength(); + var startRow = row; + + var re = /^\s*(?:\/\*|\/\/)#(end)?region\b/; + var depth = 1; + while (++row < maxRow) { + line = session.getLine(row); + var m = re.exec(line); + if (!m) continue; + if (m[1]) depth--; + else depth++; + + if (!depth) break; + } + + var endRow = row; + if (endRow > startRow) { + return new Range(startRow, startColumn, endRow, line.length); + } + }; + +}).call(FoldMode.prototype); + +}); + +define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var Range = require("../range").Range; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = JavaScriptHighlightRules; + + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.lineCommentStart = "//"; + this.blockComment = {start: "/*", end: "*/"}; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + var endState = tokenizedLine.state; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start" || state == "no_regex") { + var match = line.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/); + if (match) { + indent += tab; + } + } else if (state == "doc-start") { + if (endState == "start" || endState == "no_regex") { + return ""; + } + var match = line.match(/^\s*(\/?)\*/); + if (match) { + if (match[1]) { + indent += " "; + } + indent += "* "; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker"); + worker.attachToDocument(session.getDocument()); + + worker.on("annotate", function(results) { + session.setAnnotations(results.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + this.$id = "ace/mode/javascript"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); + +define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var XmlHighlightRules = function(normalize) { + + var tagRegex = "[a-zA-Z][-_a-zA-Z0-9]*"; + + this.$rules = { + start : [ + {token : "string.cdata.xml", regex : "<\\!\\[CDATA\\[", next : "cdata"}, + { + token : ["punctuation.xml-decl.xml", "keyword.xml-decl.xml"], + regex : "(<\\?)(xml)(?=[\\s])", next : "xml_decl", caseInsensitive: true + }, + { + token : ["punctuation.instruction.xml", "keyword.instruction.xml"], + regex : "(<\\?)(" + tagRegex + ")", next : "processing_instruction", + }, + {token : "comment.xml", regex : "<\\!--", next : "comment"}, + { + token : ["xml-pe.doctype.xml", "xml-pe.doctype.xml"], + regex : "(<\\!)(DOCTYPE)(?=[\\s])", next : "doctype", caseInsensitive: true + }, + {include : "tag"}, + {token : "text.end-tag-open.xml", regex: "", + next : "start" + }], + + processing_instruction : [ + {token : "punctuation.instruction.xml", regex : "\\?>", next : "start"}, + {defaultToken : "instruction.xml"} + ], + + doctype : [ + {include : "whitespace"}, + {include : "string"}, + {token : "xml-pe.doctype.xml", regex : ">", next : "start"}, + {token : "xml-pe.xml", regex : "[-_a-zA-Z0-9:]+"}, + {token : "punctuation.int-subset", regex : "\\[", push : "int_subset"} + ], + + int_subset : [{ + token : "text.xml", + regex : "\\s+" + }, { + token: "punctuation.int-subset.xml", + regex: "]", + next: "pop" + }, { + token : ["punctuation.markup-decl.xml", "keyword.markup-decl.xml"], + regex : "(<\\!)(" + tagRegex + ")", + push : [{ + token : "text", + regex : "\\s+" + }, + { + token : "punctuation.markup-decl.xml", + regex : ">", + next : "pop" + }, + {include : "string"}] + }], + + cdata : [ + {token : "string.cdata.xml", regex : "\\]\\]>", next : "start"}, + {token : "text.xml", regex : "\\s+"}, + {token : "text.xml", regex : "(?:[^\\]]|\\](?!\\]>))+"} + ], + + comment : [ + {token : "comment.xml", regex : "-->", next : "start"}, + {defaultToken : "comment.xml"} + ], + + reference : [{ + token : "constant.language.escape.reference.xml", + regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)" + }], + + attr_reference : [{ + token : "constant.language.escape.reference.attribute-value.xml", + regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)" + }], + + tag : [{ + token : ["meta.tag.punctuation.tag-open.xml", "meta.tag.punctuation.end-tag-open.xml", "meta.tag.tag-name.xml"], + regex : "(?:(<)|(", next : "start"} + ] + }], + + tag_whitespace : [ + {token : "text.tag-whitespace.xml", regex : "\\s+"} + ], + whitespace : [ + {token : "text.whitespace.xml", regex : "\\s+"} + ], + string: [{ + token : "string.xml", + regex : "'", + push : [ + {token : "string.xml", regex: "'", next: "pop"}, + {defaultToken : "string.xml"} + ] + }, { + token : "string.xml", + regex : '"', + push : [ + {token : "string.xml", regex: '"', next: "pop"}, + {defaultToken : "string.xml"} + ] + }], + + attributes: [{ + token : "entity.other.attribute-name.xml", + regex : "(?:" + tagRegex + ":)?" + tagRegex + "" + }, { + token : "keyword.operator.attribute-equals.xml", + regex : "=" + }, { + include: "tag_whitespace" + }, { + include: "attribute_value" + }], + + attribute_value: [{ + token : "string.attribute-value.xml", + regex : "'", + push : [ + {token : "string.attribute-value.xml", regex: "'", next: "pop"}, + {include : "attr_reference"}, + {defaultToken : "string.attribute-value.xml"} + ] + }, { + token : "string.attribute-value.xml", + regex : '"', + push : [ + {token : "string.attribute-value.xml", regex: '"', next: "pop"}, + {include : "attr_reference"}, + {defaultToken : "string.attribute-value.xml"} + ] + }] + }; + + if (this.constructor === XmlHighlightRules) + this.normalizeRules(); +}; + + +(function() { + + this.embedTagRules = function(HighlightRules, prefix, tag){ + this.$rules.tag.unshift({ + token : ["meta.tag.punctuation.tag-open.xml", "meta.tag." + tag + ".tag-name.xml"], + regex : "(<)(" + tag + "(?=\\s|>|$))", + next: [ + {include : "attributes"}, + {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>", next : prefix + "start"} + ] + }); + + this.$rules[tag + "-end"] = [ + {include : "attributes"}, + {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>", next: "start", + onMatch : function(value, currentState, stack) { + stack.splice(0); + return this.token; + }} + ] + + this.embedRules(HighlightRules, prefix, [{ + token: ["meta.tag.punctuation.end-tag-open.xml", "meta.tag." + tag + ".tag-name.xml"], + regex : "(|$))", + next: tag + "-end" + }, { + token: "string.cdata.xml", + regex : "<\\!\\[CDATA\\[" + }, { + token: "string.cdata.xml", + regex : "\\]\\]>" + }]); + }; + +}).call(TextHighlightRules.prototype); + +oop.inherits(XmlHighlightRules, TextHighlightRules); + +exports.XmlHighlightRules = XmlHighlightRules; +}); + +define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); + +function is(token, type) { + return token.type.lastIndexOf(type + ".xml") > -1; +} + +var XmlBehaviour = function () { + + this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { + if (text == '"' || text == "'") { + var quote = text; + var selected = session.doc.getTextRange(editor.getSelectionRange()); + if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { + return { + text: quote + selected + quote, + selection: false + }; + } + + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + + if (rightChar == quote && (is(token, "attribute-value") || is(token, "string"))) { + return { + text: "", + selection: [1, 1] + }; + } + + if (!token) + token = iterator.stepBackward(); + + if (!token) + return; + + while (is(token, "tag-whitespace") || is(token, "whitespace")) { + token = iterator.stepBackward(); + } + var rightSpace = !rightChar || rightChar.match(/\s/); + if (is(token, "attribute-equals") && (rightSpace || rightChar == '>') || (is(token, "decl-attribute-equals") && (rightSpace || rightChar == '?'))) { + return { + text: quote + quote, + selection: [1, 1] + }; + } + } + }); + + this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + + this.add("autoclosing", "insertion", function (state, action, editor, session, text) { + if (text == '>') { + var position = editor.getCursorPosition(); + var iterator = new TokenIterator(session, position.row, position.column); + var token = iterator.getCurrentToken() || iterator.stepBackward(); + if (!token || !(is(token, "tag-name") || is(token, "tag-whitespace") || is(token, "attribute-name") || is(token, "attribute-equals") || is(token, "attribute-value"))) + return; + if (is(token, "reference.attribute-value")) + return; + if (is(token, "attribute-value")) { + var firstChar = token.value.charAt(0); + if (firstChar == '"' || firstChar == "'") { + var lastChar = token.value.charAt(token.value.length - 1); + var tokenEnd = iterator.getCurrentTokenColumn() + token.value.length; + if (tokenEnd > position.column || tokenEnd == position.column && firstChar != lastChar) + return; + } + } + while (!is(token, "tag-name")) { + token = iterator.stepBackward(); + } + + var tokenRow = iterator.getCurrentTokenRow(); + var tokenColumn = iterator.getCurrentTokenColumn(); + if (is(iterator.stepBackward(), "end-tag-open")) + return; + + var element = token.value; + if (tokenRow == position.row) + element = element.substring(0, position.column - tokenColumn); + + if (this.voidElements.hasOwnProperty(element.toLowerCase())) + return; + + return { + text: ">" + "", + selection: [1, 1] + }; + } + }); + + this.add("autoindent", "insertion", function (state, action, editor, session, text) { + if (text == "\n") { + var cursor = editor.getCursorPosition(); + var line = session.getLine(cursor.row); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + + if (token && token.type.indexOf("tag-close") !== -1) { + if (token.value == "/>") + return; + while (token && token.type.indexOf("tag-name") === -1) { + token = iterator.stepBackward(); + } + + if (!token) { + return; + } + + var tag = token.value; + var row = iterator.getCurrentTokenRow(); + token = iterator.stepBackward(); + if (!token || token.type.indexOf("end-tag") !== -1) { + return; + } + + if (this.voidElements && !this.voidElements[tag]) { + var nextToken = session.getTokenAt(cursor.row, cursor.column+1); + var line = session.getLine(row); + var nextIndent = this.$getIndent(line); + var indent = nextIndent + session.getTabString(); + + if (nextToken && nextToken.value === " -1; +} + +(function() { + + this.getFoldWidget = function(session, foldStyle, row) { + var tag = this._getFirstTagInLine(session, row); + + if (!tag) + return ""; + + if (tag.closing || (!tag.tagName && tag.selfClosing)) + return foldStyle == "markbeginend" ? "end" : ""; + + if (!tag.tagName || tag.selfClosing || this.voidElements.hasOwnProperty(tag.tagName.toLowerCase())) + return ""; + + if (this._findEndTagInLine(session, row, tag.tagName, tag.end.column)) + return ""; + + return "start"; + }; + this._getFirstTagInLine = function(session, row) { + var tokens = session.getTokens(row); + var tag = new Tag(); + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (is(token, "tag-open")) { + tag.end.column = tag.start.column + token.value.length; + tag.closing = is(token, "end-tag-open"); + token = tokens[++i]; + if (!token) + return null; + tag.tagName = token.value; + tag.end.column += token.value.length; + for (i++; i < tokens.length; i++) { + token = tokens[i]; + tag.end.column += token.value.length; + if (is(token, "tag-close")) { + tag.selfClosing = token.value == '/>'; + break; + } + } + return tag; + } else if (is(token, "tag-close")) { + tag.selfClosing = token.value == '/>'; + return tag; + } + tag.start.column += token.value.length; + } + + return null; + }; + + this._findEndTagInLine = function(session, row, tagName, startColumn) { + var tokens = session.getTokens(row); + var column = 0; + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + column += token.value.length; + if (column < startColumn) + continue; + if (is(token, "end-tag-open")) { + token = tokens[i + 1]; + if (token && token.value == tagName) + return true; + } + } + return false; + }; + this._readTagForward = function(iterator) { + var token = iterator.getCurrentToken(); + if (!token) + return null; + + var tag = new Tag(); + do { + if (is(token, "tag-open")) { + tag.closing = is(token, "end-tag-open"); + tag.start.row = iterator.getCurrentTokenRow(); + tag.start.column = iterator.getCurrentTokenColumn(); + } else if (is(token, "tag-name")) { + tag.tagName = token.value; + } else if (is(token, "tag-close")) { + tag.selfClosing = token.value == "/>"; + tag.end.row = iterator.getCurrentTokenRow(); + tag.end.column = iterator.getCurrentTokenColumn() + token.value.length; + iterator.stepForward(); + return tag; + } + } while(token = iterator.stepForward()); + + return null; + }; + + this._readTagBackward = function(iterator) { + var token = iterator.getCurrentToken(); + if (!token) + return null; + + var tag = new Tag(); + do { + if (is(token, "tag-open")) { + tag.closing = is(token, "end-tag-open"); + tag.start.row = iterator.getCurrentTokenRow(); + tag.start.column = iterator.getCurrentTokenColumn(); + iterator.stepBackward(); + return tag; + } else if (is(token, "tag-name")) { + tag.tagName = token.value; + } else if (is(token, "tag-close")) { + tag.selfClosing = token.value == "/>"; + tag.end.row = iterator.getCurrentTokenRow(); + tag.end.column = iterator.getCurrentTokenColumn() + token.value.length; + } + } while(token = iterator.stepBackward()); + + return null; + }; + + this._pop = function(stack, tag) { + while (stack.length) { + + var top = stack[stack.length-1]; + if (!tag || top.tagName == tag.tagName) { + return stack.pop(); + } + else if (this.optionalEndTags.hasOwnProperty(top.tagName)) { + stack.pop(); + continue; + } else { + return null; + } + } + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var firstTag = this._getFirstTagInLine(session, row); + + if (!firstTag) + return null; + + var isBackward = firstTag.closing || firstTag.selfClosing; + var stack = []; + var tag; + + if (!isBackward) { + var iterator = new TokenIterator(session, row, firstTag.start.column); + var start = { + row: row, + column: firstTag.start.column + firstTag.tagName.length + 2 + }; + if (firstTag.start.row == firstTag.end.row) + start.column = firstTag.end.column; + while (tag = this._readTagForward(iterator)) { + if (tag.selfClosing) { + if (!stack.length) { + tag.start.column += tag.tagName.length + 2; + tag.end.column -= 2; + return Range.fromPoints(tag.start, tag.end); + } else + continue; + } + + if (tag.closing) { + this._pop(stack, tag); + if (stack.length == 0) + return Range.fromPoints(start, tag.start); + } + else { + stack.push(tag); + } + } + } + else { + var iterator = new TokenIterator(session, row, firstTag.end.column); + var end = { + row: row, + column: firstTag.start.column + }; + + while (tag = this._readTagBackward(iterator)) { + if (tag.selfClosing) { + if (!stack.length) { + tag.start.column += tag.tagName.length + 2; + tag.end.column -= 2; + return Range.fromPoints(tag.start, tag.end); + } else + continue; + } + + if (!tag.closing) { + this._pop(stack, tag); + if (stack.length == 0) { + tag.start.column += tag.tagName.length + 2; + if (tag.start.row == tag.end.row && tag.start.column < tag.end.column) + tag.start.column = tag.end.column; + return Range.fromPoints(tag.start, end); + } + } + else { + stack.push(tag); + } + } + } + + }; + +}).call(FoldMode.prototype); + +}); + +define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml","ace/worker/worker_client"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var TextMode = require("./text").Mode; +var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules; +var XmlBehaviour = require("./behaviour/xml").XmlBehaviour; +var XmlFoldMode = require("./folding/xml").FoldMode; +var WorkerClient = require("../worker/worker_client").WorkerClient; + +var Mode = function() { + this.HighlightRules = XmlHighlightRules; + this.$behaviour = new XmlBehaviour(); + this.foldingRules = new XmlFoldMode(); +}; + +oop.inherits(Mode, TextMode); + +(function() { + + this.voidElements = lang.arrayToMap([]); + + this.blockComment = {start: ""}; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/xml_worker", "Worker"); + worker.attachToDocument(session.getDocument()); + + worker.on("error", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + this.$id = "ace/mode/xml"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); + +define("ace/mode/css_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; +var supportType = exports.supportType = "animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|pointer-events|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index"; +var supportFunction = exports.supportFunction = "rgb|rgba|url|attr|counter|counters"; +var supportConstant = exports.supportConstant = "absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero"; +var supportConstantColor = exports.supportConstantColor = "aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow"; +var supportConstantFonts = exports.supportConstantFonts = "arial|century|comic|courier|cursive|fantasy|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace"; + +var numRe = exports.numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))"; +var pseudoElements = exports.pseudoElements = "(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b"; +var pseudoClasses = exports.pseudoClasses = "(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b"; + +var CssHighlightRules = function() { + + var keywordMapper = this.createKeywordMapper({ + "support.function": supportFunction, + "support.constant": supportConstant, + "support.type": supportType, + "support.constant.color": supportConstantColor, + "support.constant.fonts": supportConstantFonts + }, "text", true); + + this.$rules = { + "start" : [{ + token : "comment", // multi line comment + regex : "\\/\\*", + push : "comment" + }, { + token: "paren.lparen", + regex: "\\{", + push: "ruleset" + }, { + token: "string", + regex: "@.*?{", + push: "media" + }, { + token: "keyword", + regex: "#[a-z0-9-_]+" + }, { + token: "variable", + regex: "\\.[a-z0-9-_]+" + }, { + token: "string", + regex: ":[a-z0-9-_]+" + }, { + token: "constant", + regex: "[a-z0-9-_]+" + }, { + caseInsensitive: true + }], + + "media" : [{ + token : "comment", // multi line comment + regex : "\\/\\*", + push : "comment" + }, { + token: "paren.lparen", + regex: "\\{", + push: "ruleset" + }, { + token: "string", + regex: "\\}", + next: "pop" + }, { + token: "keyword", + regex: "#[a-z0-9-_]+" + }, { + token: "variable", + regex: "\\.[a-z0-9-_]+" + }, { + token: "string", + regex: ":[a-z0-9-_]+" + }, { + token: "constant", + regex: "[a-z0-9-_]+" + }, { + caseInsensitive: true + }], + + "comment" : [{ + token : "comment", + regex : "\\*\\/", + next : "pop" + }, { + defaultToken : "comment" + }], + + "ruleset" : [ + { + token : "paren.rparen", + regex : "\\}", + next: "pop" + }, { + token : "comment", // multi line comment + regex : "\\/\\*", + push : "comment" + }, { + token : "string", // single line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + }, { + token : "string", // single line + regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" + }, { + token : ["constant.numeric", "keyword"], + regex : "(" + numRe + ")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)" + }, { + token : "constant.numeric", + regex : numRe + }, { + token : "constant.numeric", // hex6 color + regex : "#[a-f0-9]{6}" + }, { + token : "constant.numeric", // hex3 color + regex : "#[a-f0-9]{3}" + }, { + token : ["punctuation", "entity.other.attribute-name.pseudo-element.css"], + regex : pseudoElements + }, { + token : ["punctuation", "entity.other.attribute-name.pseudo-class.css"], + regex : pseudoClasses + }, { + token : ["support.function", "string", "support.function"], + regex : "(url\\()(.*)(\\))" + }, { + token : keywordMapper, + regex : "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*" + }, { + caseInsensitive: true + }] + }; + + this.normalizeRules(); +}; + +oop.inherits(CssHighlightRules, TextHighlightRules); + +exports.CssHighlightRules = CssHighlightRules; + +}); + +define("ace/mode/behaviour/css",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/mode/behaviour/cstyle","ace/token_iterator"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var CstyleBehaviour = require("./cstyle").CstyleBehaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; + +var CssBehaviour = function () { + + this.inherit(CstyleBehaviour); + + this.add("colon", "insertion", function (state, action, editor, session, text) { + if (text === ':') { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + if (token && token.value.match(/\s+/)) { + token = iterator.stepBackward(); + } + if (token && token.type === 'support.type') { + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === ':') { + return { + text: '', + selection: [1, 1] + } + } + if (!line.substring(cursor.column).match(/^\s*;/)) { + return { + text: ':;', + selection: [1, 1] + } + } + } + } + }); + + this.add("colon", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected === ':') { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + if (token && token.value.match(/\s+/)) { + token = iterator.stepBackward(); + } + if (token && token.type === 'support.type') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar === ';') { + range.end.column ++; + return range; + } + } + } + }); + + this.add("semicolon", "insertion", function (state, action, editor, session, text) { + if (text === ';') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === ';') { + return { + text: '', + selection: [1, 1] + } + } + } + }); + +} +oop.inherits(CssBehaviour, CstyleBehaviour); + +exports.CssBehaviour = CssBehaviour; +}); + +define("ace/mode/css",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/css_highlight_rules","ace/mode/matching_brace_outdent","ace/worker/worker_client","ace/mode/behaviour/css","ace/mode/folding/cstyle"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var CssBehaviour = require("./behaviour/css").CssBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = CssHighlightRules; + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CssBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.foldingRules = "cStyle"; + this.blockComment = {start: "/*", end: "*/"}; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + var tokens = this.getTokenizer().getLineTokens(line, state).tokens; + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + var match = line.match(/^.*\{\s*$/); + if (match) { + indent += tab; + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/css_worker", "Worker"); + worker.attachToDocument(session.getDocument()); + + worker.on("annotate", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + this.$id = "ace/mode/css"; +}).call(Mode.prototype); + +exports.Mode = Mode; + +}); + +define("ace/mode/html_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/css_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules; +var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; +var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules; + +var tagMap = lang.createMap({ + a : 'anchor', + button : 'form', + form : 'form', + img : 'image', + input : 'form', + label : 'form', + option : 'form', + script : 'script', + select : 'form', + textarea : 'form', + style : 'style', + table : 'table', + tbody : 'table', + td : 'table', + tfoot : 'table', + th : 'table', + tr : 'table' +}); + +var HtmlHighlightRules = function() { + XmlHighlightRules.call(this); + + this.addRules({ + attributes: [{ + include : "tag_whitespace" + }, { + token : "entity.other.attribute-name.xml", + regex : "[-_a-zA-Z0-9:]+" + }, { + token : "keyword.operator.attribute-equals.xml", + regex : "=", + push : [{ + include: "tag_whitespace" + }, { + token : "string.unquoted.attribute-value.html", + regex : "[^<>='\"`\\s]+", + next : "pop" + }, { + token : "empty", + regex : "", + next : "pop" + }] + }, { + include : "attribute_value" + }], + tag: [{ + token : function(start, tag) { + var group = tagMap[tag]; + return ["meta.tag.punctuation." + (start == "<" ? "" : "end-") + "tag-open.xml", + "meta.tag" + (group ? "." + group : "") + ".tag-name.xml"]; + }, + regex : "(", next : "start"} + ], + }); + + this.embedTagRules(CssHighlightRules, "css-", "style"); + this.embedTagRules(JavaScriptHighlightRules, "js-", "script"); + + if (this.constructor === HtmlHighlightRules) + this.normalizeRules(); +}; + +oop.inherits(HtmlHighlightRules, XmlHighlightRules); + +exports.HtmlHighlightRules = HtmlHighlightRules; +}); + +define("ace/mode/folding/mixed",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var BaseFoldMode = require("./fold_mode").FoldMode; + +var FoldMode = exports.FoldMode = function(defaultMode, subModes) { + this.defaultMode = defaultMode; + this.subModes = subModes; +}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + + this.$getMode = function(state) { + if (typeof state != "string") + state = state[0]; + for (var key in this.subModes) { + if (state.indexOf(key) === 0) + return this.subModes[key]; + } + return null; + }; + + this.$tryMode = function(state, session, foldStyle, row) { + var mode = this.$getMode(state); + return (mode ? mode.getFoldWidget(session, foldStyle, row) : ""); + }; + + this.getFoldWidget = function(session, foldStyle, row) { + return ( + this.$tryMode(session.getState(row-1), session, foldStyle, row) || + this.$tryMode(session.getState(row), session, foldStyle, row) || + this.defaultMode.getFoldWidget(session, foldStyle, row) + ); + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var mode = this.$getMode(session.getState(row-1)); + + if (!mode || !mode.getFoldWidget(session, foldStyle, row)) + mode = this.$getMode(session.getState(row)); + + if (!mode || !mode.getFoldWidget(session, foldStyle, row)) + mode = this.defaultMode; + + return mode.getFoldWidgetRange(session, foldStyle, row); + }; + +}).call(FoldMode.prototype); + +}); + +define("ace/mode/folding/html",["require","exports","module","ace/lib/oop","ace/mode/folding/mixed","ace/mode/folding/xml","ace/mode/folding/cstyle"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var MixedFoldMode = require("./mixed").FoldMode; +var XmlFoldMode = require("./xml").FoldMode; +var CStyleFoldMode = require("./cstyle").FoldMode; + +var FoldMode = exports.FoldMode = function(voidElements, optionalTags) { + MixedFoldMode.call(this, new XmlFoldMode(voidElements, optionalTags), { + "js-": new CStyleFoldMode(), + "css-": new CStyleFoldMode() + }); +}; + +oop.inherits(FoldMode, MixedFoldMode); + +}); + +define("ace/mode/html_completions",["require","exports","module","ace/token_iterator"], function(require, exports, module) { +"use strict"; + +var TokenIterator = require("../token_iterator").TokenIterator; + +var commonAttributes = [ + "accesskey", + "class", + "contenteditable", + "contextmenu", + "dir", + "draggable", + "dropzone", + "hidden", + "id", + "inert", + "itemid", + "itemprop", + "itemref", + "itemscope", + "itemtype", + "lang", + "spellcheck", + "style", + "tabindex", + "title", + "translate" +]; + +var eventAttributes = [ + "onabort", + "onblur", + "oncancel", + "oncanplay", + "oncanplaythrough", + "onchange", + "onclick", + "onclose", + "oncontextmenu", + "oncuechange", + "ondblclick", + "ondrag", + "ondragend", + "ondragenter", + "ondragleave", + "ondragover", + "ondragstart", + "ondrop", + "ondurationchange", + "onemptied", + "onended", + "onerror", + "onfocus", + "oninput", + "oninvalid", + "onkeydown", + "onkeypress", + "onkeyup", + "onload", + "onloadeddata", + "onloadedmetadata", + "onloadstart", + "onmousedown", + "onmousemove", + "onmouseout", + "onmouseover", + "onmouseup", + "onmousewheel", + "onpause", + "onplay", + "onplaying", + "onprogress", + "onratechange", + "onreset", + "onscroll", + "onseeked", + "onseeking", + "onselect", + "onshow", + "onstalled", + "onsubmit", + "onsuspend", + "ontimeupdate", + "onvolumechange", + "onwaiting" +]; + +var globalAttributes = commonAttributes.concat(eventAttributes); + +var attributeMap = { + "html": ["manifest"], + "head": [], + "title": [], + "base": ["href", "target"], + "link": ["href", "hreflang", "rel", "media", "type", "sizes"], + "meta": ["http-equiv", "name", "content", "charset"], + "style": ["type", "media", "scoped"], + "script": ["charset", "type", "src", "defer", "async"], + "noscript": ["href"], + "body": ["onafterprint", "onbeforeprint", "onbeforeunload", "onhashchange", "onmessage", "onoffline", "onpopstate", "onredo", "onresize", "onstorage", "onundo", "onunload"], + "section": [], + "nav": [], + "article": ["pubdate"], + "aside": [], + "h1": [], + "h2": [], + "h3": [], + "h4": [], + "h5": [], + "h6": [], + "header": [], + "footer": [], + "address": [], + "main": [], + "p": [], + "hr": [], + "pre": [], + "blockquote": ["cite"], + "ol": ["start", "reversed"], + "ul": [], + "li": ["value"], + "dl": [], + "dt": [], + "dd": [], + "figure": [], + "figcaption": [], + "div": [], + "a": ["href", "target", "ping", "rel", "media", "hreflang", "type"], + "em": [], + "strong": [], + "small": [], + "s": [], + "cite": [], + "q": ["cite"], + "dfn": [], + "abbr": [], + "data": [], + "time": ["datetime"], + "code": [], + "var": [], + "samp": [], + "kbd": [], + "sub": [], + "sup": [], + "i": [], + "b": [], + "u": [], + "mark": [], + "ruby": [], + "rt": [], + "rp": [], + "bdi": [], + "bdo": [], + "span": [], + "br": [], + "wbr": [], + "ins": ["cite", "datetime"], + "del": ["cite", "datetime"], + "img": ["alt", "src", "height", "width", "usemap", "ismap"], + "iframe": ["name", "src", "height", "width", "sandbox", "seamless"], + "embed": ["src", "height", "width", "type"], + "object": ["param", "data", "type", "height" , "width", "usemap", "name", "form", "classid"], + "param": ["name", "value"], + "video": ["src", "autobuffer", "autoplay", "loop", "controls", "width", "height", "poster"], + "audio": ["src", "autobuffer", "autoplay", "loop", "controls"], + "source": ["src", "type", "media"], + "track": ["kind", "src", "srclang", "label", "default"], + "canvas": ["width", "height"], + "map": ["name"], + "area": ["shape", "coords", "href", "hreflang", "alt", "target", "media", "rel", "ping", "type"], + "svg": [], + "math": [], + "table": ["summary"], + "caption": [], + "colgroup": ["span"], + "col": ["span"], + "tbody": [], + "thead": [], + "tfoot": [], + "tr": [], + "td": ["headers", "rowspan", "colspan"], + "th": ["headers", "rowspan", "colspan", "scope"], + "form": ["accept-charset", "action", "autocomplete", "enctype", "method", "name", "novalidate", "target"], + "fieldset": ["disabled", "form", "name"], + "legend": [], + "label": ["form", "for"], + "input": ["type", "accept", "alt", "autocomplete", "checked", "disabled", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "height", "list", "max", "maxlength", "min", "multiple", "pattern", "placeholder", "readonly", "required", "size", "src", "step", "width", "files", "value"], + "button": ["autofocus", "disabled", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "name", "value", "type"], + "select": ["autofocus", "disabled", "form", "multiple", "name", "size"], + "datalist": [], + "optgroup": ["disabled", "label"], + "option": ["disabled", "selected", "label", "value"], + "textarea": ["autofocus", "disabled", "form", "maxlength", "name", "placeholder", "readonly", "required", "rows", "cols", "wrap"], + "keygen": ["autofocus", "challenge", "disabled", "form", "keytype", "name"], + "output": ["for", "form", "name"], + "progress": ["value", "max"], + "meter": ["value", "min", "max", "low", "high", "optimum"], + "details": ["open"], + "summary": [], + "command": ["type", "label", "icon", "disabled", "checked", "radiogroup", "command"], + "menu": ["type", "label"], + "dialog": ["open"] +}; + +var elements = Object.keys(attributeMap); + +function is(token, type) { + return token.type.lastIndexOf(type + ".xml") > -1; +} + +function findTagName(session, pos) { + var iterator = new TokenIterator(session, pos.row, pos.column); + var token = iterator.getCurrentToken(); + while (token && !is(token, "tag-name")){ + token = iterator.stepBackward(); + } + if (token) + return token.value; +} + +var HtmlCompletions = function() { + +}; + +(function() { + + this.getCompletions = function(state, session, pos, prefix) { + var token = session.getTokenAt(pos.row, pos.column); + + if (!token) + return []; + if (is(token, "tag-name") || is(token, "tag-open") || is(token, "end-tag-open")) + return this.getTagCompletions(state, session, pos, prefix); + if (is(token, "tag-whitespace") || is(token, "attribute-name")) + return this.getAttributeCompetions(state, session, pos, prefix); + + return []; + }; + + this.getTagCompletions = function(state, session, pos, prefix) { + return elements.map(function(element){ + return { + value: element, + meta: "tag", + score: Number.MAX_VALUE + }; + }); + }; + + this.getAttributeCompetions = function(state, session, pos, prefix) { + var tagName = findTagName(session, pos); + if (!tagName) + return []; + var attributes = globalAttributes; + if (tagName in attributeMap) { + attributes = attributes.concat(attributeMap[tagName]); + } + return attributes.map(function(attribute){ + return { + caption: attribute, + snippet: attribute + '="$0"', + meta: "attribute", + score: Number.MAX_VALUE + }; + }); + }; + +}).call(HtmlCompletions.prototype); + +exports.HtmlCompletions = HtmlCompletions; +}); + +define("ace/mode/html",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text","ace/mode/javascript","ace/mode/css","ace/mode/html_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/html","ace/mode/html_completions","ace/worker/worker_client"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var TextMode = require("./text").Mode; +var JavaScriptMode = require("./javascript").Mode; +var CssMode = require("./css").Mode; +var HtmlHighlightRules = require("./html_highlight_rules").HtmlHighlightRules; +var XmlBehaviour = require("./behaviour/xml").XmlBehaviour; +var HtmlFoldMode = require("./folding/html").FoldMode; +var HtmlCompletions = require("./html_completions").HtmlCompletions; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var voidElements = ["area", "base", "br", "col", "embed", "hr", "img", "input", "keygen", "link", "meta", "menuitem", "param", "source", "track", "wbr"]; +var optionalEndTags = ["li", "dt", "dd", "p", "rt", "rp", "optgroup", "option", "colgroup", "td", "th"]; + +var Mode = function(options) { + this.fragmentContext = options && options.fragmentContext; + this.HighlightRules = HtmlHighlightRules; + this.$behaviour = new XmlBehaviour(); + this.$completer = new HtmlCompletions(); + + this.createModeDelegates({ + "js-": JavaScriptMode, + "css-": CssMode + }); + + this.foldingRules = new HtmlFoldMode(this.voidElements, lang.arrayToMap(optionalEndTags)); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.blockComment = {start: ""}; + + this.voidElements = lang.arrayToMap(voidElements); + + this.getNextLineIndent = function(state, line, tab) { + return this.$getIndent(line); + }; + + this.checkOutdent = function(state, line, input) { + return false; + }; + + this.getCompletions = function(state, session, pos, prefix) { + return this.$completer.getCompletions(state, session, pos, prefix); + }; + + this.createWorker = function(session) { + if (this.constructor != Mode) + return; + var worker = new WorkerClient(["ace"], "ace/mode/html_worker", "Worker"); + worker.attachToDocument(session.getDocument()); + + if (this.fragmentContext) + worker.call("setOptions", [{context: this.fragmentContext}]); + + worker.on("error", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + this.$id = "ace/mode/html"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); + +define("ace/mode/markdown_highlight_rules",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules","ace/mode/javascript_highlight_rules","ace/mode/xml_highlight_rules","ace/mode/html_highlight_rules","ace/mode/css_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; +var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; +var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules; +var HtmlHighlightRules = require("./html_highlight_rules").HtmlHighlightRules; +var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules; + +var escaped = function(ch) { + return "(?:[^" + lang.escapeRegExp(ch) + "\\\\]|\\\\.)*"; +} + +function github_embed(tag, prefix) { + return { // Github style block + token : "support.function", + regex : "^\\s*```" + tag + "\\s*$", + push : prefix + "start" + }; +} + +var MarkdownHighlightRules = function() { + HtmlHighlightRules.call(this); + + this.$rules["start"].unshift({ + token : "empty_line", + regex : '^$', + next: "allowBlock" + }, { // h1 + token: "markup.heading.1", + regex: "^=+(?=\\s*$)" + }, { // h2 + token: "markup.heading.2", + regex: "^\\-+(?=\\s*$)" + }, { + token : function(value) { + return "markup.heading." + value.length; + }, + regex : /^#{1,6}(?=\s*[^ #]|\s+#.)/, + next : "header" + }, + github_embed("(?:javascript|js)", "jscode-"), + github_embed("xml", "xmlcode-"), + github_embed("html", "htmlcode-"), + github_embed("css", "csscode-"), + { // Github style block + token : "support.function", + regex : "^\\s*```\\s*\\S*(?:{.*?\\})?\\s*$", + next : "githubblock" + }, { // block quote + token : "string.blockquote", + regex : "^\\s*>\\s*(?:[*+-]|\\d+\\.)?\\s+", + next : "blockquote" + }, { // HR * - _ + token : "constant", + regex : "^ {0,2}(?:(?: ?\\* ?){3,}|(?: ?\\- ?){3,}|(?: ?\\_ ?){3,})\\s*$", + next: "allowBlock" + }, { // list + token : "markup.list", + regex : "^\\s{0,3}(?:[*+-]|\\d+\\.)\\s+", + next : "listblock-start" + }, { + include : "basic" + }); + + this.addRules({ + "basic" : [{ + token : "constant.language.escape", + regex : /\\[\\`*_{}\[\]()#+\-.!]/ + }, { // code span ` + token : "support.function", + regex : "(`+)(.*?[^`])(\\1)" + }, { // reference + token : ["text", "constant", "text", "url", "string", "text"], + regex : "^([ ]{0,3}\\[)([^\\]]+)(\\]:\\s*)([^ ]+)(\\s*(?:[\"][^\"]+[\"])?(\\s*))$" + }, { // link by reference + token : ["text", "string", "text", "constant", "text"], + regex : "(\\[)(" + escaped("]") + ")(\\]\s*\\[)("+ escaped("]") + ")(\\])" + }, { // link by url + token : ["text", "string", "text", "markup.underline", "string", "text"], + regex : "(\\[)(" + // [ + escaped("]") + // link text + ")(\\]\\()"+ // ]( + '((?:[^\\)\\s\\\\]|\\\\.|\\s(?=[^"]))*)' + // href + '(\\s*"' + escaped('"') + '"\\s*)?' + // "title" + "(\\))" // ) + }, { // strong ** __ + token : "string.strong", + regex : "([*]{2}|[_]{2}(?=\\S))(.*?\\S[*_]*)(\\1)" + }, { // emphasis * _ + token : "string.emphasis", + regex : "([*]|[_](?=\\S))(.*?\\S[*_]*)(\\1)" + }, { // + token : ["text", "url", "text"], + regex : "(<)("+ + "(?:https?|ftp|dict):[^'\">\\s]+"+ + "|"+ + "(?:mailto:)?[-.\\w]+\\@[-a-z0-9]+(?:\\.[-a-z0-9]+)*\\.[a-z]+"+ + ")(>)" + }], + "allowBlock": [ + {token : "support.function", regex : "^ {4}.+", next : "allowBlock"}, + {token : "empty", regex : "", next : "start"} + ], + + "header" : [{ + regex: "$", + next : "start" + }, { + include: "basic" + }, { + defaultToken : "heading" + } ], + + "listblock-start" : [{ + token : "support.variable", + regex : /(?:\[[ x]\])?/, + next : "listblock" + }], + + "listblock" : [ { // Lists only escape on completely blank lines. + token : "empty_line", + regex : "^$", + next : "start" + }, { // list + token : "markup.list", + regex : "^\\s{0,3}(?:[*+-]|\\d+\\.)\\s+", + next : "listblock-start" + }, { + include : "basic", noEscape: true + }, { // Github style block + token : "support.function", + regex : "^\\s*```\\s*[a-zA-Z]*(?:{.*?\\})?\\s*$", + next : "githubblock" + }, { + defaultToken : "list" //do not use markup.list to allow stling leading `*` differntly + } ], + + "blockquote" : [ { // Blockquotes only escape on blank lines. + token : "empty_line", + regex : "^\\s*$", + next : "start" + }, { // block quote + token : "string.blockquote", + regex : "^\\s*>\\s*(?:[*+-]|\\d+\\.)?\\s+", + next : "blockquote" + }, { + include : "basic", noEscape: true + }, { + defaultToken : "string.blockquote" + } ], + + "githubblock" : [ { + token : "support.function", + regex : "^\\s*```", + next : "start" + }, { + token : "support.function", + regex : ".+" + } ] + }); + + this.embedRules(JavaScriptHighlightRules, "jscode-", [{ + token : "support.function", + regex : "^\\s*```", + next : "pop" + }]); + + this.embedRules(HtmlHighlightRules, "htmlcode-", [{ + token : "support.function", + regex : "^\\s*```", + next : "pop" + }]); + + this.embedRules(CssHighlightRules, "csscode-", [{ + token : "support.function", + regex : "^\\s*```", + next : "pop" + }]); + + this.embedRules(XmlHighlightRules, "xmlcode-", [{ + token : "support.function", + regex : "^\\s*```", + next : "pop" + }]); + + this.normalizeRules(); +}; +oop.inherits(MarkdownHighlightRules, TextHighlightRules); + +exports.MarkdownHighlightRules = MarkdownHighlightRules; +}); + +define("ace/mode/folding/markdown",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var BaseFoldMode = require("./fold_mode").FoldMode; +var Range = require("../../range").Range; + +var FoldMode = exports.FoldMode = function() {}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + this.foldingStartMarker = /^(?:[=-]+\s*$|#{1,6} |`{3})/; + + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + if (!this.foldingStartMarker.test(line)) + return ""; + + if (line[0] == "`") { + if (session.bgTokenizer.getState(row) == "start") + return "end"; + return "start"; + } + + return "start"; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var line = session.getLine(row); + var startColumn = line.length; + var maxRow = session.getLength(); + var startRow = row; + var endRow = row; + if (!line.match(this.foldingStartMarker)) + return; + + if (line[0] == "`") { + if (session.bgTokenizer.getState(row) !== "start") { + while (++row < maxRow) { + line = session.getLine(row); + if (line[0] == "`" & line.substring(0, 3) == "```") + break; + } + return new Range(startRow, startColumn, row, 0); + } else { + while (row -- > 0) { + line = session.getLine(row); + if (line[0] == "`" & line.substring(0, 3) == "```") + break; + } + return new Range(row, line.length, startRow, 0); + } + } + + var token; + function isHeading(row) { + token = session.getTokens(row)[0]; + return token && token.type.lastIndexOf(heading, 0) === 0; + } + + var heading = "markup.heading"; + function getLevel() { + var ch = token.value[0]; + if (ch == "=") return 6; + if (ch == "-") return 5; + return 7 - token.value.search(/[^#]/); + } + + if (isHeading(row)) { + var startHeadingLevel = getLevel(); + while (++row < maxRow) { + if (!isHeading(row)) + continue; + var level = getLevel(); + if (level >= startHeadingLevel) + break; + } + + endRow = row - (!token || ["=", "-"].indexOf(token.value[0]) == -1 ? 1 : 2); + + if (endRow > startRow) { + while (endRow > startRow && /^\s*$/.test(session.getLine(endRow))) + endRow--; + } + + if (endRow > startRow) { + var endColumn = session.getLine(endRow).length; + return new Range(startRow, startColumn, endRow, endColumn); + } + } + }; + +}).call(FoldMode.prototype); + +}); + +define("ace/mode/markdown",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript","ace/mode/xml","ace/mode/html","ace/mode/markdown_highlight_rules","ace/mode/folding/markdown"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var JavaScriptMode = require("./javascript").Mode; +var XmlMode = require("./xml").Mode; +var HtmlMode = require("./html").Mode; +var MarkdownHighlightRules = require("./markdown_highlight_rules").MarkdownHighlightRules; +var MarkdownFoldMode = require("./folding/markdown").FoldMode; + +var Mode = function() { + this.HighlightRules = MarkdownHighlightRules; + + this.createModeDelegates({ + "js-": JavaScriptMode, + "xml-": XmlMode, + "html-": HtmlMode + }); + + this.foldingRules = new MarkdownFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + this.type = "text"; + this.blockComment = {start: ""}; + + this.getNextLineIndent = function(state, line, tab) { + if (state == "listblock") { + var match = /^(\s*)(?:([-+*])|(\d+)\.)(\s+)/.exec(line); + if (!match) + return ""; + var marker = match[2]; + if (!marker) + marker = parseInt(match[3], 10) + 1 + "."; + return match[1] + marker + match[4]; + } else { + return this.$getIndent(line); + } + }; + this.$id = "ace/mode/markdown"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/mode-svg.js b/Patent2Net/media/graph-recipes/app/assets/ace/mode-svg.js new file mode 100644 index 00000000..ceb130a1 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/mode-svg.js @@ -0,0 +1,1802 @@ +define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var XmlHighlightRules = function(normalize) { + + var tagRegex = "[a-zA-Z][-_a-zA-Z0-9]*"; + + this.$rules = { + start : [ + {token : "string.cdata.xml", regex : "<\\!\\[CDATA\\[", next : "cdata"}, + { + token : ["punctuation.xml-decl.xml", "keyword.xml-decl.xml"], + regex : "(<\\?)(xml)(?=[\\s])", next : "xml_decl", caseInsensitive: true + }, + { + token : ["punctuation.instruction.xml", "keyword.instruction.xml"], + regex : "(<\\?)(" + tagRegex + ")", next : "processing_instruction", + }, + {token : "comment.xml", regex : "<\\!--", next : "comment"}, + { + token : ["xml-pe.doctype.xml", "xml-pe.doctype.xml"], + regex : "(<\\!)(DOCTYPE)(?=[\\s])", next : "doctype", caseInsensitive: true + }, + {include : "tag"}, + {token : "text.end-tag-open.xml", regex: "", + next : "start" + }], + + processing_instruction : [ + {token : "punctuation.instruction.xml", regex : "\\?>", next : "start"}, + {defaultToken : "instruction.xml"} + ], + + doctype : [ + {include : "whitespace"}, + {include : "string"}, + {token : "xml-pe.doctype.xml", regex : ">", next : "start"}, + {token : "xml-pe.xml", regex : "[-_a-zA-Z0-9:]+"}, + {token : "punctuation.int-subset", regex : "\\[", push : "int_subset"} + ], + + int_subset : [{ + token : "text.xml", + regex : "\\s+" + }, { + token: "punctuation.int-subset.xml", + regex: "]", + next: "pop" + }, { + token : ["punctuation.markup-decl.xml", "keyword.markup-decl.xml"], + regex : "(<\\!)(" + tagRegex + ")", + push : [{ + token : "text", + regex : "\\s+" + }, + { + token : "punctuation.markup-decl.xml", + regex : ">", + next : "pop" + }, + {include : "string"}] + }], + + cdata : [ + {token : "string.cdata.xml", regex : "\\]\\]>", next : "start"}, + {token : "text.xml", regex : "\\s+"}, + {token : "text.xml", regex : "(?:[^\\]]|\\](?!\\]>))+"} + ], + + comment : [ + {token : "comment.xml", regex : "-->", next : "start"}, + {defaultToken : "comment.xml"} + ], + + reference : [{ + token : "constant.language.escape.reference.xml", + regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)" + }], + + attr_reference : [{ + token : "constant.language.escape.reference.attribute-value.xml", + regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)" + }], + + tag : [{ + token : ["meta.tag.punctuation.tag-open.xml", "meta.tag.punctuation.end-tag-open.xml", "meta.tag.tag-name.xml"], + regex : "(?:(<)|(", next : "start"} + ] + }], + + tag_whitespace : [ + {token : "text.tag-whitespace.xml", regex : "\\s+"} + ], + whitespace : [ + {token : "text.whitespace.xml", regex : "\\s+"} + ], + string: [{ + token : "string.xml", + regex : "'", + push : [ + {token : "string.xml", regex: "'", next: "pop"}, + {defaultToken : "string.xml"} + ] + }, { + token : "string.xml", + regex : '"', + push : [ + {token : "string.xml", regex: '"', next: "pop"}, + {defaultToken : "string.xml"} + ] + }], + + attributes: [{ + token : "entity.other.attribute-name.xml", + regex : "(?:" + tagRegex + ":)?" + tagRegex + "" + }, { + token : "keyword.operator.attribute-equals.xml", + regex : "=" + }, { + include: "tag_whitespace" + }, { + include: "attribute_value" + }], + + attribute_value: [{ + token : "string.attribute-value.xml", + regex : "'", + push : [ + {token : "string.attribute-value.xml", regex: "'", next: "pop"}, + {include : "attr_reference"}, + {defaultToken : "string.attribute-value.xml"} + ] + }, { + token : "string.attribute-value.xml", + regex : '"', + push : [ + {token : "string.attribute-value.xml", regex: '"', next: "pop"}, + {include : "attr_reference"}, + {defaultToken : "string.attribute-value.xml"} + ] + }] + }; + + if (this.constructor === XmlHighlightRules) + this.normalizeRules(); +}; + + +(function() { + + this.embedTagRules = function(HighlightRules, prefix, tag){ + this.$rules.tag.unshift({ + token : ["meta.tag.punctuation.tag-open.xml", "meta.tag." + tag + ".tag-name.xml"], + regex : "(<)(" + tag + "(?=\\s|>|$))", + next: [ + {include : "attributes"}, + {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>", next : prefix + "start"} + ] + }); + + this.$rules[tag + "-end"] = [ + {include : "attributes"}, + {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>", next: "start", + onMatch : function(value, currentState, stack) { + stack.splice(0); + return this.token; + }} + ] + + this.embedRules(HighlightRules, prefix, [{ + token: ["meta.tag.punctuation.end-tag-open.xml", "meta.tag." + tag + ".tag-name.xml"], + regex : "(|$))", + next: tag + "-end" + }, { + token: "string.cdata.xml", + regex : "<\\!\\[CDATA\\[" + }, { + token: "string.cdata.xml", + regex : "\\]\\]>" + }]); + }; + +}).call(TextHighlightRules.prototype); + +oop.inherits(XmlHighlightRules, TextHighlightRules); + +exports.XmlHighlightRules = XmlHighlightRules; +}); + +define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); + +function is(token, type) { + return token.type.lastIndexOf(type + ".xml") > -1; +} + +var XmlBehaviour = function () { + + this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { + if (text == '"' || text == "'") { + var quote = text; + var selected = session.doc.getTextRange(editor.getSelectionRange()); + if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { + return { + text: quote + selected + quote, + selection: false + }; + } + + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + + if (rightChar == quote && (is(token, "attribute-value") || is(token, "string"))) { + return { + text: "", + selection: [1, 1] + }; + } + + if (!token) + token = iterator.stepBackward(); + + if (!token) + return; + + while (is(token, "tag-whitespace") || is(token, "whitespace")) { + token = iterator.stepBackward(); + } + var rightSpace = !rightChar || rightChar.match(/\s/); + if (is(token, "attribute-equals") && (rightSpace || rightChar == '>') || (is(token, "decl-attribute-equals") && (rightSpace || rightChar == '?'))) { + return { + text: quote + quote, + selection: [1, 1] + }; + } + } + }); + + this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + + this.add("autoclosing", "insertion", function (state, action, editor, session, text) { + if (text == '>') { + var position = editor.getCursorPosition(); + var iterator = new TokenIterator(session, position.row, position.column); + var token = iterator.getCurrentToken() || iterator.stepBackward(); + if (!token || !(is(token, "tag-name") || is(token, "tag-whitespace") || is(token, "attribute-name") || is(token, "attribute-equals") || is(token, "attribute-value"))) + return; + if (is(token, "reference.attribute-value")) + return; + if (is(token, "attribute-value")) { + var firstChar = token.value.charAt(0); + if (firstChar == '"' || firstChar == "'") { + var lastChar = token.value.charAt(token.value.length - 1); + var tokenEnd = iterator.getCurrentTokenColumn() + token.value.length; + if (tokenEnd > position.column || tokenEnd == position.column && firstChar != lastChar) + return; + } + } + while (!is(token, "tag-name")) { + token = iterator.stepBackward(); + } + + var tokenRow = iterator.getCurrentTokenRow(); + var tokenColumn = iterator.getCurrentTokenColumn(); + if (is(iterator.stepBackward(), "end-tag-open")) + return; + + var element = token.value; + if (tokenRow == position.row) + element = element.substring(0, position.column - tokenColumn); + + if (this.voidElements.hasOwnProperty(element.toLowerCase())) + return; + + return { + text: ">" + "", + selection: [1, 1] + }; + } + }); + + this.add("autoindent", "insertion", function (state, action, editor, session, text) { + if (text == "\n") { + var cursor = editor.getCursorPosition(); + var line = session.getLine(cursor.row); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + + if (token && token.type.indexOf("tag-close") !== -1) { + if (token.value == "/>") + return; + while (token && token.type.indexOf("tag-name") === -1) { + token = iterator.stepBackward(); + } + + if (!token) { + return; + } + + var tag = token.value; + var row = iterator.getCurrentTokenRow(); + token = iterator.stepBackward(); + if (!token || token.type.indexOf("end-tag") !== -1) { + return; + } + + if (this.voidElements && !this.voidElements[tag]) { + var nextToken = session.getTokenAt(cursor.row, cursor.column+1); + var line = session.getLine(row); + var nextIndent = this.$getIndent(line); + var indent = nextIndent + session.getTabString(); + + if (nextToken && nextToken.value === " -1; +} + +(function() { + + this.getFoldWidget = function(session, foldStyle, row) { + var tag = this._getFirstTagInLine(session, row); + + if (!tag) + return ""; + + if (tag.closing || (!tag.tagName && tag.selfClosing)) + return foldStyle == "markbeginend" ? "end" : ""; + + if (!tag.tagName || tag.selfClosing || this.voidElements.hasOwnProperty(tag.tagName.toLowerCase())) + return ""; + + if (this._findEndTagInLine(session, row, tag.tagName, tag.end.column)) + return ""; + + return "start"; + }; + this._getFirstTagInLine = function(session, row) { + var tokens = session.getTokens(row); + var tag = new Tag(); + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (is(token, "tag-open")) { + tag.end.column = tag.start.column + token.value.length; + tag.closing = is(token, "end-tag-open"); + token = tokens[++i]; + if (!token) + return null; + tag.tagName = token.value; + tag.end.column += token.value.length; + for (i++; i < tokens.length; i++) { + token = tokens[i]; + tag.end.column += token.value.length; + if (is(token, "tag-close")) { + tag.selfClosing = token.value == '/>'; + break; + } + } + return tag; + } else if (is(token, "tag-close")) { + tag.selfClosing = token.value == '/>'; + return tag; + } + tag.start.column += token.value.length; + } + + return null; + }; + + this._findEndTagInLine = function(session, row, tagName, startColumn) { + var tokens = session.getTokens(row); + var column = 0; + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + column += token.value.length; + if (column < startColumn) + continue; + if (is(token, "end-tag-open")) { + token = tokens[i + 1]; + if (token && token.value == tagName) + return true; + } + } + return false; + }; + this._readTagForward = function(iterator) { + var token = iterator.getCurrentToken(); + if (!token) + return null; + + var tag = new Tag(); + do { + if (is(token, "tag-open")) { + tag.closing = is(token, "end-tag-open"); + tag.start.row = iterator.getCurrentTokenRow(); + tag.start.column = iterator.getCurrentTokenColumn(); + } else if (is(token, "tag-name")) { + tag.tagName = token.value; + } else if (is(token, "tag-close")) { + tag.selfClosing = token.value == "/>"; + tag.end.row = iterator.getCurrentTokenRow(); + tag.end.column = iterator.getCurrentTokenColumn() + token.value.length; + iterator.stepForward(); + return tag; + } + } while(token = iterator.stepForward()); + + return null; + }; + + this._readTagBackward = function(iterator) { + var token = iterator.getCurrentToken(); + if (!token) + return null; + + var tag = new Tag(); + do { + if (is(token, "tag-open")) { + tag.closing = is(token, "end-tag-open"); + tag.start.row = iterator.getCurrentTokenRow(); + tag.start.column = iterator.getCurrentTokenColumn(); + iterator.stepBackward(); + return tag; + } else if (is(token, "tag-name")) { + tag.tagName = token.value; + } else if (is(token, "tag-close")) { + tag.selfClosing = token.value == "/>"; + tag.end.row = iterator.getCurrentTokenRow(); + tag.end.column = iterator.getCurrentTokenColumn() + token.value.length; + } + } while(token = iterator.stepBackward()); + + return null; + }; + + this._pop = function(stack, tag) { + while (stack.length) { + + var top = stack[stack.length-1]; + if (!tag || top.tagName == tag.tagName) { + return stack.pop(); + } + else if (this.optionalEndTags.hasOwnProperty(top.tagName)) { + stack.pop(); + continue; + } else { + return null; + } + } + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var firstTag = this._getFirstTagInLine(session, row); + + if (!firstTag) + return null; + + var isBackward = firstTag.closing || firstTag.selfClosing; + var stack = []; + var tag; + + if (!isBackward) { + var iterator = new TokenIterator(session, row, firstTag.start.column); + var start = { + row: row, + column: firstTag.start.column + firstTag.tagName.length + 2 + }; + if (firstTag.start.row == firstTag.end.row) + start.column = firstTag.end.column; + while (tag = this._readTagForward(iterator)) { + if (tag.selfClosing) { + if (!stack.length) { + tag.start.column += tag.tagName.length + 2; + tag.end.column -= 2; + return Range.fromPoints(tag.start, tag.end); + } else + continue; + } + + if (tag.closing) { + this._pop(stack, tag); + if (stack.length == 0) + return Range.fromPoints(start, tag.start); + } + else { + stack.push(tag); + } + } + } + else { + var iterator = new TokenIterator(session, row, firstTag.end.column); + var end = { + row: row, + column: firstTag.start.column + }; + + while (tag = this._readTagBackward(iterator)) { + if (tag.selfClosing) { + if (!stack.length) { + tag.start.column += tag.tagName.length + 2; + tag.end.column -= 2; + return Range.fromPoints(tag.start, tag.end); + } else + continue; + } + + if (!tag.closing) { + this._pop(stack, tag); + if (stack.length == 0) { + tag.start.column += tag.tagName.length + 2; + if (tag.start.row == tag.end.row && tag.start.column < tag.end.column) + tag.start.column = tag.end.column; + return Range.fromPoints(tag.start, end); + } + } + else { + stack.push(tag); + } + } + } + + }; + +}).call(FoldMode.prototype); + +}); + +define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml","ace/worker/worker_client"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var TextMode = require("./text").Mode; +var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules; +var XmlBehaviour = require("./behaviour/xml").XmlBehaviour; +var XmlFoldMode = require("./folding/xml").FoldMode; +var WorkerClient = require("../worker/worker_client").WorkerClient; + +var Mode = function() { + this.HighlightRules = XmlHighlightRules; + this.$behaviour = new XmlBehaviour(); + this.foldingRules = new XmlFoldMode(); +}; + +oop.inherits(Mode, TextMode); + +(function() { + + this.voidElements = lang.arrayToMap([]); + + this.blockComment = {start: ""}; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/xml_worker", "Worker"); + worker.attachToDocument(session.getDocument()); + + worker.on("error", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + this.$id = "ace/mode/xml"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); + +define("ace/mode/doc_comment_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var DocCommentHighlightRules = function() { + this.$rules = { + "start" : [ { + token : "comment.doc.tag", + regex : "@[\\w\\d_]+" // TODO: fix email addresses + }, + DocCommentHighlightRules.getTagRule(), + { + defaultToken : "comment.doc", + caseInsensitive: true + }] + }; +}; + +oop.inherits(DocCommentHighlightRules, TextHighlightRules); + +DocCommentHighlightRules.getTagRule = function(start) { + return { + token : "comment.doc.tag.storage.type", + regex : "\\b(?:TODO|FIXME|XXX|HACK)\\b" + }; +} + +DocCommentHighlightRules.getStartRule = function(start) { + return { + token : "comment.doc", // doc comment + regex : "\\/\\*(?=\\*)", + next : start + }; +}; + +DocCommentHighlightRules.getEndRule = function (start) { + return { + token : "comment.doc", // closing comment + regex : "\\*\\/", + next : start + }; +}; + + +exports.DocCommentHighlightRules = DocCommentHighlightRules; + +}); + +define("ace/mode/javascript_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/doc_comment_highlight_rules","ace/mode/text_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules; +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var JavaScriptHighlightRules = function(options) { + var keywordMapper = this.createKeywordMapper({ + "variable.language": + "Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|" + // Constructors + "Namespace|QName|XML|XMLList|" + // E4X + "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|" + + "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|" + + "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|" + // Errors + "SyntaxError|TypeError|URIError|" + + "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" + // Non-constructor functions + "isNaN|parseFloat|parseInt|" + + "JSON|Math|" + // Other + "this|arguments|prototype|window|document" , // Pseudo + "keyword": + "const|yield|import|get|set|" + + "break|case|catch|continue|default|delete|do|else|finally|for|function|" + + "if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|" + + "__parent__|__count__|escape|unescape|with|__proto__|" + + "class|enum|extends|super|export|implements|private|public|interface|package|protected|static", + "storage.type": + "const|let|var|function", + "constant.language": + "null|Infinity|NaN|undefined", + "support.function": + "alert", + "constant.language.boolean": "true|false" + }, "identifier"); + var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void"; + var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b"; + + var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex + "u[0-9a-fA-F]{4}|" + // unicode + "[0-2][0-7]{0,2}|" + // oct + "3[0-6][0-7]?|" + // oct + "37[0-7]?|" + // oct + "[4-7][0-7]?|" + //oct + ".)"; + + this.$rules = { + "no_regex" : [ + { + token : "comment", + regex : "\\/\\/", + next : "line_comment" + }, + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + regex : /\/\*/, + next : "comment" + }, { + token : "string", + regex : "'(?=.)", + next : "qstring" + }, { + token : "string", + regex : '"(?=.)', + next : "qqstring" + }, { + token : "constant.numeric", // hex + regex : /0[xX][0-9a-fA-F]+\b/ + }, { + token : "constant.numeric", // float + regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/ + }, { + token : [ + "storage.type", "punctuation.operator", "support.function", + "punctuation.operator", "entity.name.function", "text","keyword.operator" + ], + regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)", + next: "function_arguments" + }, { + token : [ + "storage.type", "punctuation.operator", "entity.name.function", "text", + "keyword.operator", "text", "storage.type", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "entity.name.function", "text", "keyword.operator", "text", "storage.type", + "text", "paren.lparen" + ], + regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "storage.type", "punctuation.operator", "entity.name.function", "text", + "keyword.operator", "text", + "storage.type", "text", "entity.name.function", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "storage.type", "text", "entity.name.function", "text", "paren.lparen" + ], + regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "entity.name.function", "text", "punctuation.operator", + "text", "storage.type", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "text", "text", "storage.type", "text", "paren.lparen" + ], + regex : "(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : "keyword", + regex : "(?:" + kwBeforeRe + ")\\b", + next : "start" + }, { + token : ["punctuation.operator", "support.function"], + regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/ + }, { + token : ["punctuation.operator", "support.function.dom"], + regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName|ClassName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/ + }, { + token : ["punctuation.operator", "support.constant"], + regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/ + }, { + token : ["support.constant"], + regex : /that\b/ + }, { + token : ["storage.type", "punctuation.operator", "support.function.firebug"], + regex : /(console)(\.)(warn|info|log|error|time|trace|timeEnd|assert)\b/ + }, { + token : keywordMapper, + regex : identifierRe + }, { + token : "keyword.operator", + regex : /--|\+\+|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|[!$%&*+\-~\/^]=?/, + next : "start" + }, { + token : "punctuation.operator", + regex : /[?:,;.]/, + next : "start" + }, { + token : "paren.lparen", + regex : /[\[({]/, + next : "start" + }, { + token : "paren.rparen", + regex : /[\])}]/ + }, { + token: "comment", + regex: /^#!.*$/ + } + ], + "start": [ + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + regex : "\\/\\*", + next : "comment_regex_allowed" + }, { + token : "comment", + regex : "\\/\\/", + next : "line_comment_regex_allowed" + }, { + token: "string.regexp", + regex: "\\/", + next: "regex" + }, { + token : "text", + regex : "\\s+|^$", + next : "start" + }, { + token: "empty", + regex: "", + next: "no_regex" + } + ], + "regex": [ + { + token: "regexp.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + token: "string.regexp", + regex: "/[sxngimy]*", + next: "no_regex" + }, { + token : "invalid", + regex: /\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/ + }, { + token : "constant.language.escape", + regex: /\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?.]/ + }, { + token : "constant.language.delimiter", + regex: /\|/ + }, { + token: "constant.language.escape", + regex: /\[\^?/, + next: "regex_character_class" + }, { + token: "empty", + regex: "$", + next: "no_regex" + }, { + defaultToken: "string.regexp" + } + ], + "regex_character_class": [ + { + token: "regexp.charclass.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + token: "constant.language.escape", + regex: "]", + next: "regex" + }, { + token: "constant.language.escape", + regex: "-" + }, { + token: "empty", + regex: "$", + next: "no_regex" + }, { + defaultToken: "string.regexp.charachterclass" + } + ], + "function_arguments": [ + { + token: "variable.parameter", + regex: identifierRe + }, { + token: "punctuation.operator", + regex: "[, ]+" + }, { + token: "punctuation.operator", + regex: "$" + }, { + token: "empty", + regex: "", + next: "no_regex" + } + ], + "comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "\\*\\/", next : "start"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "comment" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "\\*\\/", next : "no_regex"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "line_comment_regex_allowed" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "$|^", next : "start"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "line_comment" : [ + DocCommentHighlightRules.getTagRule(), + {token : "comment", regex : "$|^", next : "no_regex"}, + {defaultToken : "comment", caseInsensitive: true} + ], + "qqstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : "\\\\$", + next : "qqstring" + }, { + token : "string", + regex : '"|$', + next : "no_regex" + }, { + defaultToken: "string" + } + ], + "qstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : "\\\\$", + next : "qstring" + }, { + token : "string", + regex : "'|$", + next : "no_regex" + }, { + defaultToken: "string" + } + ] + }; + + + if (!options || !options.noES6) { + this.$rules.no_regex.unshift({ + regex: "[{}]", onMatch: function(val, state, stack) { + this.next = val == "{" ? this.nextState : ""; + if (val == "{" && stack.length) { + stack.unshift("start", state); + return "paren"; + } + if (val == "}" && stack.length) { + stack.shift(); + this.next = stack.shift(); + if (this.next.indexOf("string") != -1) + return "paren.quasi.end"; + } + return val == "{" ? "paren.lparen" : "paren.rparen"; + }, + nextState: "start" + }, { + token : "string.quasi.start", + regex : /`/, + push : [{ + token : "constant.language.escape", + regex : escapedRe + }, { + token : "paren.quasi.start", + regex : /\${/, + push : "start" + }, { + token : "string.quasi.end", + regex : /`/, + next : "pop" + }, { + defaultToken: "string.quasi" + }] + }); + } + + this.embedRules(DocCommentHighlightRules, "doc-", + [ DocCommentHighlightRules.getEndRule("no_regex") ]); + + this.normalizeRules(); +}; + +oop.inherits(JavaScriptHighlightRules, TextHighlightRules); + +exports.JavaScriptHighlightRules = JavaScriptHighlightRules; +}); + +define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"], function(require, exports, module) { +"use strict"; + +var Range = require("../range").Range; + +var MatchingBraceOutdent = function() {}; + +(function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + +}).call(MatchingBraceOutdent.prototype); + +exports.MatchingBraceOutdent = MatchingBraceOutdent; +}); + +define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); + +var SAFE_INSERT_IN_TOKENS = + ["text", "paren.rparen", "punctuation.operator"]; +var SAFE_INSERT_BEFORE_TOKENS = + ["text", "paren.rparen", "punctuation.operator", "comment"]; + +var context; +var contextCache = {}; +var initContext = function(editor) { + var id = -1; + if (editor.multiSelect) { + id = editor.selection.index; + if (contextCache.rangeCount != editor.multiSelect.rangeCount) + contextCache = {rangeCount: editor.multiSelect.rangeCount}; + } + if (contextCache[id]) + return context = contextCache[id]; + context = contextCache[id] = { + autoInsertedBrackets: 0, + autoInsertedRow: -1, + autoInsertedLineEnd: "", + maybeInsertedBrackets: 0, + maybeInsertedRow: -1, + maybeInsertedLineStart: "", + maybeInsertedLineEnd: "" + }; +}; + +var CstyleBehaviour = function() { + this.add("braces", "insertion", function(state, action, editor, session, text) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (text == '{') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { + return { + text: '{' + selected + '}', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode) { + CstyleBehaviour.recordAutoInsert(editor, session, "}"); + return { + text: '{}', + selection: [1, 1] + }; + } else { + CstyleBehaviour.recordMaybeInsert(editor, session, "{"); + return { + text: '{', + selection: [1, 1] + }; + } + } + } else if (text == '}') { + initContext(editor); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } else if (text == "\n" || text == "\r\n") { + initContext(editor); + var closing = ""; + if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { + closing = lang.stringRepeat("}", context.maybeInsertedBrackets); + CstyleBehaviour.clearMaybeInsertedClosing(); + } + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === '}') { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column+1}, '}'); + if (!openBracePos) + return null; + var next_indent = this.$getIndent(session.getLine(openBracePos.row)); + } else if (closing) { + var next_indent = this.$getIndent(line); + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + return; + } + var indent = next_indent + session.getTabString(); + + return { + text: '\n' + indent + '\n' + next_indent + closing, + selection: [1, indent.length, 1, indent.length] + }; + } else { + CstyleBehaviour.clearMaybeInsertedClosing(); + } + }); + + this.add("braces", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar == '}') { + range.end.column++; + return range; + } else { + context.maybeInsertedBrackets--; + } + } + }); + + this.add("parens", "insertion", function(state, action, editor, session, text) { + if (text == '(') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '(' + selected + ')', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, ")"); + return { + text: '()', + selection: [1, 1] + }; + } + } else if (text == ')') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ')') { + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("parens", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ')') { + range.end.column++; + return range; + } + } + }); + + this.add("brackets", "insertion", function(state, action, editor, session, text) { + if (text == '[') { + initContext(editor); + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '[' + selected + ']', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, "]"); + return { + text: '[]', + selection: [1, 1] + }; + } + } else if (text == ']') { + initContext(editor); + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ']') { + var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("brackets", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '[') { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ']') { + range.end.column++; + return range; + } + } + }); + + this.add("string_dquotes", "insertion", function(state, action, editor, session, text) { + if (text == '"' || text == "'") { + initContext(editor); + var quote = text; + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { + return { + text: quote + selected + quote, + selection: false + }; + } else if (!selected) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + var rightChar = line.substring(cursor.column, cursor.column + 1); + + var token = session.getTokenAt(cursor.row, cursor.column); + var rightToken = session.getTokenAt(cursor.row, cursor.column + 1); + if (leftChar == "\\" && token && /escape/.test(token.type)) + return null; + + var stringBefore = token && /string/.test(token.type); + var stringAfter = !rightToken || /string/.test(rightToken.type); + + var pair; + if (rightChar == quote) { + pair = stringBefore !== stringAfter; + } else { + if (stringBefore && !stringAfter) + return null; // wrap string with different quote + if (stringBefore && stringAfter) + return null; // do not pair quotes inside strings + var wordRe = session.$mode.tokenRe; + wordRe.lastIndex = 0; + var isWordBefore = wordRe.test(leftChar); + wordRe.lastIndex = 0; + var isWordAfter = wordRe.test(leftChar); + if (isWordBefore || isWordAfter) + return null; // before or after alphanumeric + if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) + return null; // there is rightChar and it isn't closing + pair = true; + } + return { + text: pair ? quote + quote : "", + selection: [1,1] + }; + } + } + }); + + this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + initContext(editor); + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + +}; + + +CstyleBehaviour.isSaneInsertion = function(editor, session) { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { + var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); + if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) + return false; + } + iterator.stepForward(); + return iterator.getCurrentTokenRow() !== cursor.row || + this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); +}; + +CstyleBehaviour.$matchTokenType = function(token, types) { + return types.indexOf(token.type || token) > -1; +}; + +CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0])) + context.autoInsertedBrackets = 0; + context.autoInsertedRow = cursor.row; + context.autoInsertedLineEnd = bracket + line.substr(cursor.column); + context.autoInsertedBrackets++; +}; + +CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isMaybeInsertedClosing(cursor, line)) + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = cursor.row; + context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; + context.maybeInsertedLineEnd = line.substr(cursor.column); + context.maybeInsertedBrackets++; +}; + +CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { + return context.autoInsertedBrackets > 0 && + cursor.row === context.autoInsertedRow && + bracket === context.autoInsertedLineEnd[0] && + line.substr(cursor.column) === context.autoInsertedLineEnd; +}; + +CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { + return context.maybeInsertedBrackets > 0 && + cursor.row === context.maybeInsertedRow && + line.substr(cursor.column) === context.maybeInsertedLineEnd && + line.substr(0, cursor.column) == context.maybeInsertedLineStart; +}; + +CstyleBehaviour.popAutoInsertedClosing = function() { + context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1); + context.autoInsertedBrackets--; +}; + +CstyleBehaviour.clearMaybeInsertedClosing = function() { + if (context) { + context.maybeInsertedBrackets = 0; + context.maybeInsertedRow = -1; + } +}; + + + +oop.inherits(CstyleBehaviour, Behaviour); + +exports.CstyleBehaviour = CstyleBehaviour; +}); + +define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var Range = require("../../range").Range; +var BaseFoldMode = require("./fold_mode").FoldMode; + +var FoldMode = exports.FoldMode = function(commentRegex) { + if (commentRegex) { + this.foldingStartMarker = new RegExp( + this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start) + ); + this.foldingStopMarker = new RegExp( + this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end) + ); + } +}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; + this.singleLineBlockCommentRe= /^\s*(\/\*).*\*\/\s*$/; + this.tripleStarBlockCommentRe = /^\s*(\/\*\*\*).*\*\/\s*$/; + this.startRegionRe = /^\s*(\/\*|\/\/)#region\b/; + this._getFoldWidgetBase = this.getFoldWidget; + this.getFoldWidget = function(session, foldStyle, row) { + var line = session.getLine(row); + + if (this.singleLineBlockCommentRe.test(line)) { + if (!this.startRegionRe.test(line) && !this.tripleStarBlockCommentRe.test(line)) + return ""; + } + + var fw = this._getFoldWidgetBase(session, foldStyle, row); + + if (!fw && this.startRegionRe.test(line)) + return "start"; // lineCommentRegionStart + + return fw; + }; + + this.getFoldWidgetRange = function(session, foldStyle, row, forceMultiline) { + var line = session.getLine(row); + + if (this.startRegionRe.test(line)) + return this.getCommentRegionBlock(session, line, row); + + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + + if (match[1]) + return this.openingBracketBlock(session, match[1], row, i); + + var range = session.getCommentFoldRange(row, i + match[0].length, 1); + + if (range && !range.isMultiLine()) { + if (forceMultiline) { + range = this.getSectionRange(session, row); + } else if (foldStyle != "all") + range = null; + } + + return range; + } + + if (foldStyle === "markbegin") + return; + + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + + if (match[1]) + return this.closingBracketBlock(session, match[1], row, i); + + return session.getCommentFoldRange(row, i, -1); + } + }; + + this.getSectionRange = function(session, row) { + var line = session.getLine(row); + var startIndent = line.search(/\S/); + var startRow = row; + var startColumn = line.length; + row = row + 1; + var endRow = row; + var maxRow = session.getLength(); + while (++row < maxRow) { + line = session.getLine(row); + var indent = line.search(/\S/); + if (indent === -1) + continue; + if (startIndent > indent) + break; + var subRange = this.getFoldWidgetRange(session, "all", row); + + if (subRange) { + if (subRange.start.row <= startRow) { + break; + } else if (subRange.isMultiLine()) { + row = subRange.end.row; + } else if (startIndent == indent) { + break; + } + } + endRow = row; + } + + return new Range(startRow, startColumn, endRow, session.getLine(endRow).length); + }; + + this.getCommentRegionBlock = function(session, line, row) { + var startColumn = line.search(/\s*$/); + var maxRow = session.getLength(); + var startRow = row; + + var re = /^\s*(?:\/\*|\/\/)#(end)?region\b/; + var depth = 1; + while (++row < maxRow) { + line = session.getLine(row); + var m = re.exec(line); + if (!m) continue; + if (m[1]) depth--; + else depth++; + + if (!depth) break; + } + + var endRow = row; + if (endRow > startRow) { + return new Range(startRow, startColumn, endRow, line.length); + } + }; + +}).call(FoldMode.prototype); + +}); + +define("ace/mode/javascript",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/javascript_highlight_rules","ace/mode/matching_brace_outdent","ace/range","ace/worker/worker_client","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var Range = require("../range").Range; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = JavaScriptHighlightRules; + + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.lineCommentStart = "//"; + this.blockComment = {start: "/*", end: "*/"}; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + var endState = tokenizedLine.state; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start" || state == "no_regex") { + var match = line.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/); + if (match) { + indent += tab; + } + } else if (state == "doc-start") { + if (endState == "start" || endState == "no_regex") { + return ""; + } + var match = line.match(/^\s*(\/?)\*/); + if (match) { + if (match[1]) { + indent += " "; + } + indent += "* "; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker"); + worker.attachToDocument(session.getDocument()); + + worker.on("annotate", function(results) { + session.setAnnotations(results.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + + this.$id = "ace/mode/javascript"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); + +define("ace/mode/svg_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/javascript_highlight_rules","ace/mode/xml_highlight_rules"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; +var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules; + +var SvgHighlightRules = function() { + XmlHighlightRules.call(this); + + this.embedTagRules(JavaScriptHighlightRules, "js-", "script"); + + this.normalizeRules(); +}; + +oop.inherits(SvgHighlightRules, XmlHighlightRules); + +exports.SvgHighlightRules = SvgHighlightRules; +}); + +define("ace/mode/folding/mixed",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode"], function(require, exports, module) { +"use strict"; + +var oop = require("../../lib/oop"); +var BaseFoldMode = require("./fold_mode").FoldMode; + +var FoldMode = exports.FoldMode = function(defaultMode, subModes) { + this.defaultMode = defaultMode; + this.subModes = subModes; +}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + + this.$getMode = function(state) { + if (typeof state != "string") + state = state[0]; + for (var key in this.subModes) { + if (state.indexOf(key) === 0) + return this.subModes[key]; + } + return null; + }; + + this.$tryMode = function(state, session, foldStyle, row) { + var mode = this.$getMode(state); + return (mode ? mode.getFoldWidget(session, foldStyle, row) : ""); + }; + + this.getFoldWidget = function(session, foldStyle, row) { + return ( + this.$tryMode(session.getState(row-1), session, foldStyle, row) || + this.$tryMode(session.getState(row), session, foldStyle, row) || + this.defaultMode.getFoldWidget(session, foldStyle, row) + ); + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var mode = this.$getMode(session.getState(row-1)); + + if (!mode || !mode.getFoldWidget(session, foldStyle, row)) + mode = this.$getMode(session.getState(row)); + + if (!mode || !mode.getFoldWidget(session, foldStyle, row)) + mode = this.defaultMode; + + return mode.getFoldWidgetRange(session, foldStyle, row); + }; + +}).call(FoldMode.prototype); + +}); + +define("ace/mode/svg",["require","exports","module","ace/lib/oop","ace/mode/xml","ace/mode/javascript","ace/mode/svg_highlight_rules","ace/mode/folding/mixed","ace/mode/folding/xml","ace/mode/folding/cstyle"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var XmlMode = require("./xml").Mode; +var JavaScriptMode = require("./javascript").Mode; +var SvgHighlightRules = require("./svg_highlight_rules").SvgHighlightRules; +var MixedFoldMode = require("./folding/mixed").FoldMode; +var XmlFoldMode = require("./folding/xml").FoldMode; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + XmlMode.call(this); + + this.HighlightRules = SvgHighlightRules; + + this.createModeDelegates({ + "js-": JavaScriptMode + }); + + this.foldingRules = new MixedFoldMode(new XmlFoldMode(), { + "js-": new CStyleFoldMode() + }); +}; + +oop.inherits(Mode, XmlMode); + +(function() { + + this.getNextLineIndent = function(state, line, tab) { + return this.$getIndent(line); + }; + + + this.$id = "ace/mode/svg"; +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/mode-text.js b/Patent2Net/media/graph-recipes/app/assets/ace/mode-text.js new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/mode-text.js @@ -0,0 +1 @@ + diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/abap.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/abap.js new file mode 100644 index 00000000..cc404459 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/abap.js @@ -0,0 +1,7 @@ +define("ace/snippets/abap",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "abap"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/abc.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/abc.js new file mode 100644 index 00000000..1df7d31b --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/abc.js @@ -0,0 +1,38 @@ +define("ace/snippets/abc",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "\n\ +snippet zupfnoter.print\n\ + %%%%hn.print {\"startpos\": ${1:pos_y}, \"t\":\"${2:title}\", \"v\":[${3:voices}], \"s\":[[${4:syncvoices}1,2]], \"f\":[${5:flowlines}], \"sf\":[${6:subflowlines}], \"j\":[${7:jumplines}]}\n\ +\n\ +snippet zupfnoter.note\n\ + %%%%hn.note {\"pos\": [${1:pos_x},${2:pos_y}], \"text\": \"${3:text}\", \"style\": \"${4:style}\"}\n\ +\n\ +snippet zupfnoter.annotation\n\ + %%%%hn.annotation {\"id\": \"${1:id}\", \"pos\": [${2:pos}], \"text\": \"${3:text}\"}\n\ +\n\ +snippet zupfnoter.lyrics\n\ + %%%%hn.lyrics {\"pos\": [${1:x_pos},${2:y_pos}]}\n\ +\n\ +snippet zupfnoter.legend\n\ + %%%%hn.legend {\"pos\": [${1:x_pos},${2:y_pos}]}\n\ +\n\ +\n\ +\n\ +snippet zupfnoter.target\n\ + \"^:${1:target}\"\n\ +\n\ +snippet zupfnoter.goto\n\ + \"^@${1:target}@${2:distance}\"\n\ +\n\ +snippet zupfnoter.annotationref\n\ + \"^#${1:target}\"\n\ +\n\ +snippet zupfnoter.annotation\n\ + \"^!${1:text}@${2:x_offset},${3:y_offset}\"\n\ +\n\ +\n\ +"; +exports.scope = "abc"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/actionscript.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/actionscript.js new file mode 100644 index 00000000..41577b13 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/actionscript.js @@ -0,0 +1,159 @@ +define("ace/snippets/actionscript",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet main\n\ + package {\n\ + import flash.display.*;\n\ + import flash.Events.*;\n\ + \n\ + public class Main extends Sprite {\n\ + public function Main ( ) {\n\ + trace(\"start\");\n\ + stage.scaleMode = StageScaleMode.NO_SCALE;\n\ + stage.addEventListener(Event.RESIZE, resizeListener);\n\ + }\n\ + \n\ + private function resizeListener (e:Event):void {\n\ + trace(\"The application window changed size!\");\n\ + trace(\"New width: \" + stage.stageWidth);\n\ + trace(\"New height: \" + stage.stageHeight);\n\ + }\n\ + \n\ + }\n\ + \n\ + }\n\ +snippet class\n\ + ${1:public|internal} class ${2:name} ${3:extends } {\n\ + public function $2 ( ) {\n\ + (\"start\");\n\ + }\n\ + }\n\ +snippet all\n\ + package name {\n\ +\n\ + ${1:public|internal|final} class ${2:name} ${3:extends } {\n\ + private|public| static const FOO = \"abc\";\n\ + private|public| static var BAR = \"abc\";\n\ + if Cababilities.os == \"Linux|MacOS\" {\n\ + FOO = \"other\";\n\ + }\n\ + public function $2 ( ){\n\ + super2();\n\ + trace(\"start\");\n\ + }\n\ + public function name (a, b...){\n\ + super.name(..);\n\ + lable:break\n\ + }\n\ + }\n\ + }\n\ +\n\ + function A(){\n\ + }\n\ +snippet switch\n\ + switch(${1}){\n\ + case ${2}:\n\ + ${3}\n\ + break;\n\ + default:\n\ + }\n\ +snippet case\n\ + case ${1}:\n\ + ${2}\n\ + break;\n\ +snippet package\n\ + package ${1:package}{\n\ + ${2}\n\ + }\n\ +snippet wh\n\ + while ${1:cond}{\n\ + ${2}\n\ + }\n\ +snippet do\n\ + do {\n\ + ${2}\n\ + } while (${1:cond})\n\ +snippet while\n\ + while ${1:cond}{\n\ + ${2}\n\ + }\n\ +snippet for enumerate names\n\ + for (${1:var} in ${2:object}){\n\ + ${3}\n\ + }\n\ +snippet for enumerate values\n\ + for each (${1:var} in ${2:object}){\n\ + ${3}\n\ + }\n\ +snippet get_set\n\ + function get ${1:name} {\n\ + return ${2}\n\ + }\n\ + function set $1 (newValue) {\n\ + ${3}\n\ + }\n\ +snippet interface\n\ + interface name {\n\ + function method(${1}):${2:returntype};\n\ + }\n\ +snippet try\n\ + try {\n\ + ${1}\n\ + } catch (error:ErrorType) {\n\ + ${2}\n\ + } finally {\n\ + ${3}\n\ + }\n\ +# For Loop (same as c.snippet)\n\ +snippet for for (..) {..}\n\ + for (${2:i} = 0; $2 < ${1:count}; $2${3:++}) {\n\ + ${4:/* code */}\n\ + }\n\ +# Custom For Loop\n\ +snippet forr\n\ + for (${1:i} = ${2:0}; ${3:$1 < 10}; $1${4:++}) {\n\ + ${5:/* code */}\n\ + }\n\ +# If Condition\n\ +snippet if\n\ + if (${1:/* condition */}) {\n\ + ${2:/* code */}\n\ + }\n\ +snippet el\n\ + else {\n\ + ${1}\n\ + }\n\ +# Ternary conditional\n\ +snippet t\n\ + ${1:/* condition */} ? ${2:a} : ${3:b}\n\ +snippet fun\n\ + function ${1:function_name}(${2})${3}\n\ + {\n\ + ${4:/* code */}\n\ + }\n\ +# FlxSprite (usefull when using the flixel library)\n\ +snippet FlxSprite\n\ + package\n\ + {\n\ + import org.flixel.*\n\ +\n\ + public class ${1:ClassName} extends ${2:FlxSprite}\n\ + {\n\ + public function $1(${3: X:Number, Y:Number}):void\n\ + {\n\ + super(X,Y);\n\ + ${4: //code...}\n\ + }\n\ +\n\ + override public function update():void\n\ + {\n\ + super.update();\n\ + ${5: //code...}\n\ + }\n\ + }\n\ + }\n\ +\n\ +"; +exports.scope = "actionscript"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ada.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ada.js new file mode 100644 index 00000000..2e53d2d1 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ada.js @@ -0,0 +1,7 @@ +define("ace/snippets/ada",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "ada"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/apache_conf.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/apache_conf.js new file mode 100644 index 00000000..21055de0 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/apache_conf.js @@ -0,0 +1,7 @@ +define("ace/snippets/apache_conf",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "apache_conf"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/applescript.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/applescript.js new file mode 100644 index 00000000..7f8710d4 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/applescript.js @@ -0,0 +1,7 @@ +define("ace/snippets/applescript",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "applescript"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/asciidoc.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/asciidoc.js new file mode 100644 index 00000000..4f82a045 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/asciidoc.js @@ -0,0 +1,7 @@ +define("ace/snippets/asciidoc",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "asciidoc"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/assembly_x86.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/assembly_x86.js new file mode 100644 index 00000000..87694e0b --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/assembly_x86.js @@ -0,0 +1,7 @@ +define("ace/snippets/assembly_x86",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "assembly_x86"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/autohotkey.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/autohotkey.js new file mode 100644 index 00000000..834f3e28 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/autohotkey.js @@ -0,0 +1,7 @@ +define("ace/snippets/autohotkey",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "autohotkey"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/batchfile.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/batchfile.js new file mode 100644 index 00000000..9be8afeb --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/batchfile.js @@ -0,0 +1,7 @@ +define("ace/snippets/batchfile",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "batchfile"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/c9search.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/c9search.js new file mode 100644 index 00000000..0cc56756 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/c9search.js @@ -0,0 +1,7 @@ +define("ace/snippets/c9search",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "c9search"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/c_cpp.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/c_cpp.js new file mode 100644 index 00000000..3ad618df --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/c_cpp.js @@ -0,0 +1,138 @@ +define("ace/snippets/c_cpp",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "## STL Collections\n\ +# std::array\n\ +snippet array\n\ + std::array<${1:T}, ${2:N}> ${3};${4}\n\ +# std::vector\n\ +snippet vector\n\ + std::vector<${1:T}> ${2};${3}\n\ +# std::deque\n\ +snippet deque\n\ + std::deque<${1:T}> ${2};${3}\n\ +# std::forward_list\n\ +snippet flist\n\ + std::forward_list<${1:T}> ${2};${3}\n\ +# std::list\n\ +snippet list\n\ + std::list<${1:T}> ${2};${3}\n\ +# std::set\n\ +snippet set\n\ + std::set<${1:T}> ${2};${3}\n\ +# std::map\n\ +snippet map\n\ + std::map<${1:Key}, ${2:T}> ${3};${4}\n\ +# std::multiset\n\ +snippet mset\n\ + std::multiset<${1:T}> ${2};${3}\n\ +# std::multimap\n\ +snippet mmap\n\ + std::multimap<${1:Key}, ${2:T}> ${3};${4}\n\ +# std::unordered_set\n\ +snippet uset\n\ + std::unordered_set<${1:T}> ${2};${3}\n\ +# std::unordered_map\n\ +snippet umap\n\ + std::unordered_map<${1:Key}, ${2:T}> ${3};${4}\n\ +# std::unordered_multiset\n\ +snippet umset\n\ + std::unordered_multiset<${1:T}> ${2};${3}\n\ +# std::unordered_multimap\n\ +snippet ummap\n\ + std::unordered_multimap<${1:Key}, ${2:T}> ${3};${4}\n\ +# std::stack\n\ +snippet stack\n\ + std::stack<${1:T}> ${2};${3}\n\ +# std::queue\n\ +snippet queue\n\ + std::queue<${1:T}> ${2};${3}\n\ +# std::priority_queue\n\ +snippet pqueue\n\ + std::priority_queue<${1:T}> ${2};${3}\n\ +##\n\ +## Access Modifiers\n\ +# private\n\ +snippet pri\n\ + private\n\ +# protected\n\ +snippet pro\n\ + protected\n\ +# public\n\ +snippet pub\n\ + public\n\ +# friend\n\ +snippet fr\n\ + friend\n\ +# mutable\n\ +snippet mu\n\ + mutable\n\ +## \n\ +## Class\n\ +# class\n\ +snippet cl\n\ + class ${1:`Filename('$1', 'name')`} \n\ + {\n\ + public:\n\ + $1(${2});\n\ + ~$1();\n\ +\n\ + private:\n\ + ${3:/* data */}\n\ + };\n\ +# member function implementation\n\ +snippet mfun\n\ + ${4:void} ${1:`Filename('$1', 'ClassName')`}::${2:memberFunction}(${3}) {\n\ + ${5:/* code */}\n\ + }\n\ +# namespace\n\ +snippet ns\n\ + namespace ${1:`Filename('', 'my')`} {\n\ + ${2}\n\ + } /* namespace $1 */\n\ +##\n\ +## Input/Output\n\ +# std::cout\n\ +snippet cout\n\ + std::cout << ${1} << std::endl;${2}\n\ +# std::cin\n\ +snippet cin\n\ + std::cin >> ${1};${2}\n\ +##\n\ +## Iteration\n\ +# for i \n\ +snippet fori\n\ + for (int ${2:i} = 0; $2 < ${1:count}; $2${3:++}) {\n\ + ${4:/* code */}\n\ + }${5}\n\ +\n\ +# foreach\n\ +snippet fore\n\ + for (${1:auto} ${2:i} : ${3:container}) {\n\ + ${4:/* code */}\n\ + }${5}\n\ +# iterator\n\ +snippet iter\n\ + for (${1:std::vector}<${2:type}>::${3:const_iterator} ${4:i} = ${5:container}.begin(); $4 != $5.end(); ++$4) {\n\ + ${6}\n\ + }${7}\n\ +\n\ +# auto iterator\n\ +snippet itera\n\ + for (auto ${1:i} = $1.begin(); $1 != $1.end(); ++$1) {\n\ + ${2:std::cout << *$1 << std::endl;}\n\ + }${3}\n\ +##\n\ +## Lambdas\n\ +# lamda (one line)\n\ +snippet ld\n\ + [${1}](${2}){${3:/* code */}}${4}\n\ +# lambda (multi-line)\n\ +snippet lld\n\ + [${1}](${2}){\n\ + ${3:/* code */}\n\ + }${4}\n\ +"; +exports.scope = "c_cpp"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/cirru.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/cirru.js new file mode 100644 index 00000000..13ade9c9 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/cirru.js @@ -0,0 +1,7 @@ +define("ace/snippets/cirru",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "cirru"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/clojure.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/clojure.js new file mode 100644 index 00000000..278a4770 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/clojure.js @@ -0,0 +1,97 @@ +define("ace/snippets/clojure",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet comm\n\ + (comment\n\ + ${1}\n\ + )\n\ +snippet condp\n\ + (condp ${1:pred} ${2:expr}\n\ + ${3})\n\ +snippet def\n\ + (def ${1})\n\ +snippet defm\n\ + (defmethod ${1:multifn} \"${2:doc-string}\" ${3:dispatch-val} [${4:args}]\n\ + ${5})\n\ +snippet defmm\n\ + (defmulti ${1:name} \"${2:doc-string}\" ${3:dispatch-fn})\n\ +snippet defma\n\ + (defmacro ${1:name} \"${2:doc-string}\" ${3:dispatch-fn})\n\ +snippet defn\n\ + (defn ${1:name} \"${2:doc-string}\" [${3:arg-list}]\n\ + ${4})\n\ +snippet defp\n\ + (defprotocol ${1:name}\n\ + ${2})\n\ +snippet defr\n\ + (defrecord ${1:name} [${2:fields}]\n\ + ${3:protocol}\n\ + ${4})\n\ +snippet deft\n\ + (deftest ${1:name}\n\ + (is (= ${2:assertion})))\n\ + ${3})\n\ +snippet is\n\ + (is (= ${1} ${2}))\n\ +snippet defty\n\ + (deftype ${1:Name} [${2:fields}]\n\ + ${3:Protocol}\n\ + ${4})\n\ +snippet doseq\n\ + (doseq [${1:elem} ${2:coll}]\n\ + ${3})\n\ +snippet fn\n\ + (fn [${1:arg-list}] ${2})\n\ +snippet if\n\ + (if ${1:test-expr}\n\ + ${2:then-expr}\n\ + ${3:else-expr})\n\ +snippet if-let \n\ + (if-let [${1:result} ${2:test-expr}]\n\ + (${3:then-expr} $1)\n\ + (${4:else-expr}))\n\ +snippet imp\n\ + (:import [${1:package}])\n\ + & {:keys [${1:keys}] :or {${2:defaults}}}\n\ +snippet let\n\ + (let [${1:name} ${2:expr}]\n\ + ${3})\n\ +snippet letfn\n\ + (letfn [(${1:name) [${2:args}]\n\ + ${3})])\n\ +snippet map\n\ + (map ${1:func} ${2:coll})\n\ +snippet mapl\n\ + (map #(${1:lambda}) ${2:coll})\n\ +snippet met\n\ + (${1:name} [${2:this} ${3:args}]\n\ + ${4})\n\ +snippet ns\n\ + (ns ${1:name}\n\ + ${2})\n\ +snippet dotimes\n\ + (dotimes [_ 10]\n\ + (time\n\ + (dotimes [_ ${1:times}]\n\ + ${2})))\n\ +snippet pmethod\n\ + (${1:name} [${2:this} ${3:args}])\n\ +snippet refer\n\ + (:refer-clojure :exclude [${1}])\n\ +snippet require\n\ + (:require [${1:namespace} :as [${2}]])\n\ +snippet use\n\ + (:use [${1:namespace} :only [${2}]])\n\ +snippet print\n\ + (println ${1})\n\ +snippet reduce\n\ + (reduce ${1:(fn [p n] ${3})} ${2})\n\ +snippet when\n\ + (when ${1:test} ${2:body})\n\ +snippet when-let\n\ + (when-let [${1:result} ${2:test}]\n\ + ${3:body})\n\ +"; +exports.scope = "clojure"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/cobol.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/cobol.js new file mode 100644 index 00000000..632bffe5 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/cobol.js @@ -0,0 +1,7 @@ +define("ace/snippets/cobol",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "cobol"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/coffee.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/coffee.js new file mode 100644 index 00000000..e6b8a924 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/coffee.js @@ -0,0 +1,102 @@ +define("ace/snippets/coffee",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# Closure loop\n\ +snippet forindo\n\ + for ${1:name} in ${2:array}\n\ + do ($1) ->\n\ + ${3:// body}\n\ +# Array comprehension\n\ +snippet fora\n\ + for ${1:name} in ${2:array}\n\ + ${3:// body...}\n\ +# Object comprehension\n\ +snippet foro\n\ + for ${1:key}, ${2:value} of ${3:object}\n\ + ${4:// body...}\n\ +# Range comprehension (inclusive)\n\ +snippet forr\n\ + for ${1:name} in [${2:start}..${3:finish}]\n\ + ${4:// body...}\n\ +snippet forrb\n\ + for ${1:name} in [${2:start}..${3:finish}] by ${4:step}\n\ + ${5:// body...}\n\ +# Range comprehension (exclusive)\n\ +snippet forrex\n\ + for ${1:name} in [${2:start}...${3:finish}]\n\ + ${4:// body...}\n\ +snippet forrexb\n\ + for ${1:name} in [${2:start}...${3:finish}] by ${4:step}\n\ + ${5:// body...}\n\ +# Function\n\ +snippet fun\n\ + (${1:args}) ->\n\ + ${2:// body...}\n\ +# Function (bound)\n\ +snippet bfun\n\ + (${1:args}) =>\n\ + ${2:// body...}\n\ +# Class\n\ +snippet cla class ..\n\ + class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`}\n\ + ${2}\n\ +snippet cla class .. constructor: ..\n\ + class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`}\n\ + constructor: (${2:args}) ->\n\ + ${3}\n\ +\n\ + ${4}\n\ +snippet cla class .. extends ..\n\ + class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`} extends ${2:ParentClass}\n\ + ${3}\n\ +snippet cla class .. extends .. constructor: ..\n\ + class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`} extends ${2:ParentClass}\n\ + constructor: (${3:args}) ->\n\ + ${4}\n\ +\n\ + ${5}\n\ +# If\n\ +snippet if\n\ + if ${1:condition}\n\ + ${2:// body...}\n\ +# If __ Else\n\ +snippet ife\n\ + if ${1:condition}\n\ + ${2:// body...}\n\ + else\n\ + ${3:// body...}\n\ +# Else if\n\ +snippet elif\n\ + else if ${1:condition}\n\ + ${2:// body...}\n\ +# Ternary If\n\ +snippet ifte\n\ + if ${1:condition} then ${2:value} else ${3:other}\n\ +# Unless\n\ +snippet unl\n\ + ${1:action} unless ${2:condition}\n\ +# Switch\n\ +snippet swi\n\ + switch ${1:object}\n\ + when ${2:value}\n\ + ${3:// body...}\n\ +\n\ +# Log\n\ +snippet log\n\ + console.log ${1}\n\ +# Try __ Catch\n\ +snippet try\n\ + try\n\ + ${1}\n\ + catch ${2:error}\n\ + ${3}\n\ +# Require\n\ +snippet req\n\ + ${2:$1} = require '${1:sys}'${3}\n\ +# Export\n\ +snippet exp\n\ + ${1:root} = exports ? this\n\ +"; +exports.scope = "coffee"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/coldfusion.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/coldfusion.js new file mode 100644 index 00000000..cba55cd8 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/coldfusion.js @@ -0,0 +1,7 @@ +define("ace/snippets/coldfusion",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "coldfusion"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/csharp.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/csharp.js new file mode 100644 index 00000000..07d12a48 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/csharp.js @@ -0,0 +1,7 @@ +define("ace/snippets/csharp",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "csharp"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/css.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/css.js new file mode 100644 index 00000000..195ce47b --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/css.js @@ -0,0 +1,974 @@ +define("ace/snippets/css",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet .\n\ + ${1} {\n\ + ${2}\n\ + }\n\ +snippet !\n\ + !important\n\ +snippet bdi:m+\n\ + -moz-border-image: url(${1}) ${2:0} ${3:0} ${4:0} ${5:0} ${6:stretch} ${7:stretch};\n\ +snippet bdi:m\n\ + -moz-border-image: ${1};\n\ +snippet bdrz:m\n\ + -moz-border-radius: ${1};\n\ +snippet bxsh:m+\n\ + -moz-box-shadow: ${1:0} ${2:0} ${3:0} #${4:000};\n\ +snippet bxsh:m\n\ + -moz-box-shadow: ${1};\n\ +snippet bdi:w+\n\ + -webkit-border-image: url(${1}) ${2:0} ${3:0} ${4:0} ${5:0} ${6:stretch} ${7:stretch};\n\ +snippet bdi:w\n\ + -webkit-border-image: ${1};\n\ +snippet bdrz:w\n\ + -webkit-border-radius: ${1};\n\ +snippet bxsh:w+\n\ + -webkit-box-shadow: ${1:0} ${2:0} ${3:0} #${4:000};\n\ +snippet bxsh:w\n\ + -webkit-box-shadow: ${1};\n\ +snippet @f\n\ + @font-face {\n\ + font-family: ${1};\n\ + src: url(${2});\n\ + }\n\ +snippet @i\n\ + @import url(${1});\n\ +snippet @m\n\ + @media ${1:print} {\n\ + ${2}\n\ + }\n\ +snippet bg+\n\ + background: #${1:FFF} url(${2}) ${3:0} ${4:0} ${5:no-repeat};\n\ +snippet bga\n\ + background-attachment: ${1};\n\ +snippet bga:f\n\ + background-attachment: fixed;\n\ +snippet bga:s\n\ + background-attachment: scroll;\n\ +snippet bgbk\n\ + background-break: ${1};\n\ +snippet bgbk:bb\n\ + background-break: bounding-box;\n\ +snippet bgbk:c\n\ + background-break: continuous;\n\ +snippet bgbk:eb\n\ + background-break: each-box;\n\ +snippet bgcp\n\ + background-clip: ${1};\n\ +snippet bgcp:bb\n\ + background-clip: border-box;\n\ +snippet bgcp:cb\n\ + background-clip: content-box;\n\ +snippet bgcp:nc\n\ + background-clip: no-clip;\n\ +snippet bgcp:pb\n\ + background-clip: padding-box;\n\ +snippet bgc\n\ + background-color: #${1:FFF};\n\ +snippet bgc:t\n\ + background-color: transparent;\n\ +snippet bgi\n\ + background-image: url(${1});\n\ +snippet bgi:n\n\ + background-image: none;\n\ +snippet bgo\n\ + background-origin: ${1};\n\ +snippet bgo:bb\n\ + background-origin: border-box;\n\ +snippet bgo:cb\n\ + background-origin: content-box;\n\ +snippet bgo:pb\n\ + background-origin: padding-box;\n\ +snippet bgpx\n\ + background-position-x: ${1};\n\ +snippet bgpy\n\ + background-position-y: ${1};\n\ +snippet bgp\n\ + background-position: ${1:0} ${2:0};\n\ +snippet bgr\n\ + background-repeat: ${1};\n\ +snippet bgr:n\n\ + background-repeat: no-repeat;\n\ +snippet bgr:x\n\ + background-repeat: repeat-x;\n\ +snippet bgr:y\n\ + background-repeat: repeat-y;\n\ +snippet bgr:r\n\ + background-repeat: repeat;\n\ +snippet bgz\n\ + background-size: ${1};\n\ +snippet bgz:a\n\ + background-size: auto;\n\ +snippet bgz:ct\n\ + background-size: contain;\n\ +snippet bgz:cv\n\ + background-size: cover;\n\ +snippet bg\n\ + background: ${1};\n\ +snippet bg:ie\n\ + filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='${1}',sizingMethod='${2:crop}');\n\ +snippet bg:n\n\ + background: none;\n\ +snippet bd+\n\ + border: ${1:1px} ${2:solid} #${3:000};\n\ +snippet bdb+\n\ + border-bottom: ${1:1px} ${2:solid} #${3:000};\n\ +snippet bdbc\n\ + border-bottom-color: #${1:000};\n\ +snippet bdbi\n\ + border-bottom-image: url(${1});\n\ +snippet bdbi:n\n\ + border-bottom-image: none;\n\ +snippet bdbli\n\ + border-bottom-left-image: url(${1});\n\ +snippet bdbli:c\n\ + border-bottom-left-image: continue;\n\ +snippet bdbli:n\n\ + border-bottom-left-image: none;\n\ +snippet bdblrz\n\ + border-bottom-left-radius: ${1};\n\ +snippet bdbri\n\ + border-bottom-right-image: url(${1});\n\ +snippet bdbri:c\n\ + border-bottom-right-image: continue;\n\ +snippet bdbri:n\n\ + border-bottom-right-image: none;\n\ +snippet bdbrrz\n\ + border-bottom-right-radius: ${1};\n\ +snippet bdbs\n\ + border-bottom-style: ${1};\n\ +snippet bdbs:n\n\ + border-bottom-style: none;\n\ +snippet bdbw\n\ + border-bottom-width: ${1};\n\ +snippet bdb\n\ + border-bottom: ${1};\n\ +snippet bdb:n\n\ + border-bottom: none;\n\ +snippet bdbk\n\ + border-break: ${1};\n\ +snippet bdbk:c\n\ + border-break: close;\n\ +snippet bdcl\n\ + border-collapse: ${1};\n\ +snippet bdcl:c\n\ + border-collapse: collapse;\n\ +snippet bdcl:s\n\ + border-collapse: separate;\n\ +snippet bdc\n\ + border-color: #${1:000};\n\ +snippet bdci\n\ + border-corner-image: url(${1});\n\ +snippet bdci:c\n\ + border-corner-image: continue;\n\ +snippet bdci:n\n\ + border-corner-image: none;\n\ +snippet bdf\n\ + border-fit: ${1};\n\ +snippet bdf:c\n\ + border-fit: clip;\n\ +snippet bdf:of\n\ + border-fit: overwrite;\n\ +snippet bdf:ow\n\ + border-fit: overwrite;\n\ +snippet bdf:r\n\ + border-fit: repeat;\n\ +snippet bdf:sc\n\ + border-fit: scale;\n\ +snippet bdf:sp\n\ + border-fit: space;\n\ +snippet bdf:st\n\ + border-fit: stretch;\n\ +snippet bdi\n\ + border-image: url(${1}) ${2:0} ${3:0} ${4:0} ${5:0} ${6:stretch} ${7:stretch};\n\ +snippet bdi:n\n\ + border-image: none;\n\ +snippet bdl+\n\ + border-left: ${1:1px} ${2:solid} #${3:000};\n\ +snippet bdlc\n\ + border-left-color: #${1:000};\n\ +snippet bdli\n\ + border-left-image: url(${1});\n\ +snippet bdli:n\n\ + border-left-image: none;\n\ +snippet bdls\n\ + border-left-style: ${1};\n\ +snippet bdls:n\n\ + border-left-style: none;\n\ +snippet bdlw\n\ + border-left-width: ${1};\n\ +snippet bdl\n\ + border-left: ${1};\n\ +snippet bdl:n\n\ + border-left: none;\n\ +snippet bdlt\n\ + border-length: ${1};\n\ +snippet bdlt:a\n\ + border-length: auto;\n\ +snippet bdrz\n\ + border-radius: ${1};\n\ +snippet bdr+\n\ + border-right: ${1:1px} ${2:solid} #${3:000};\n\ +snippet bdrc\n\ + border-right-color: #${1:000};\n\ +snippet bdri\n\ + border-right-image: url(${1});\n\ +snippet bdri:n\n\ + border-right-image: none;\n\ +snippet bdrs\n\ + border-right-style: ${1};\n\ +snippet bdrs:n\n\ + border-right-style: none;\n\ +snippet bdrw\n\ + border-right-width: ${1};\n\ +snippet bdr\n\ + border-right: ${1};\n\ +snippet bdr:n\n\ + border-right: none;\n\ +snippet bdsp\n\ + border-spacing: ${1};\n\ +snippet bds\n\ + border-style: ${1};\n\ +snippet bds:ds\n\ + border-style: dashed;\n\ +snippet bds:dtds\n\ + border-style: dot-dash;\n\ +snippet bds:dtdtds\n\ + border-style: dot-dot-dash;\n\ +snippet bds:dt\n\ + border-style: dotted;\n\ +snippet bds:db\n\ + border-style: double;\n\ +snippet bds:g\n\ + border-style: groove;\n\ +snippet bds:h\n\ + border-style: hidden;\n\ +snippet bds:i\n\ + border-style: inset;\n\ +snippet bds:n\n\ + border-style: none;\n\ +snippet bds:o\n\ + border-style: outset;\n\ +snippet bds:r\n\ + border-style: ridge;\n\ +snippet bds:s\n\ + border-style: solid;\n\ +snippet bds:w\n\ + border-style: wave;\n\ +snippet bdt+\n\ + border-top: ${1:1px} ${2:solid} #${3:000};\n\ +snippet bdtc\n\ + border-top-color: #${1:000};\n\ +snippet bdti\n\ + border-top-image: url(${1});\n\ +snippet bdti:n\n\ + border-top-image: none;\n\ +snippet bdtli\n\ + border-top-left-image: url(${1});\n\ +snippet bdtli:c\n\ + border-corner-image: continue;\n\ +snippet bdtli:n\n\ + border-corner-image: none;\n\ +snippet bdtlrz\n\ + border-top-left-radius: ${1};\n\ +snippet bdtri\n\ + border-top-right-image: url(${1});\n\ +snippet bdtri:c\n\ + border-top-right-image: continue;\n\ +snippet bdtri:n\n\ + border-top-right-image: none;\n\ +snippet bdtrrz\n\ + border-top-right-radius: ${1};\n\ +snippet bdts\n\ + border-top-style: ${1};\n\ +snippet bdts:n\n\ + border-top-style: none;\n\ +snippet bdtw\n\ + border-top-width: ${1};\n\ +snippet bdt\n\ + border-top: ${1};\n\ +snippet bdt:n\n\ + border-top: none;\n\ +snippet bdw\n\ + border-width: ${1};\n\ +snippet bd\n\ + border: ${1};\n\ +snippet bd:n\n\ + border: none;\n\ +snippet b\n\ + bottom: ${1};\n\ +snippet b:a\n\ + bottom: auto;\n\ +snippet bxsh+\n\ + box-shadow: ${1:0} ${2:0} ${3:0} #${4:000};\n\ +snippet bxsh\n\ + box-shadow: ${1};\n\ +snippet bxsh:n\n\ + box-shadow: none;\n\ +snippet bxz\n\ + box-sizing: ${1};\n\ +snippet bxz:bb\n\ + box-sizing: border-box;\n\ +snippet bxz:cb\n\ + box-sizing: content-box;\n\ +snippet cps\n\ + caption-side: ${1};\n\ +snippet cps:b\n\ + caption-side: bottom;\n\ +snippet cps:t\n\ + caption-side: top;\n\ +snippet cl\n\ + clear: ${1};\n\ +snippet cl:b\n\ + clear: both;\n\ +snippet cl:l\n\ + clear: left;\n\ +snippet cl:n\n\ + clear: none;\n\ +snippet cl:r\n\ + clear: right;\n\ +snippet cp\n\ + clip: ${1};\n\ +snippet cp:a\n\ + clip: auto;\n\ +snippet cp:r\n\ + clip: rect(${1:0} ${2:0} ${3:0} ${4:0});\n\ +snippet c\n\ + color: #${1:000};\n\ +snippet ct\n\ + content: ${1};\n\ +snippet ct:a\n\ + content: attr(${1});\n\ +snippet ct:cq\n\ + content: close-quote;\n\ +snippet ct:c\n\ + content: counter(${1});\n\ +snippet ct:cs\n\ + content: counters(${1});\n\ +snippet ct:ncq\n\ + content: no-close-quote;\n\ +snippet ct:noq\n\ + content: no-open-quote;\n\ +snippet ct:n\n\ + content: normal;\n\ +snippet ct:oq\n\ + content: open-quote;\n\ +snippet coi\n\ + counter-increment: ${1};\n\ +snippet cor\n\ + counter-reset: ${1};\n\ +snippet cur\n\ + cursor: ${1};\n\ +snippet cur:a\n\ + cursor: auto;\n\ +snippet cur:c\n\ + cursor: crosshair;\n\ +snippet cur:d\n\ + cursor: default;\n\ +snippet cur:ha\n\ + cursor: hand;\n\ +snippet cur:he\n\ + cursor: help;\n\ +snippet cur:m\n\ + cursor: move;\n\ +snippet cur:p\n\ + cursor: pointer;\n\ +snippet cur:t\n\ + cursor: text;\n\ +snippet d\n\ + display: ${1};\n\ +snippet d:mib\n\ + display: -moz-inline-box;\n\ +snippet d:mis\n\ + display: -moz-inline-stack;\n\ +snippet d:b\n\ + display: block;\n\ +snippet d:cp\n\ + display: compact;\n\ +snippet d:ib\n\ + display: inline-block;\n\ +snippet d:itb\n\ + display: inline-table;\n\ +snippet d:i\n\ + display: inline;\n\ +snippet d:li\n\ + display: list-item;\n\ +snippet d:n\n\ + display: none;\n\ +snippet d:ri\n\ + display: run-in;\n\ +snippet d:tbcp\n\ + display: table-caption;\n\ +snippet d:tbc\n\ + display: table-cell;\n\ +snippet d:tbclg\n\ + display: table-column-group;\n\ +snippet d:tbcl\n\ + display: table-column;\n\ +snippet d:tbfg\n\ + display: table-footer-group;\n\ +snippet d:tbhg\n\ + display: table-header-group;\n\ +snippet d:tbrg\n\ + display: table-row-group;\n\ +snippet d:tbr\n\ + display: table-row;\n\ +snippet d:tb\n\ + display: table;\n\ +snippet ec\n\ + empty-cells: ${1};\n\ +snippet ec:h\n\ + empty-cells: hide;\n\ +snippet ec:s\n\ + empty-cells: show;\n\ +snippet exp\n\ + expression()\n\ +snippet fl\n\ + float: ${1};\n\ +snippet fl:l\n\ + float: left;\n\ +snippet fl:n\n\ + float: none;\n\ +snippet fl:r\n\ + float: right;\n\ +snippet f+\n\ + font: ${1:1em} ${2:Arial},${3:sans-serif};\n\ +snippet fef\n\ + font-effect: ${1};\n\ +snippet fef:eb\n\ + font-effect: emboss;\n\ +snippet fef:eg\n\ + font-effect: engrave;\n\ +snippet fef:n\n\ + font-effect: none;\n\ +snippet fef:o\n\ + font-effect: outline;\n\ +snippet femp\n\ + font-emphasize-position: ${1};\n\ +snippet femp:a\n\ + font-emphasize-position: after;\n\ +snippet femp:b\n\ + font-emphasize-position: before;\n\ +snippet fems\n\ + font-emphasize-style: ${1};\n\ +snippet fems:ac\n\ + font-emphasize-style: accent;\n\ +snippet fems:c\n\ + font-emphasize-style: circle;\n\ +snippet fems:ds\n\ + font-emphasize-style: disc;\n\ +snippet fems:dt\n\ + font-emphasize-style: dot;\n\ +snippet fems:n\n\ + font-emphasize-style: none;\n\ +snippet fem\n\ + font-emphasize: ${1};\n\ +snippet ff\n\ + font-family: ${1};\n\ +snippet ff:c\n\ + font-family: ${1:'Monotype Corsiva','Comic Sans MS'},cursive;\n\ +snippet ff:f\n\ + font-family: ${1:Capitals,Impact},fantasy;\n\ +snippet ff:m\n\ + font-family: ${1:Monaco,'Courier New'},monospace;\n\ +snippet ff:ss\n\ + font-family: ${1:Helvetica,Arial},sans-serif;\n\ +snippet ff:s\n\ + font-family: ${1:Georgia,'Times New Roman'},serif;\n\ +snippet fza\n\ + font-size-adjust: ${1};\n\ +snippet fza:n\n\ + font-size-adjust: none;\n\ +snippet fz\n\ + font-size: ${1};\n\ +snippet fsm\n\ + font-smooth: ${1};\n\ +snippet fsm:aw\n\ + font-smooth: always;\n\ +snippet fsm:a\n\ + font-smooth: auto;\n\ +snippet fsm:n\n\ + font-smooth: never;\n\ +snippet fst\n\ + font-stretch: ${1};\n\ +snippet fst:c\n\ + font-stretch: condensed;\n\ +snippet fst:e\n\ + font-stretch: expanded;\n\ +snippet fst:ec\n\ + font-stretch: extra-condensed;\n\ +snippet fst:ee\n\ + font-stretch: extra-expanded;\n\ +snippet fst:n\n\ + font-stretch: normal;\n\ +snippet fst:sc\n\ + font-stretch: semi-condensed;\n\ +snippet fst:se\n\ + font-stretch: semi-expanded;\n\ +snippet fst:uc\n\ + font-stretch: ultra-condensed;\n\ +snippet fst:ue\n\ + font-stretch: ultra-expanded;\n\ +snippet fs\n\ + font-style: ${1};\n\ +snippet fs:i\n\ + font-style: italic;\n\ +snippet fs:n\n\ + font-style: normal;\n\ +snippet fs:o\n\ + font-style: oblique;\n\ +snippet fv\n\ + font-variant: ${1};\n\ +snippet fv:n\n\ + font-variant: normal;\n\ +snippet fv:sc\n\ + font-variant: small-caps;\n\ +snippet fw\n\ + font-weight: ${1};\n\ +snippet fw:b\n\ + font-weight: bold;\n\ +snippet fw:br\n\ + font-weight: bolder;\n\ +snippet fw:lr\n\ + font-weight: lighter;\n\ +snippet fw:n\n\ + font-weight: normal;\n\ +snippet f\n\ + font: ${1};\n\ +snippet h\n\ + height: ${1};\n\ +snippet h:a\n\ + height: auto;\n\ +snippet l\n\ + left: ${1};\n\ +snippet l:a\n\ + left: auto;\n\ +snippet lts\n\ + letter-spacing: ${1};\n\ +snippet lh\n\ + line-height: ${1};\n\ +snippet lisi\n\ + list-style-image: url(${1});\n\ +snippet lisi:n\n\ + list-style-image: none;\n\ +snippet lisp\n\ + list-style-position: ${1};\n\ +snippet lisp:i\n\ + list-style-position: inside;\n\ +snippet lisp:o\n\ + list-style-position: outside;\n\ +snippet list\n\ + list-style-type: ${1};\n\ +snippet list:c\n\ + list-style-type: circle;\n\ +snippet list:dclz\n\ + list-style-type: decimal-leading-zero;\n\ +snippet list:dc\n\ + list-style-type: decimal;\n\ +snippet list:d\n\ + list-style-type: disc;\n\ +snippet list:lr\n\ + list-style-type: lower-roman;\n\ +snippet list:n\n\ + list-style-type: none;\n\ +snippet list:s\n\ + list-style-type: square;\n\ +snippet list:ur\n\ + list-style-type: upper-roman;\n\ +snippet lis\n\ + list-style: ${1};\n\ +snippet lis:n\n\ + list-style: none;\n\ +snippet mb\n\ + margin-bottom: ${1};\n\ +snippet mb:a\n\ + margin-bottom: auto;\n\ +snippet ml\n\ + margin-left: ${1};\n\ +snippet ml:a\n\ + margin-left: auto;\n\ +snippet mr\n\ + margin-right: ${1};\n\ +snippet mr:a\n\ + margin-right: auto;\n\ +snippet mt\n\ + margin-top: ${1};\n\ +snippet mt:a\n\ + margin-top: auto;\n\ +snippet m\n\ + margin: ${1};\n\ +snippet m:4\n\ + margin: ${1:0} ${2:0} ${3:0} ${4:0};\n\ +snippet m:3\n\ + margin: ${1:0} ${2:0} ${3:0};\n\ +snippet m:2\n\ + margin: ${1:0} ${2:0};\n\ +snippet m:0\n\ + margin: 0;\n\ +snippet m:a\n\ + margin: auto;\n\ +snippet mah\n\ + max-height: ${1};\n\ +snippet mah:n\n\ + max-height: none;\n\ +snippet maw\n\ + max-width: ${1};\n\ +snippet maw:n\n\ + max-width: none;\n\ +snippet mih\n\ + min-height: ${1};\n\ +snippet miw\n\ + min-width: ${1};\n\ +snippet op\n\ + opacity: ${1};\n\ +snippet op:ie\n\ + filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=${1:100});\n\ +snippet op:ms\n\ + -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=${1:100})';\n\ +snippet orp\n\ + orphans: ${1};\n\ +snippet o+\n\ + outline: ${1:1px} ${2:solid} #${3:000};\n\ +snippet oc\n\ + outline-color: ${1:#000};\n\ +snippet oc:i\n\ + outline-color: invert;\n\ +snippet oo\n\ + outline-offset: ${1};\n\ +snippet os\n\ + outline-style: ${1};\n\ +snippet ow\n\ + outline-width: ${1};\n\ +snippet o\n\ + outline: ${1};\n\ +snippet o:n\n\ + outline: none;\n\ +snippet ovs\n\ + overflow-style: ${1};\n\ +snippet ovs:a\n\ + overflow-style: auto;\n\ +snippet ovs:mq\n\ + overflow-style: marquee;\n\ +snippet ovs:mv\n\ + overflow-style: move;\n\ +snippet ovs:p\n\ + overflow-style: panner;\n\ +snippet ovs:s\n\ + overflow-style: scrollbar;\n\ +snippet ovx\n\ + overflow-x: ${1};\n\ +snippet ovx:a\n\ + overflow-x: auto;\n\ +snippet ovx:h\n\ + overflow-x: hidden;\n\ +snippet ovx:s\n\ + overflow-x: scroll;\n\ +snippet ovx:v\n\ + overflow-x: visible;\n\ +snippet ovy\n\ + overflow-y: ${1};\n\ +snippet ovy:a\n\ + overflow-y: auto;\n\ +snippet ovy:h\n\ + overflow-y: hidden;\n\ +snippet ovy:s\n\ + overflow-y: scroll;\n\ +snippet ovy:v\n\ + overflow-y: visible;\n\ +snippet ov\n\ + overflow: ${1};\n\ +snippet ov:a\n\ + overflow: auto;\n\ +snippet ov:h\n\ + overflow: hidden;\n\ +snippet ov:s\n\ + overflow: scroll;\n\ +snippet ov:v\n\ + overflow: visible;\n\ +snippet pb\n\ + padding-bottom: ${1};\n\ +snippet pl\n\ + padding-left: ${1};\n\ +snippet pr\n\ + padding-right: ${1};\n\ +snippet pt\n\ + padding-top: ${1};\n\ +snippet p\n\ + padding: ${1};\n\ +snippet p:4\n\ + padding: ${1:0} ${2:0} ${3:0} ${4:0};\n\ +snippet p:3\n\ + padding: ${1:0} ${2:0} ${3:0};\n\ +snippet p:2\n\ + padding: ${1:0} ${2:0};\n\ +snippet p:0\n\ + padding: 0;\n\ +snippet pgba\n\ + page-break-after: ${1};\n\ +snippet pgba:aw\n\ + page-break-after: always;\n\ +snippet pgba:a\n\ + page-break-after: auto;\n\ +snippet pgba:l\n\ + page-break-after: left;\n\ +snippet pgba:r\n\ + page-break-after: right;\n\ +snippet pgbb\n\ + page-break-before: ${1};\n\ +snippet pgbb:aw\n\ + page-break-before: always;\n\ +snippet pgbb:a\n\ + page-break-before: auto;\n\ +snippet pgbb:l\n\ + page-break-before: left;\n\ +snippet pgbb:r\n\ + page-break-before: right;\n\ +snippet pgbi\n\ + page-break-inside: ${1};\n\ +snippet pgbi:a\n\ + page-break-inside: auto;\n\ +snippet pgbi:av\n\ + page-break-inside: avoid;\n\ +snippet pos\n\ + position: ${1};\n\ +snippet pos:a\n\ + position: absolute;\n\ +snippet pos:f\n\ + position: fixed;\n\ +snippet pos:r\n\ + position: relative;\n\ +snippet pos:s\n\ + position: static;\n\ +snippet q\n\ + quotes: ${1};\n\ +snippet q:en\n\ + quotes: '\\201C' '\\201D' '\\2018' '\\2019';\n\ +snippet q:n\n\ + quotes: none;\n\ +snippet q:ru\n\ + quotes: '\\00AB' '\\00BB' '\\201E' '\\201C';\n\ +snippet rz\n\ + resize: ${1};\n\ +snippet rz:b\n\ + resize: both;\n\ +snippet rz:h\n\ + resize: horizontal;\n\ +snippet rz:n\n\ + resize: none;\n\ +snippet rz:v\n\ + resize: vertical;\n\ +snippet r\n\ + right: ${1};\n\ +snippet r:a\n\ + right: auto;\n\ +snippet tbl\n\ + table-layout: ${1};\n\ +snippet tbl:a\n\ + table-layout: auto;\n\ +snippet tbl:f\n\ + table-layout: fixed;\n\ +snippet tal\n\ + text-align-last: ${1};\n\ +snippet tal:a\n\ + text-align-last: auto;\n\ +snippet tal:c\n\ + text-align-last: center;\n\ +snippet tal:l\n\ + text-align-last: left;\n\ +snippet tal:r\n\ + text-align-last: right;\n\ +snippet ta\n\ + text-align: ${1};\n\ +snippet ta:c\n\ + text-align: center;\n\ +snippet ta:l\n\ + text-align: left;\n\ +snippet ta:r\n\ + text-align: right;\n\ +snippet td\n\ + text-decoration: ${1};\n\ +snippet td:l\n\ + text-decoration: line-through;\n\ +snippet td:n\n\ + text-decoration: none;\n\ +snippet td:o\n\ + text-decoration: overline;\n\ +snippet td:u\n\ + text-decoration: underline;\n\ +snippet te\n\ + text-emphasis: ${1};\n\ +snippet te:ac\n\ + text-emphasis: accent;\n\ +snippet te:a\n\ + text-emphasis: after;\n\ +snippet te:b\n\ + text-emphasis: before;\n\ +snippet te:c\n\ + text-emphasis: circle;\n\ +snippet te:ds\n\ + text-emphasis: disc;\n\ +snippet te:dt\n\ + text-emphasis: dot;\n\ +snippet te:n\n\ + text-emphasis: none;\n\ +snippet th\n\ + text-height: ${1};\n\ +snippet th:a\n\ + text-height: auto;\n\ +snippet th:f\n\ + text-height: font-size;\n\ +snippet th:m\n\ + text-height: max-size;\n\ +snippet th:t\n\ + text-height: text-size;\n\ +snippet ti\n\ + text-indent: ${1};\n\ +snippet ti:-\n\ + text-indent: -9999px;\n\ +snippet tj\n\ + text-justify: ${1};\n\ +snippet tj:a\n\ + text-justify: auto;\n\ +snippet tj:d\n\ + text-justify: distribute;\n\ +snippet tj:ic\n\ + text-justify: inter-cluster;\n\ +snippet tj:ii\n\ + text-justify: inter-ideograph;\n\ +snippet tj:iw\n\ + text-justify: inter-word;\n\ +snippet tj:k\n\ + text-justify: kashida;\n\ +snippet tj:t\n\ + text-justify: tibetan;\n\ +snippet to+\n\ + text-outline: ${1:0} ${2:0} #${3:000};\n\ +snippet to\n\ + text-outline: ${1};\n\ +snippet to:n\n\ + text-outline: none;\n\ +snippet tr\n\ + text-replace: ${1};\n\ +snippet tr:n\n\ + text-replace: none;\n\ +snippet tsh+\n\ + text-shadow: ${1:0} ${2:0} ${3:0} #${4:000};\n\ +snippet tsh\n\ + text-shadow: ${1};\n\ +snippet tsh:n\n\ + text-shadow: none;\n\ +snippet tt\n\ + text-transform: ${1};\n\ +snippet tt:c\n\ + text-transform: capitalize;\n\ +snippet tt:l\n\ + text-transform: lowercase;\n\ +snippet tt:n\n\ + text-transform: none;\n\ +snippet tt:u\n\ + text-transform: uppercase;\n\ +snippet tw\n\ + text-wrap: ${1};\n\ +snippet tw:no\n\ + text-wrap: none;\n\ +snippet tw:n\n\ + text-wrap: normal;\n\ +snippet tw:s\n\ + text-wrap: suppress;\n\ +snippet tw:u\n\ + text-wrap: unrestricted;\n\ +snippet t\n\ + top: ${1};\n\ +snippet t:a\n\ + top: auto;\n\ +snippet va\n\ + vertical-align: ${1};\n\ +snippet va:bl\n\ + vertical-align: baseline;\n\ +snippet va:b\n\ + vertical-align: bottom;\n\ +snippet va:m\n\ + vertical-align: middle;\n\ +snippet va:sub\n\ + vertical-align: sub;\n\ +snippet va:sup\n\ + vertical-align: super;\n\ +snippet va:tb\n\ + vertical-align: text-bottom;\n\ +snippet va:tt\n\ + vertical-align: text-top;\n\ +snippet va:t\n\ + vertical-align: top;\n\ +snippet v\n\ + visibility: ${1};\n\ +snippet v:c\n\ + visibility: collapse;\n\ +snippet v:h\n\ + visibility: hidden;\n\ +snippet v:v\n\ + visibility: visible;\n\ +snippet whsc\n\ + white-space-collapse: ${1};\n\ +snippet whsc:ba\n\ + white-space-collapse: break-all;\n\ +snippet whsc:bs\n\ + white-space-collapse: break-strict;\n\ +snippet whsc:k\n\ + white-space-collapse: keep-all;\n\ +snippet whsc:l\n\ + white-space-collapse: loose;\n\ +snippet whsc:n\n\ + white-space-collapse: normal;\n\ +snippet whs\n\ + white-space: ${1};\n\ +snippet whs:n\n\ + white-space: normal;\n\ +snippet whs:nw\n\ + white-space: nowrap;\n\ +snippet whs:pl\n\ + white-space: pre-line;\n\ +snippet whs:pw\n\ + white-space: pre-wrap;\n\ +snippet whs:p\n\ + white-space: pre;\n\ +snippet wid\n\ + widows: ${1};\n\ +snippet w\n\ + width: ${1};\n\ +snippet w:a\n\ + width: auto;\n\ +snippet wob\n\ + word-break: ${1};\n\ +snippet wob:ba\n\ + word-break: break-all;\n\ +snippet wob:bs\n\ + word-break: break-strict;\n\ +snippet wob:k\n\ + word-break: keep-all;\n\ +snippet wob:l\n\ + word-break: loose;\n\ +snippet wob:n\n\ + word-break: normal;\n\ +snippet wos\n\ + word-spacing: ${1};\n\ +snippet wow\n\ + word-wrap: ${1};\n\ +snippet wow:no\n\ + word-wrap: none;\n\ +snippet wow:n\n\ + word-wrap: normal;\n\ +snippet wow:s\n\ + word-wrap: suppress;\n\ +snippet wow:u\n\ + word-wrap: unrestricted;\n\ +snippet z\n\ + z-index: ${1};\n\ +snippet z:a\n\ + z-index: auto;\n\ +snippet zoo\n\ + zoom: 1;\n\ +"; +exports.scope = "css"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/curly.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/curly.js new file mode 100644 index 00000000..2bf82d9d --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/curly.js @@ -0,0 +1,7 @@ +define("ace/snippets/curly",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "curly"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/d.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/d.js new file mode 100644 index 00000000..bf78cfdd --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/d.js @@ -0,0 +1,7 @@ +define("ace/snippets/d",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "d"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/dart.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/dart.js new file mode 100644 index 00000000..9c12f917 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/dart.js @@ -0,0 +1,90 @@ +define("ace/snippets/dart",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet lib\n\ + library ${1};\n\ + ${2}\n\ +snippet im\n\ + import '${1}';\n\ + ${2}\n\ +snippet pa\n\ + part '${1}';\n\ + ${2}\n\ +snippet pao\n\ + part of ${1};\n\ + ${2}\n\ +snippet main\n\ + void main() {\n\ + ${1:/* code */}\n\ + }\n\ +snippet st\n\ + static ${1}\n\ +snippet fi\n\ + final ${1}\n\ +snippet re\n\ + return ${1}\n\ +snippet br\n\ + break;\n\ +snippet th\n\ + throw ${1}\n\ +snippet cl\n\ + class ${1:`Filename(\"\", \"untitled\")`} ${2}\n\ +snippet imp\n\ + implements ${1}\n\ +snippet ext\n\ + extends ${1}\n\ +snippet if\n\ + if (${1:true}) {\n\ + ${2}\n\ + }\n\ +snippet ife\n\ + if (${1:true}) {\n\ + ${2}\n\ + } else {\n\ + ${3}\n\ + }\n\ +snippet el\n\ + else\n\ +snippet sw\n\ + switch (${1}) {\n\ + ${2}\n\ + }\n\ +snippet cs\n\ + case ${1}:\n\ + ${2}\n\ +snippet de\n\ + default:\n\ + ${1}\n\ +snippet for\n\ + for (var ${2:i} = 0, len = ${1:things}.length; $2 < len; ${3:++}$2) {\n\ + ${4:$1[$2]}\n\ + }\n\ +snippet fore\n\ + for (final ${2:item} in ${1:itemList}) {\n\ + ${3:/* code */}\n\ + }\n\ +snippet wh\n\ + while (${1:/* condition */}) {\n\ + ${2:/* code */}\n\ + }\n\ +snippet dowh\n\ + do {\n\ + ${2:/* code */}\n\ + } while (${1:/* condition */});\n\ +snippet as\n\ + assert(${1:/* condition */});\n\ +snippet try\n\ + try {\n\ + ${2}\n\ + } catch (${1:Exception e}) {\n\ + }\n\ +snippet tryf\n\ + try {\n\ + ${2}\n\ + } catch (${1:Exception e}) {\n\ + } finally {\n\ + }\n\ +"; +exports.scope = "dart"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/diff.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/diff.js new file mode 100644 index 00000000..ffabc8f2 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/diff.js @@ -0,0 +1,18 @@ +define("ace/snippets/diff",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# DEP-3 (http://dep.debian.net/deps/dep3/) style patch header\n\ +snippet header DEP-3 style header\n\ + Description: ${1}\n\ + Origin: ${2:vendor|upstream|other}, ${3:url of the original patch}\n\ + Bug: ${4:url in upstream bugtracker}\n\ + Forwarded: ${5:no|not-needed|url}\n\ + Author: ${6:`g:snips_author`}\n\ + Reviewed-by: ${7:name and email}\n\ + Last-Update: ${8:`strftime(\"%Y-%m-%d\")`}\n\ + Applied-Upstream: ${9:upstream version|url|commit}\n\ +\n\ +"; +exports.scope = "diff"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/django.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/django.js new file mode 100644 index 00000000..f82e0a7f --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/django.js @@ -0,0 +1,115 @@ +define("ace/snippets/django",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# Model Fields\n\ +\n\ +# Note: Optional arguments are using defaults that match what Django will use\n\ +# as a default, e.g. with max_length fields. Doing this as a form of self\n\ +# documentation and to make it easy to know whether you should override the\n\ +# default or not.\n\ +\n\ +# Note: Optional arguments that are booleans will use the opposite since you\n\ +# can either not specify them, or override them, e.g. auto_now_add=False.\n\ +\n\ +snippet auto\n\ + ${1:FIELDNAME} = models.AutoField(${2})\n\ +snippet bool\n\ + ${1:FIELDNAME} = models.BooleanField(${2:default=True})\n\ +snippet char\n\ + ${1:FIELDNAME} = models.CharField(max_length=${2}${3:, blank=True})\n\ +snippet comma\n\ + ${1:FIELDNAME} = models.CommaSeparatedIntegerField(max_length=${2}${3:, blank=True})\n\ +snippet date\n\ + ${1:FIELDNAME} = models.DateField(${2:auto_now_add=True, auto_now=True}${3:, blank=True, null=True})\n\ +snippet datetime\n\ + ${1:FIELDNAME} = models.DateTimeField(${2:auto_now_add=True, auto_now=True}${3:, blank=True, null=True})\n\ +snippet decimal\n\ + ${1:FIELDNAME} = models.DecimalField(max_digits=${2}, decimal_places=${3})\n\ +snippet email\n\ + ${1:FIELDNAME} = models.EmailField(max_length=${2:75}${3:, blank=True})\n\ +snippet file\n\ + ${1:FIELDNAME} = models.FileField(upload_to=${2:path/for/upload}${3:, max_length=100})\n\ +snippet filepath\n\ + ${1:FIELDNAME} = models.FilePathField(path=${2:\"/abs/path/to/dir\"}${3:, max_length=100}${4:, match=\"*.ext\"}${5:, recursive=True}${6:, blank=True, })\n\ +snippet float\n\ + ${1:FIELDNAME} = models.FloatField(${2})\n\ +snippet image\n\ + ${1:FIELDNAME} = models.ImageField(upload_to=${2:path/for/upload}${3:, height_field=height, width_field=width}${4:, max_length=100})\n\ +snippet int\n\ + ${1:FIELDNAME} = models.IntegerField(${2})\n\ +snippet ip\n\ + ${1:FIELDNAME} = models.IPAddressField(${2})\n\ +snippet nullbool\n\ + ${1:FIELDNAME} = models.NullBooleanField(${2})\n\ +snippet posint\n\ + ${1:FIELDNAME} = models.PositiveIntegerField(${2})\n\ +snippet possmallint\n\ + ${1:FIELDNAME} = models.PositiveSmallIntegerField(${2})\n\ +snippet slug\n\ + ${1:FIELDNAME} = models.SlugField(max_length=${2:50}${3:, blank=True})\n\ +snippet smallint\n\ + ${1:FIELDNAME} = models.SmallIntegerField(${2})\n\ +snippet text\n\ + ${1:FIELDNAME} = models.TextField(${2:blank=True})\n\ +snippet time\n\ + ${1:FIELDNAME} = models.TimeField(${2:auto_now_add=True, auto_now=True}${3:, blank=True, null=True})\n\ +snippet url\n\ + ${1:FIELDNAME} = models.URLField(${2:verify_exists=False}${3:, max_length=200}${4:, blank=True})\n\ +snippet xml\n\ + ${1:FIELDNAME} = models.XMLField(schema_path=${2:None}${3:, blank=True})\n\ +# Relational Fields\n\ +snippet fk\n\ + ${1:FIELDNAME} = models.ForeignKey(${2:OtherModel}${3:, related_name=''}${4:, limit_choices_to=}${5:, to_field=''})\n\ +snippet m2m\n\ + ${1:FIELDNAME} = models.ManyToManyField(${2:OtherModel}${3:, related_name=''}${4:, limit_choices_to=}${5:, symmetrical=False}${6:, through=''}${7:, db_table=''})\n\ +snippet o2o\n\ + ${1:FIELDNAME} = models.OneToOneField(${2:OtherModel}${3:, parent_link=True}${4:, related_name=''}${5:, limit_choices_to=}${6:, to_field=''})\n\ +\n\ +# Code Skeletons\n\ +\n\ +snippet form\n\ + class ${1:FormName}(forms.Form):\n\ + \"\"\"${2:docstring}\"\"\"\n\ + ${3}\n\ +\n\ +snippet model\n\ + class ${1:ModelName}(models.Model):\n\ + \"\"\"${2:docstring}\"\"\"\n\ + ${3}\n\ + \n\ + class Meta:\n\ + ${4}\n\ + \n\ + def __unicode__(self):\n\ + ${5}\n\ + \n\ + def save(self, force_insert=False, force_update=False):\n\ + ${6}\n\ + \n\ + @models.permalink\n\ + def get_absolute_url(self):\n\ + return ('${7:view_or_url_name}' ${8})\n\ +\n\ +snippet modeladmin\n\ + class ${1:ModelName}Admin(admin.ModelAdmin):\n\ + ${2}\n\ + \n\ + admin.site.register($1, $1Admin)\n\ + \n\ +snippet tabularinline\n\ + class ${1:ModelName}Inline(admin.TabularInline):\n\ + model = $1\n\ +\n\ +snippet stackedinline\n\ + class ${1:ModelName}Inline(admin.StackedInline):\n\ + model = $1\n\ +\n\ +snippet r2r\n\ + return render_to_response('${1:template.html}', {\n\ + ${2}\n\ + }${3:, context_instance=RequestContext(request)}\n\ + )\n\ +"; +exports.scope = "django"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/dockerfile.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/dockerfile.js new file mode 100644 index 00000000..75b4dedd --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/dockerfile.js @@ -0,0 +1,7 @@ +define("ace/snippets/dockerfile",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "dockerfile"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/dot.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/dot.js new file mode 100644 index 00000000..77b345c0 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/dot.js @@ -0,0 +1,7 @@ +define("ace/snippets/dot",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "dot"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/eiffel.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/eiffel.js new file mode 100644 index 00000000..2ff0e7d0 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/eiffel.js @@ -0,0 +1,7 @@ +define("ace/snippets/eiffel",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "eiffel"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ejs.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ejs.js new file mode 100644 index 00000000..41bc823c --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ejs.js @@ -0,0 +1,7 @@ +define("ace/snippets/ejs",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "ejs"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/elixir.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/elixir.js new file mode 100644 index 00000000..a866bf72 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/elixir.js @@ -0,0 +1,7 @@ +define("ace/snippets/elixir",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = ""; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/elm.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/elm.js new file mode 100644 index 00000000..f75be859 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/elm.js @@ -0,0 +1,7 @@ +define("ace/snippets/elm",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "elm"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/erlang.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/erlang.js new file mode 100644 index 00000000..b0d0c950 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/erlang.js @@ -0,0 +1,167 @@ +define("ace/snippets/erlang",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# module and export all\n\ +snippet mod\n\ + -module(${1:`Filename('', 'my')`}).\n\ + \n\ + -compile([export_all]).\n\ + \n\ + start() ->\n\ + ${2}\n\ + \n\ + stop() ->\n\ + ok.\n\ +# define directive\n\ +snippet def\n\ + -define(${1:macro}, ${2:body}).${3}\n\ +# export directive\n\ +snippet exp\n\ + -export([${1:function}/${2:arity}]).\n\ +# include directive\n\ +snippet inc\n\ + -include(\"${1:file}\").${2}\n\ +# behavior directive\n\ +snippet beh\n\ + -behaviour(${1:behaviour}).${2}\n\ +# if expression\n\ +snippet if\n\ + if\n\ + ${1:guard} ->\n\ + ${2:body}\n\ + end\n\ +# case expression\n\ +snippet case\n\ + case ${1:expression} of\n\ + ${2:pattern} ->\n\ + ${3:body};\n\ + end\n\ +# anonymous function\n\ +snippet fun\n\ + fun (${1:Parameters}) -> ${2:body} end${3}\n\ +# try...catch\n\ +snippet try\n\ + try\n\ + ${1}\n\ + catch\n\ + ${2:_:_} -> ${3:got_some_exception}\n\ + end\n\ +# record directive\n\ +snippet rec\n\ + -record(${1:record}, {\n\ + ${2:field}=${3:value}}).${4}\n\ +# todo comment\n\ +snippet todo\n\ + %% TODO: ${1}\n\ +## Snippets below (starting with '%') are in EDoc format.\n\ +## See http://www.erlang.org/doc/apps/edoc/chapter.html#id56887 for more details\n\ +# doc comment\n\ +snippet %d\n\ + %% @doc ${1}\n\ +# end of doc comment\n\ +snippet %e\n\ + %% @end\n\ +# specification comment\n\ +snippet %s\n\ + %% @spec ${1}\n\ +# private function marker\n\ +snippet %p\n\ + %% @private\n\ +# OTP application\n\ +snippet application\n\ + -module(${1:`Filename('', 'my')`}).\n\ +\n\ + -behaviour(application).\n\ +\n\ + -export([start/2, stop/1]).\n\ +\n\ + start(_Type, _StartArgs) ->\n\ + case ${2:root_supervisor}:start_link() of\n\ + {ok, Pid} ->\n\ + {ok, Pid};\n\ + Other ->\n\ + {error, Other}\n\ + end.\n\ +\n\ + stop(_State) ->\n\ + ok. \n\ +# OTP supervisor\n\ +snippet supervisor\n\ + -module(${1:`Filename('', 'my')`}).\n\ +\n\ + -behaviour(supervisor).\n\ +\n\ + %% API\n\ + -export([start_link/0]).\n\ +\n\ + %% Supervisor callbacks\n\ + -export([init/1]).\n\ +\n\ + -define(SERVER, ?MODULE).\n\ +\n\ + start_link() ->\n\ + supervisor:start_link({local, ?SERVER}, ?MODULE, []).\n\ +\n\ + init([]) ->\n\ + Server = {${2:my_server}, {$2, start_link, []},\n\ + permanent, 2000, worker, [$2]},\n\ + Children = [Server],\n\ + RestartStrategy = {one_for_one, 0, 1},\n\ + {ok, {RestartStrategy, Children}}.\n\ +# OTP gen_server\n\ +snippet gen_server\n\ + -module(${1:`Filename('', 'my')`}).\n\ +\n\ + -behaviour(gen_server).\n\ +\n\ + %% API\n\ + -export([\n\ + start_link/0\n\ + ]).\n\ +\n\ + %% gen_server callbacks\n\ + -export([init/1, handle_call/3, handle_cast/2, handle_info/2,\n\ + terminate/2, code_change/3]).\n\ +\n\ + -define(SERVER, ?MODULE).\n\ +\n\ + -record(state, {}).\n\ +\n\ + %%%===================================================================\n\ + %%% API\n\ + %%%===================================================================\n\ +\n\ + start_link() ->\n\ + gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).\n\ +\n\ + %%%===================================================================\n\ + %%% gen_server callbacks\n\ + %%%===================================================================\n\ +\n\ + init([]) ->\n\ + {ok, #state{}}.\n\ +\n\ + handle_call(_Request, _From, State) ->\n\ + Reply = ok,\n\ + {reply, Reply, State}.\n\ +\n\ + handle_cast(_Msg, State) ->\n\ + {noreply, State}.\n\ +\n\ + handle_info(_Info, State) ->\n\ + {noreply, State}.\n\ +\n\ + terminate(_Reason, _State) ->\n\ + ok.\n\ +\n\ + code_change(_OldVsn, State, _Extra) ->\n\ + {ok, State}.\n\ +\n\ + %%%===================================================================\n\ + %%% Internal functions\n\ + %%%===================================================================\n\ +\n\ +"; +exports.scope = "erlang"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/forth.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/forth.js new file mode 100644 index 00000000..f81b5a3f --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/forth.js @@ -0,0 +1,7 @@ +define("ace/snippets/forth",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "forth"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ftl.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ftl.js new file mode 100644 index 00000000..8f8e7c1d --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ftl.js @@ -0,0 +1,7 @@ +define("ace/snippets/ftl",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "ftl"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/gcode.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/gcode.js new file mode 100644 index 00000000..f00c381f --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/gcode.js @@ -0,0 +1,7 @@ +define("ace/snippets/gcode",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "gcode"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/gherkin.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/gherkin.js new file mode 100644 index 00000000..6b3de21c --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/gherkin.js @@ -0,0 +1,7 @@ +define("ace/snippets/gherkin",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "gherkin"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/gitignore.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/gitignore.js new file mode 100644 index 00000000..c9f18286 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/gitignore.js @@ -0,0 +1,7 @@ +define("ace/snippets/gitignore",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "gitignore"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/glsl.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/glsl.js new file mode 100644 index 00000000..fff970ff --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/glsl.js @@ -0,0 +1,7 @@ +define("ace/snippets/glsl",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "glsl"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/golang.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/golang.js new file mode 100644 index 00000000..81d2ab9f --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/golang.js @@ -0,0 +1,7 @@ +define("ace/snippets/golang",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "golang"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/groovy.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/groovy.js new file mode 100644 index 00000000..f5a16581 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/groovy.js @@ -0,0 +1,7 @@ +define("ace/snippets/groovy",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "groovy"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/haml.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/haml.js new file mode 100644 index 00000000..cfb95477 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/haml.js @@ -0,0 +1,27 @@ +define("ace/snippets/haml",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet t\n\ + %table\n\ + %tr\n\ + %th\n\ + ${1:headers}\n\ + %tr\n\ + %td\n\ + ${2:headers}\n\ +snippet ul\n\ + %ul\n\ + %li\n\ + ${1:item}\n\ + %li\n\ +snippet =rp\n\ + = render :partial => '${1:partial}'\n\ +snippet =rpl\n\ + = render :partial => '${1:partial}', :locals => {}\n\ +snippet =rpc\n\ + = render :partial => '${1:partial}', :collection => @$1\n\ +\n\ +"; +exports.scope = "haml"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/handlebars.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/handlebars.js new file mode 100644 index 00000000..85eacaa5 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/handlebars.js @@ -0,0 +1,7 @@ +define("ace/snippets/handlebars",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "handlebars"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/haskell.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/haskell.js new file mode 100644 index 00000000..b4f504a6 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/haskell.js @@ -0,0 +1,89 @@ +define("ace/snippets/haskell",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet lang\n\ + {-# LANGUAGE ${1:OverloadedStrings} #-}\n\ +snippet info\n\ + -- |\n\ + -- Module : ${1:Module.Namespace}\n\ + -- Copyright : ${2:Author} ${3:2011-2012}\n\ + -- License : ${4:BSD3}\n\ + --\n\ + -- Maintainer : ${5:email@something.com}\n\ + -- Stability : ${6:experimental}\n\ + -- Portability : ${7:unknown}\n\ + --\n\ + -- ${8:Description}\n\ + --\n\ +snippet import\n\ + import ${1:Data.Text}\n\ +snippet import2\n\ + import ${1:Data.Text} (${2:head})\n\ +snippet importq\n\ + import qualified ${1:Data.Text} as ${2:T}\n\ +snippet inst\n\ + instance ${1:Monoid} ${2:Type} where\n\ + ${3}\n\ +snippet type\n\ + type ${1:Type} = ${2:Type}\n\ +snippet data\n\ + data ${1:Type} = ${2:$1} ${3:Int}\n\ +snippet newtype\n\ + newtype ${1:Type} = ${2:$1} ${3:Int}\n\ +snippet class\n\ + class ${1:Class} a where\n\ + ${2}\n\ +snippet module\n\ + module `substitute(substitute(expand('%:r'), '[/\\\\]','.','g'),'^\\%(\\l*\\.\\)\\?','','')` (\n\ + ) where\n\ + `expand('%') =~ 'Main' ? \"\\n\\nmain = do\\n print \\\"hello world\\\"\" : \"\"`\n\ +\n\ +snippet const\n\ + ${1:name} :: ${2:a}\n\ + $1 = ${3:undefined}\n\ +snippet fn\n\ + ${1:fn} :: ${2:a} -> ${3:a}\n\ + $1 ${4} = ${5:undefined}\n\ +snippet fn2\n\ + ${1:fn} :: ${2:a} -> ${3:a} -> ${4:a}\n\ + $1 ${5} = ${6:undefined}\n\ +snippet ap\n\ + ${1:map} ${2:fn} ${3:list}\n\ +snippet do\n\ + do\n\ + \n\ +snippet λ\n\ + \\${1:x} -> ${2}\n\ +snippet \\\n\ + \\${1:x} -> ${2}\n\ +snippet <-\n\ + ${1:a} <- ${2:m a}\n\ +snippet ←\n\ + ${1:a} <- ${2:m a}\n\ +snippet ->\n\ + ${1:m a} -> ${2:a}\n\ +snippet →\n\ + ${1:m a} -> ${2:a}\n\ +snippet tup\n\ + (${1:a}, ${2:b})\n\ +snippet tup2\n\ + (${1:a}, ${2:b}, ${3:c})\n\ +snippet tup3\n\ + (${1:a}, ${2:b}, ${3:c}, ${4:d})\n\ +snippet rec\n\ + ${1:Record} { ${2:recFieldA} = ${3:undefined}\n\ + , ${4:recFieldB} = ${5:undefined}\n\ + }\n\ +snippet case\n\ + case ${1:something} of\n\ + ${2} -> ${3}\n\ +snippet let\n\ + let ${1} = ${2}\n\ + in ${3}\n\ +snippet where\n\ + where\n\ + ${1:fn} = ${2:undefined}\n\ +"; +exports.scope = "haskell"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/haxe.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/haxe.js new file mode 100644 index 00000000..6a42a507 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/haxe.js @@ -0,0 +1,7 @@ +define("ace/snippets/haxe",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "haxe"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/html.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/html.js new file mode 100644 index 00000000..3466ecb7 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/html.js @@ -0,0 +1,835 @@ +define("ace/snippets/html",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# Some useful Unicode entities\n\ +# Non-Breaking Space\n\ +snippet nbs\n\ +  \n\ +# ←\n\ +snippet left\n\ + ←\n\ +# →\n\ +snippet right\n\ + →\n\ +# ↑\n\ +snippet up\n\ + ↑\n\ +# ↓\n\ +snippet down\n\ + ↓\n\ +# ↩\n\ +snippet return\n\ + ↩\n\ +# ⇤\n\ +snippet backtab\n\ + ⇤\n\ +# ⇥\n\ +snippet tab\n\ + ⇥\n\ +# ⇧\n\ +snippet shift\n\ + ⇧\n\ +# ⌃\n\ +snippet ctrl\n\ + ⌃\n\ +# ⌅\n\ +snippet enter\n\ + ⌅\n\ +# ⌘\n\ +snippet cmd\n\ + ⌘\n\ +# ⌥\n\ +snippet option\n\ + ⌥\n\ +# ⌦\n\ +snippet delete\n\ + ⌦\n\ +# ⌫\n\ +snippet backspace\n\ + ⌫\n\ +# ⎋\n\ +snippet esc\n\ + ⎋\n\ +# Generic Doctype\n\ +snippet doctype HTML 4.01 Strict\n\ + \n\ +snippet doctype HTML 4.01 Transitional\n\ + \n\ +snippet doctype HTML 5\n\ + \n\ +snippet doctype XHTML 1.0 Frameset\n\ + \n\ +snippet doctype XHTML 1.0 Strict\n\ + \n\ +snippet doctype XHTML 1.0 Transitional\n\ + \n\ +snippet doctype XHTML 1.1\n\ + \n\ +# HTML Doctype 4.01 Strict\n\ +snippet docts\n\ + \n\ +# HTML Doctype 4.01 Transitional\n\ +snippet doct\n\ + \n\ +# HTML Doctype 5\n\ +snippet doct5\n\ + \n\ +# XHTML Doctype 1.0 Frameset\n\ +snippet docxf\n\ + \n\ +# XHTML Doctype 1.0 Strict\n\ +snippet docxs\n\ + \n\ +# XHTML Doctype 1.0 Transitional\n\ +snippet docxt\n\ + \n\ +# XHTML Doctype 1.1\n\ +snippet docx\n\ + \n\ +# Attributes\n\ +snippet attr\n\ + ${1:attribute}=\"${2:property}\"\n\ +snippet attr+\n\ + ${1:attribute}=\"${2:property}\" attr+${3}\n\ +snippet .\n\ + class=\"${1}\"${2}\n\ +snippet #\n\ + id=\"${1}\"${2}\n\ +snippet alt\n\ + alt=\"${1}\"${2}\n\ +snippet charset\n\ + charset=\"${1:utf-8}\"${2}\n\ +snippet data\n\ + data-${1}=\"${2:$1}\"${3}\n\ +snippet for\n\ + for=\"${1}\"${2}\n\ +snippet height\n\ + height=\"${1}\"${2}\n\ +snippet href\n\ + href=\"${1:#}\"${2}\n\ +snippet lang\n\ + lang=\"${1:en}\"${2}\n\ +snippet media\n\ + media=\"${1}\"${2}\n\ +snippet name\n\ + name=\"${1}\"${2}\n\ +snippet rel\n\ + rel=\"${1}\"${2}\n\ +snippet scope\n\ + scope=\"${1:row}\"${2}\n\ +snippet src\n\ + src=\"${1}\"${2}\n\ +snippet title=\n\ + title=\"${1}\"${2}\n\ +snippet type\n\ + type=\"${1}\"${2}\n\ +snippet value\n\ + value=\"${1}\"${2}\n\ +snippet width\n\ + width=\"${1}\"${2}\n\ +# Elements\n\ +snippet a\n\ + ${2:$1}\n\ +snippet a.\n\ + ${3:$1}\n\ +snippet a#\n\ + ${3:$1}\n\ +snippet a:ext\n\ + ${2:$1}\n\ +snippet a:mail\n\ + ${3:email me}\n\ +snippet abbr\n\ + ${2}\n\ +snippet address\n\ +
\n\ + ${1}\n\ +
\n\ +snippet area\n\ + \"${4}\"\n\ +snippet area+\n\ + \"${4}\"\n\ + area+${5}\n\ +snippet area:c\n\ + \"${3}\"\n\ +snippet area:d\n\ + \"${3}\"\n\ +snippet area:p\n\ + \"${3}\"\n\ +snippet area:r\n\ + \"${3}\"\n\ +snippet article\n\ +
\n\ + ${1}\n\ +
\n\ +snippet article.\n\ +
\n\ + ${2}\n\ +
\n\ +snippet article#\n\ +
\n\ + ${2}\n\ +
\n\ +snippet aside\n\ + \n\ +snippet aside.\n\ + \n\ +snippet aside#\n\ + \n\ +snippet audio\n\ + \n\ +snippet b\n\ + ${1}\n\ +snippet base\n\ + \n\ +snippet bdi\n\ + ${1}\n\ +snippet bdo\n\ + ${2}\n\ +snippet bdo:l\n\ + ${1}\n\ +snippet bdo:r\n\ + ${1}\n\ +snippet blockquote\n\ +
\n\ + ${1}\n\ +
\n\ +snippet body\n\ + \n\ + ${1}\n\ + \n\ +snippet br\n\ +
${1}\n\ +snippet button\n\ + \n\ +snippet button.\n\ + \n\ +snippet button#\n\ + \n\ +snippet button:s\n\ + \n\ +snippet button:r\n\ + \n\ +snippet canvas\n\ + \n\ + ${1}\n\ + \n\ +snippet caption\n\ + ${1}\n\ +snippet cite\n\ + ${1}\n\ +snippet code\n\ + ${1}\n\ +snippet col\n\ + ${1}\n\ +snippet col+\n\ + \n\ + col+${1}\n\ +snippet colgroup\n\ + \n\ + ${1}\n\ + \n\ +snippet colgroup+\n\ + \n\ + \n\ + col+${1}\n\ + \n\ +snippet command\n\ + \n\ +snippet command:c\n\ + \n\ +snippet command:r\n\ + \n\ +snippet datagrid\n\ + \n\ + ${1}\n\ + \n\ +snippet datalist\n\ + \n\ + ${1}\n\ + \n\ +snippet datatemplate\n\ + \n\ + ${1}\n\ + \n\ +snippet dd\n\ +
${1}
\n\ +snippet dd.\n\ +
${2}
\n\ +snippet dd#\n\ +
${2}
\n\ +snippet del\n\ + ${1}\n\ +snippet details\n\ +
${1}
\n\ +snippet dfn\n\ + ${1}\n\ +snippet dialog\n\ + \n\ + ${1}\n\ + \n\ +snippet div\n\ +
\n\ + ${1}\n\ +
\n\ +snippet div.\n\ +
\n\ + ${2}\n\ +
\n\ +snippet div#\n\ +
\n\ + ${2}\n\ +
\n\ +snippet dl\n\ +
\n\ + ${1}\n\ +
\n\ +snippet dl.\n\ +
\n\ + ${2}\n\ +
\n\ +snippet dl#\n\ +
\n\ + ${2}\n\ +
\n\ +snippet dl+\n\ +
\n\ +
${1}
\n\ +
${2}
\n\ + dt+${3}\n\ +
\n\ +snippet dt\n\ +
${1}
\n\ +snippet dt.\n\ +
${2}
\n\ +snippet dt#\n\ +
${2}
\n\ +snippet dt+\n\ +
${1}
\n\ +
${2}
\n\ + dt+${3}\n\ +snippet em\n\ + ${1}\n\ +snippet embed\n\ + \n\ +snippet fieldset\n\ +
\n\ + ${1}\n\ +
\n\ +snippet fieldset.\n\ +
\n\ + ${2}\n\ +
\n\ +snippet fieldset#\n\ +
\n\ + ${2}\n\ +
\n\ +snippet fieldset+\n\ +
\n\ + ${1}\n\ + ${2}\n\ +
\n\ + fieldset+${3}\n\ +snippet figcaption\n\ +
${1}
\n\ +snippet figure\n\ +
${1}
\n\ +snippet footer\n\ +
\n\ + ${1}\n\ +
\n\ +snippet footer.\n\ +
\n\ + ${2}\n\ +
\n\ +snippet footer#\n\ +
\n\ + ${2}\n\ +
\n\ +snippet form\n\ +
\n\ + ${3}\n\ +
\n\ +snippet form.\n\ +
\n\ + ${4}\n\ +
\n\ +snippet form#\n\ +
\n\ + ${4}\n\ +
\n\ +snippet h1\n\ +

${1}

\n\ +snippet h1.\n\ +

${2}

\n\ +snippet h1#\n\ +

${2}

\n\ +snippet h2\n\ +

${1}

\n\ +snippet h2.\n\ +

${2}

\n\ +snippet h2#\n\ +

${2}

\n\ +snippet h3\n\ +

${1}

\n\ +snippet h3.\n\ +

${2}

\n\ +snippet h3#\n\ +

${2}

\n\ +snippet h4\n\ +

${1}

\n\ +snippet h4.\n\ +

${2}

\n\ +snippet h4#\n\ +

${2}

\n\ +snippet h5\n\ +
${1}
\n\ +snippet h5.\n\ +
${2}
\n\ +snippet h5#\n\ +
${2}
\n\ +snippet h6\n\ +
${1}
\n\ +snippet h6.\n\ +
${2}
\n\ +snippet h6#\n\ +
${2}
\n\ +snippet head\n\ + \n\ + \n\ +\n\ + ${1:`substitute(Filename('', 'Page Title'), '^.', '\\u&', '')`}\n\ + ${2}\n\ + \n\ +snippet header\n\ +
\n\ + ${1}\n\ +
\n\ +snippet header.\n\ +
\n\ + ${2}\n\ +
\n\ +snippet header#\n\ +
\n\ + ${2}\n\ +
\n\ +snippet hgroup\n\ +
\n\ + ${1}\n\ +
\n\ +snippet hgroup.\n\ +
\n\ + ${2}\n\ +
\n\ +snippet hr\n\ +
${1}\n\ +snippet html\n\ + \n\ + ${1}\n\ + \n\ +snippet xhtml\n\ + \n\ + ${1}\n\ + \n\ +snippet html5\n\ + \n\ + \n\ + \n\ + \n\ + ${1:`substitute(Filename('', 'Page Title'), '^.', '\\u&', '')`}\n\ + ${2:meta}\n\ + \n\ + \n\ + ${3:body}\n\ + \n\ + \n\ +snippet i\n\ + ${1}\n\ +snippet iframe\n\ + ${2}\n\ +snippet iframe.\n\ + ${3}\n\ +snippet iframe#\n\ + ${3}\n\ +snippet img\n\ + \"${2}\"${3}\n\ +snippet img.\n\ + \"${3}\"${4}\n\ +snippet img#\n\ + \"${3}\"${4}\n\ +snippet input\n\ + ${5}\n\ +snippet input.\n\ + ${6}\n\ +snippet input:text\n\ + ${4}\n\ +snippet input:submit\n\ + ${4}\n\ +snippet input:hidden\n\ + ${4}\n\ +snippet input:button\n\ + ${4}\n\ +snippet input:image\n\ + ${5}\n\ +snippet input:checkbox\n\ + ${3}\n\ +snippet input:radio\n\ + ${3}\n\ +snippet input:color\n\ + ${4}\n\ +snippet input:date\n\ + ${4}\n\ +snippet input:datetime\n\ + ${4}\n\ +snippet input:datetime-local\n\ + ${4}\n\ +snippet input:email\n\ + ${4}\n\ +snippet input:file\n\ + ${4}\n\ +snippet input:month\n\ + ${4}\n\ +snippet input:number\n\ + ${4}\n\ +snippet input:password\n\ + ${4}\n\ +snippet input:range\n\ + ${4}\n\ +snippet input:reset\n\ + ${4}\n\ +snippet input:search\n\ + ${4}\n\ +snippet input:time\n\ + ${4}\n\ +snippet input:url\n\ + ${4}\n\ +snippet input:week\n\ + ${4}\n\ +snippet ins\n\ + ${1}\n\ +snippet kbd\n\ + ${1}\n\ +snippet keygen\n\ + ${1}\n\ +snippet label\n\ + \n\ +snippet label:i\n\ + \n\ + ${7}\n\ +snippet label:s\n\ + \n\ + \n\ +snippet legend\n\ + ${1}\n\ +snippet legend+\n\ + ${1}\n\ +snippet li\n\ +
  • ${1}
  • \n\ +snippet li.\n\ +
  • ${2}
  • \n\ +snippet li+\n\ +
  • ${1}
  • \n\ + li+${2}\n\ +snippet lia\n\ +
  • ${1}
  • \n\ +snippet lia+\n\ +
  • ${1}
  • \n\ + lia+${3}\n\ +snippet link\n\ + ${5}\n\ +snippet link:atom\n\ + ${2}\n\ +snippet link:css\n\ + ${4}\n\ +snippet link:favicon\n\ + ${2}\n\ +snippet link:rss\n\ + ${2}\n\ +snippet link:touch\n\ + ${2}\n\ +snippet map\n\ + \n\ + ${2}\n\ + \n\ +snippet map.\n\ + \n\ + ${3}\n\ + \n\ +snippet map#\n\ + \n\ + ${3}\n\ + \n\ +snippet map+\n\ + \n\ + \"${5}\"${6}\n\ + ${7}\n\ +snippet mark\n\ + ${1}\n\ +snippet menu\n\ + \n\ + ${1}\n\ + \n\ +snippet menu:c\n\ + \n\ + ${1}\n\ + \n\ +snippet menu:t\n\ + \n\ + ${1}\n\ + \n\ +snippet meta\n\ + ${3}\n\ +snippet meta:compat\n\ + ${3}\n\ +snippet meta:refresh\n\ + ${3}\n\ +snippet meta:utf\n\ + ${3}\n\ +snippet meter\n\ + ${1}\n\ +snippet nav\n\ + \n\ +snippet nav.\n\ + \n\ +snippet nav#\n\ + \n\ +snippet noscript\n\ + \n\ +snippet object\n\ + \n\ + ${3}\n\ + ${4}\n\ +# Embed QT Movie\n\ +snippet movie\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + ${6}\n\ +snippet ol\n\ +
      \n\ + ${1}\n\ +
    \n\ +snippet ol.\n\ +
      \n\ + ${2}\n\ +
    \n\ +snippet ol#\n\ +
      \n\ + ${2}\n\ +
    \n\ +snippet ol+\n\ +
      \n\ +
    1. ${1}
    2. \n\ + li+${2}\n\ +
    \n\ +snippet opt\n\ + \n\ +snippet opt+\n\ + \n\ + opt+${3}\n\ +snippet optt\n\ + \n\ +snippet optgroup\n\ + \n\ + \n\ + opt+${3}\n\ + \n\ +snippet output\n\ + ${1}\n\ +snippet p\n\ +

    ${1}

    \n\ +snippet param\n\ + ${3}\n\ +snippet pre\n\ +
    \n\
    +		${1}\n\
    +	
    \n\ +snippet progress\n\ + ${1}\n\ +snippet q\n\ + ${1}\n\ +snippet rp\n\ + ${1}\n\ +snippet rt\n\ + ${1}\n\ +snippet ruby\n\ + \n\ + ${1}\n\ + \n\ +snippet s\n\ + ${1}\n\ +snippet samp\n\ + \n\ + ${1}\n\ + \n\ +snippet script\n\ + \n\ +snippet scriptsrc\n\ + \n\ +snippet section\n\ +
    \n\ + ${1}\n\ +
    \n\ +snippet section.\n\ +
    \n\ + ${2}\n\ +
    \n\ +snippet section#\n\ +
    \n\ + ${2}\n\ +
    \n\ +snippet select\n\ + \n\ +snippet select.\n\ + \n\ +snippet select+\n\ + \n\ +snippet small\n\ + ${1}\n\ +snippet source\n\ + \n\ +snippet span\n\ + ${1}\n\ +snippet strong\n\ + ${1}\n\ +snippet style\n\ + \n\ +snippet sub\n\ + ${1}\n\ +snippet summary\n\ + \n\ + ${1}\n\ + \n\ +snippet sup\n\ + ${1}\n\ +snippet table\n\ + \n\ + ${2}\n\ +
    \n\ +snippet table.\n\ + \n\ + ${3}\n\ +
    \n\ +snippet table#\n\ + \n\ + ${3}\n\ +
    \n\ +snippet tbody\n\ + \n\ + ${1}\n\ + \n\ +snippet td\n\ + ${1}\n\ +snippet td.\n\ + ${2}\n\ +snippet td#\n\ + ${2}\n\ +snippet td+\n\ + ${1}\n\ + td+${2}\n\ +snippet textarea\n\ + ${6}\n\ +snippet tfoot\n\ + \n\ + ${1}\n\ + \n\ +snippet th\n\ + ${1}\n\ +snippet th.\n\ + ${2}\n\ +snippet th#\n\ + ${2}\n\ +snippet th+\n\ + ${1}\n\ + th+${2}\n\ +snippet thead\n\ + \n\ + ${1}\n\ + \n\ +snippet time\n\ + \n\ +snippet title\n\ + ${1:`substitute(Filename('', 'Page Title'), '^.', '\\u&', '')`}\n\ +snippet tr\n\ + \n\ + ${1}\n\ + \n\ +snippet tr+\n\ + \n\ + ${1}\n\ + td+${2}\n\ + \n\ +snippet track\n\ + ${5}${6}\n\ +snippet ul\n\ +
      \n\ + ${1}\n\ +
    \n\ +snippet ul.\n\ +
      \n\ + ${2}\n\ +
    \n\ +snippet ul#\n\ +
      \n\ + ${2}\n\ +
    \n\ +snippet ul+\n\ +
      \n\ +
    • ${1}
    • \n\ + li+${2}\n\ +
    \n\ +snippet var\n\ + ${1}\n\ +snippet video\n\ + ${8}\n\ +snippet wbr\n\ + ${1}\n\ +"; +exports.scope = "html"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/html_ruby.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/html_ruby.js new file mode 100644 index 00000000..7a781d81 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/html_ruby.js @@ -0,0 +1,7 @@ +define("ace/snippets/html_ruby",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "html_ruby"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ini.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ini.js new file mode 100644 index 00000000..bc5bc939 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ini.js @@ -0,0 +1,7 @@ +define("ace/snippets/ini",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "ini"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/io.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/io.js new file mode 100644 index 00000000..743b5d2a --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/io.js @@ -0,0 +1,69 @@ +define("ace/snippets/io",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippets = [ + { + "content": "assertEquals(${1:expected}, ${2:expr})", + "name": "assertEquals", + "scope": "io", + "tabTrigger": "ae" + }, + { + "content": "${1:${2:newValue} := ${3:Object} }clone do(\n\t$0\n)", + "name": "clone do", + "scope": "io", + "tabTrigger": "cdo" + }, + { + "content": "docSlot(\"${1:slotName}\", \"${2:documentation}\")", + "name": "docSlot", + "scope": "io", + "tabTrigger": "ds" + }, + { + "content": "(${1:header,}\n\t${2:body}\n)$0", + "keyEquivalent": "@(", + "name": "Indented Bracketed Line", + "scope": "io", + "tabTrigger": "(" + }, + { + "content": "\n\t$0\n", + "keyEquivalent": "\r", + "name": "Special: Return Inside Empty Parenthesis", + "scope": "io meta.empty-parenthesis.io, io meta.comma-parenthesis.io" + }, + { + "content": "${1:methodName} := method(${2:args,}\n\t$0\n)", + "name": "method", + "scope": "io", + "tabTrigger": "m" + }, + { + "content": "newSlot(\"${1:slotName}\", ${2:defaultValue}, \"${3:docString}\")$0", + "name": "newSlot", + "scope": "io", + "tabTrigger": "ns" + }, + { + "content": "${1:name} := Object clone do(\n\t$0\n)", + "name": "Object clone do", + "scope": "io", + "tabTrigger": "ocdo" + }, + { + "content": "test${1:SomeFeature} := method(\n\t$0\n)", + "name": "testMethod", + "scope": "io", + "tabTrigger": "ts" + }, + { + "content": "${1:Something}Test := ${2:UnitTest} clone do(\n\t$0\n)", + "name": "UnitTest", + "scope": "io", + "tabTrigger": "ut" + } +]; +exports.scope = "io"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jack.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jack.js new file mode 100644 index 00000000..154a0b06 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jack.js @@ -0,0 +1,7 @@ +define("ace/snippets/jack",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "jack"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jade.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jade.js new file mode 100644 index 00000000..f96faee4 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jade.js @@ -0,0 +1,7 @@ +define("ace/snippets/jade",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "jade"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/java.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/java.js new file mode 100644 index 00000000..a33c3878 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/java.js @@ -0,0 +1,241 @@ +define("ace/snippets/java",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "## Access Modifiers\n\ +snippet po\n\ + protected\n\ +snippet pu\n\ + public\n\ +snippet pr\n\ + private\n\ +##\n\ +## Annotations\n\ +snippet before\n\ + @Before\n\ + static void ${1:intercept}(${2:args}) { ${3} }\n\ +snippet mm\n\ + @ManyToMany\n\ + ${1}\n\ +snippet mo\n\ + @ManyToOne\n\ + ${1}\n\ +snippet om\n\ + @OneToMany${1:(cascade=CascadeType.ALL)}\n\ + ${2}\n\ +snippet oo\n\ + @OneToOne\n\ + ${1}\n\ +##\n\ +## Basic Java packages and import\n\ +snippet im\n\ + import\n\ +snippet j.b\n\ + java.beans.\n\ +snippet j.i\n\ + java.io.\n\ +snippet j.m\n\ + java.math.\n\ +snippet j.n\n\ + java.net.\n\ +snippet j.u\n\ + java.util.\n\ +##\n\ +## Class\n\ +snippet cl\n\ + class ${1:`Filename(\"\", \"untitled\")`} ${2}\n\ +snippet in\n\ + interface ${1:`Filename(\"\", \"untitled\")`} ${2:extends Parent}${3}\n\ +snippet tc\n\ + public class ${1:`Filename()`} extends ${2:TestCase}\n\ +##\n\ +## Class Enhancements\n\ +snippet ext\n\ + extends \n\ +snippet imp\n\ + implements\n\ +##\n\ +## Comments\n\ +snippet /*\n\ +##\n\ +## Constants\n\ +snippet co\n\ + static public final ${1:String} ${2:var} = ${3};${4}\n\ +snippet cos\n\ + static public final String ${1:var} = \"${2}\";${3}\n\ +##\n\ +## Control Statements\n\ +snippet case\n\ + case ${1}:\n\ + ${2}\n\ +snippet def\n\ + default:\n\ + ${2}\n\ +snippet el\n\ + else\n\ +snippet elif\n\ + else if (${1}) ${2}\n\ +snippet if\n\ + if (${1}) ${2}\n\ +snippet sw\n\ + switch (${1}) {\n\ + ${2}\n\ + }\n\ +##\n\ +## Create a Method\n\ +snippet m\n\ + ${1:void} ${2:method}(${3}) ${4:throws }${5}\n\ +##\n\ +## Create a Variable\n\ +snippet v\n\ + ${1:String} ${2:var}${3: = null}${4};${5}\n\ +##\n\ +## Enhancements to Methods, variables, classes, etc.\n\ +snippet ab\n\ + abstract\n\ +snippet fi\n\ + final\n\ +snippet st\n\ + static\n\ +snippet sy\n\ + synchronized\n\ +##\n\ +## Error Methods\n\ +snippet err\n\ + System.err.print(\"${1:Message}\");\n\ +snippet errf\n\ + System.err.printf(\"${1:Message}\", ${2:exception});\n\ +snippet errln\n\ + System.err.println(\"${1:Message}\");\n\ +##\n\ +## Exception Handling\n\ +snippet as\n\ + assert ${1:test} : \"${2:Failure message}\";${3}\n\ +snippet ca\n\ + catch(${1:Exception} ${2:e}) ${3}\n\ +snippet thr\n\ + throw\n\ +snippet ths\n\ + throws\n\ +snippet try\n\ + try {\n\ + ${3}\n\ + } catch(${1:Exception} ${2:e}) {\n\ + }\n\ +snippet tryf\n\ + try {\n\ + ${3}\n\ + } catch(${1:Exception} ${2:e}) {\n\ + } finally {\n\ + }\n\ +##\n\ +## Find Methods\n\ +snippet findall\n\ + List<${1:listName}> ${2:items} = ${1}.findAll();${3}\n\ +snippet findbyid\n\ + ${1:var} ${2:item} = ${1}.findById(${3});${4}\n\ +##\n\ +## Javadocs\n\ +snippet /**\n\ +snippet @au\n\ + @author `system(\"grep \\`id -un\\` /etc/passwd | cut -d \\\":\\\" -f5 | cut -d \\\",\\\" -f1\")`\n\ +snippet @br\n\ + @brief ${1:Description}\n\ +snippet @fi\n\ + @file ${1:`Filename()`}.java\n\ +snippet @pa\n\ + @param ${1:param}\n\ +snippet @re\n\ + @return ${1:param}\n\ +##\n\ +## Logger Methods\n\ +snippet debug\n\ + Logger.debug(${1:param});${2}\n\ +snippet error\n\ + Logger.error(${1:param});${2}\n\ +snippet info\n\ + Logger.info(${1:param});${2}\n\ +snippet warn\n\ + Logger.warn(${1:param});${2}\n\ +##\n\ +## Loops\n\ +snippet enfor\n\ + for (${1} : ${2}) ${3}\n\ +snippet for\n\ + for (${1}; ${2}; ${3}) ${4}\n\ +snippet wh\n\ + while (${1}) ${2}\n\ +##\n\ +## Main method\n\ +snippet main\n\ + public static void main (String[] args) {\n\ + ${1:/* code */}\n\ + }\n\ +##\n\ +## Print Methods\n\ +snippet print\n\ + System.out.print(\"${1:Message}\");\n\ +snippet printf\n\ + System.out.printf(\"${1:Message}\", ${2:args});\n\ +snippet println\n\ + System.out.println(${1});\n\ +##\n\ +## Render Methods\n\ +snippet ren\n\ + render(${1:param});${2}\n\ +snippet rena\n\ + renderArgs.put(\"${1}\", ${2});${3}\n\ +snippet renb\n\ + renderBinary(${1:param});${2}\n\ +snippet renj\n\ + renderJSON(${1:param});${2}\n\ +snippet renx\n\ + renderXml(${1:param});${2}\n\ +##\n\ +## Setter and Getter Methods\n\ +snippet set\n\ + ${1:public} void set${3:}(${2:String} ${4:}){\n\ + this.$4 = $4;\n\ + }\n\ +snippet get\n\ + ${1:public} ${2:String} get${3:}(){\n\ + return this.${4:};\n\ + }\n\ +##\n\ +## Terminate Methods or Loops\n\ +snippet re\n\ + return\n\ +snippet br\n\ + break;\n\ +##\n\ +## Test Methods\n\ +snippet t\n\ + public void test${1:Name}() throws Exception {\n\ + ${2}\n\ + }\n\ +snippet test\n\ + @Test\n\ + public void test${1:Name}() throws Exception {\n\ + ${2}\n\ + }\n\ +##\n\ +## Utils\n\ +snippet Sc\n\ + Scanner\n\ +##\n\ +## Miscellaneous\n\ +snippet action\n\ + public static void ${1:index}(${2:args}) { ${3} }\n\ +snippet rnf\n\ + notFound(${1:param});${2}\n\ +snippet rnfin\n\ + notFoundIfNull(${1:param});${2}\n\ +snippet rr\n\ + redirect(${1:param});${2}\n\ +snippet ru\n\ + unauthorized(${1:param});${2}\n\ +snippet unless\n\ + (unless=${1:param});${2}\n\ +"; +exports.scope = "java"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/javascript.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/javascript.js new file mode 100644 index 00000000..8f12aae5 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/javascript.js @@ -0,0 +1,189 @@ +define("ace/snippets/javascript",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# Prototype\n\ +snippet proto\n\ + ${1:class_name}.prototype.${2:method_name} = function(${3:first_argument}) {\n\ + ${4:// body...}\n\ + };\n\ +# Function\n\ +snippet fun\n\ + function ${1?:function_name}(${2:argument}) {\n\ + ${3:// body...}\n\ + }\n\ +# Anonymous Function\n\ +regex /((=)\\s*|(:)\\s*|(\\()|\\b)/f/(\\))?/\n\ +snippet f\n\ + function${M1?: ${1:functionName}}($2) {\n\ + ${0:$TM_SELECTED_TEXT}\n\ + }${M2?;}${M3?,}${M4?)}\n\ +# Immediate function\n\ +trigger \\(?f\\(\n\ +endTrigger \\)?\n\ +snippet f(\n\ + (function(${1}) {\n\ + ${0:${TM_SELECTED_TEXT:/* code */}}\n\ + }(${1}));\n\ +# if\n\ +snippet if\n\ + if (${1:true}) {\n\ + ${0}\n\ + }\n\ +# if ... else\n\ +snippet ife\n\ + if (${1:true}) {\n\ + ${2}\n\ + } else {\n\ + ${0}\n\ + }\n\ +# tertiary conditional\n\ +snippet ter\n\ + ${1:/* condition */} ? ${2:a} : ${3:b}\n\ +# switch\n\ +snippet switch\n\ + switch (${1:expression}) {\n\ + case '${3:case}':\n\ + ${4:// code}\n\ + break;\n\ + ${5}\n\ + default:\n\ + ${2:// code}\n\ + }\n\ +# case\n\ +snippet case\n\ + case '${1:case}':\n\ + ${2:// code}\n\ + break;\n\ + ${3}\n\ +\n\ +# while (...) {...}\n\ +snippet wh\n\ + while (${1:/* condition */}) {\n\ + ${0:/* code */}\n\ + }\n\ +# try\n\ +snippet try\n\ + try {\n\ + ${0:/* code */}\n\ + } catch (e) {}\n\ +# do...while\n\ +snippet do\n\ + do {\n\ + ${2:/* code */}\n\ + } while (${1:/* condition */});\n\ +# Object Method\n\ +snippet :f\n\ +regex /([,{[])|^\\s*/:f/\n\ + ${1:method_name}: function(${2:attribute}) {\n\ + ${0}\n\ + }${3:,}\n\ +# setTimeout function\n\ +snippet setTimeout\n\ +regex /\\b/st|timeout|setTimeo?u?t?/\n\ + setTimeout(function() {${3:$TM_SELECTED_TEXT}}, ${1:10});\n\ +# Get Elements\n\ +snippet gett\n\ + getElementsBy${1:TagName}('${2}')${3}\n\ +# Get Element\n\ +snippet get\n\ + getElementBy${1:Id}('${2}')${3}\n\ +# console.log (Firebug)\n\ +snippet cl\n\ + console.log(${1});\n\ +# return\n\ +snippet ret\n\ + return ${1:result}\n\ +# for (property in object ) { ... }\n\ +snippet fori\n\ + for (var ${1:prop} in ${2:Things}) {\n\ + ${0:$2[$1]}\n\ + }\n\ +# hasOwnProperty\n\ +snippet has\n\ + hasOwnProperty(${1})\n\ +# docstring\n\ +snippet /**\n\ +snippet @par\n\ +regex /^\\s*\\*\\s*/@(para?m?)?/\n\ + @param {${1:type}} ${2:name} ${3:description}\n\ +snippet @ret\n\ + @return {${1:type}} ${2:description}\n\ +# JSON.parse\n\ +snippet jsonp\n\ + JSON.parse(${1:jstr});\n\ +# JSON.stringify\n\ +snippet jsons\n\ + JSON.stringify(${1:object});\n\ +# self-defining function\n\ +snippet sdf\n\ + var ${1:function_name} = function(${2:argument}) {\n\ + ${3:// initial code ...}\n\ +\n\ + $1 = function($2) {\n\ + ${4:// main code}\n\ + };\n\ + }\n\ +# singleton\n\ +snippet sing\n\ + function ${1:Singleton} (${2:argument}) {\n\ + var instance;\n\ + $1 = function $1($2) {\n\ + return instance;\n\ + };\n\ + $1.prototype = this;\n\ + instance = new $1();\n\ + instance.constructor = $1;\n\ +\n\ + ${3:// code ...}\n\ +\n\ + return instance;\n\ + }\n\ +# class\n\ +snippet class\n\ +regex /^\\s*/clas{0,2}/\n\ + var ${1:class} = function(${20}) {\n\ + $40$0\n\ + };\n\ + \n\ + (function() {\n\ + ${60:this.prop = \"\"}\n\ + }).call(${1:class}.prototype);\n\ + \n\ + exports.${1:class} = ${1:class};\n\ +# \n\ +snippet for-\n\ + for (var ${1:i} = ${2:Things}.length; ${1:i}--; ) {\n\ + ${0:${2:Things}[${1:i}];}\n\ + }\n\ +# for (...) {...}\n\ +snippet for\n\ + for (var ${1:i} = 0; $1 < ${2:Things}.length; $1++) {\n\ + ${3:$2[$1]}$0\n\ + }\n\ +# for (...) {...} (Improved Native For-Loop)\n\ +snippet forr\n\ + for (var ${1:i} = ${2:Things}.length - 1; $1 >= 0; $1--) {\n\ + ${3:$2[$1]}$0\n\ + }\n\ +\n\ +\n\ +#modules\n\ +snippet def\n\ + define(function(require, exports, module) {\n\ + \"use strict\";\n\ + var ${1/.*\\///} = require(\"${1}\");\n\ + \n\ + $TM_SELECTED_TEXT\n\ + });\n\ +snippet req\n\ +guard ^\\s*\n\ + var ${1/.*\\///} = require(\"${1}\");\n\ + $0\n\ +snippet requ\n\ +guard ^\\s*\n\ + var ${1/.*\\/(.)/\\u$1/} = require(\"${1}\").${1/.*\\/(.)/\\u$1/};\n\ + $0\n\ +"; +exports.scope = "javascript"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/json.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/json.js new file mode 100644 index 00000000..88a63c16 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/json.js @@ -0,0 +1,7 @@ +define("ace/snippets/json",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "json"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsoniq.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsoniq.js new file mode 100644 index 00000000..7b036696 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsoniq.js @@ -0,0 +1,68 @@ +define("ace/snippets/jsoniq",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet for\n\ + for $${1:item} in ${2:expr}\n\ +snippet return\n\ + return ${1:expr}\n\ +snippet import\n\ + import module namespace ${1:ns} = \"${2:http://www.example.com/}\";\n\ +snippet some\n\ + some $${1:varname} in ${2:expr} satisfies ${3:expr}\n\ +snippet every\n\ + every $${1:varname} in ${2:expr} satisfies ${3:expr}\n\ +snippet if\n\ + if(${1:true}) then ${2:expr} else ${3:true}\n\ +snippet switch\n\ + switch(${1:\"foo\"})\n\ + case ${2:\"foo\"}\n\ + return ${3:true}\n\ + default return ${4:false}\n\ +snippet try\n\ + try { ${1:expr} } catch ${2:*} { ${3:expr} }\n\ +snippet tumbling\n\ + for tumbling window $${1:varname} in ${2:expr}\n\ + start at $${3:start} when ${4:expr}\n\ + end at $${5:end} when ${6:expr}\n\ + return ${7:expr}\n\ +snippet sliding\n\ + for sliding window $${1:varname} in ${2:expr}\n\ + start at $${3:start} when ${4:expr}\n\ + end at $${5:end} when ${6:expr}\n\ + return ${7:expr}\n\ +snippet let\n\ + let $${1:varname} := ${2:expr}\n\ +snippet group\n\ + group by $${1:varname} := ${2:expr}\n\ +snippet order\n\ + order by ${1:expr} ${2:descending}\n\ +snippet stable\n\ + stable order by ${1:expr}\n\ +snippet count\n\ + count $${1:varname}\n\ +snippet ordered\n\ + ordered { ${1:expr} }\n\ +snippet unordered\n\ + unordered { ${1:expr} }\n\ +snippet treat \n\ + treat as ${1:expr}\n\ +snippet castable\n\ + castable as ${1:atomicType}\n\ +snippet cast\n\ + cast as ${1:atomicType}\n\ +snippet typeswitch\n\ + typeswitch(${1:expr})\n\ + case ${2:type} return ${3:expr}\n\ + default return ${4:expr}\n\ +snippet var\n\ + declare variable $${1:varname} := ${2:expr};\n\ +snippet fn\n\ + declare function ${1:ns}:${2:name}(){\n\ + ${3:expr}\n\ + };\n\ +snippet module\n\ + module namespace ${1:ns} = \"${2:http://www.example.com}\";\n\ +"; +exports.scope = "jsoniq"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsp.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsp.js new file mode 100644 index 00000000..2aff1564 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsp.js @@ -0,0 +1,106 @@ +define("ace/snippets/jsp",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet @page\n\ + <%@page contentType=\"text/html\" pageEncoding=\"UTF-8\"%>\n\ +snippet jstl\n\ + <%@ taglib uri=\"http://java.sun.com/jsp/jstl/core\" prefix=\"c\" %>\n\ + <%@ taglib uri=\"http://java.sun.com/jsp/jstl/functions\" prefix=\"fn\" %>\n\ +snippet jstl:c\n\ + <%@ taglib uri=\"http://java.sun.com/jsp/jstl/core\" prefix=\"c\" %>\n\ +snippet jstl:fn\n\ + <%@ taglib uri=\"http://java.sun.com/jsp/jstl/functions\" prefix=\"fn\" %>\n\ +snippet cpath\n\ + ${pageContext.request.contextPath}\n\ +snippet cout\n\ + \n\ +snippet cset\n\ + \n\ +snippet cremove\n\ + \n\ +snippet ccatch\n\ + \n\ +snippet cif\n\ + \n\ + ${2}\n\ + \n\ +snippet cchoose\n\ + \n\ + ${1}\n\ + \n\ +snippet cwhen\n\ + \n\ + ${2}\n\ + \n\ +snippet cother\n\ + \n\ + ${1}\n\ + \n\ +snippet cfore\n\ + \n\ + ${4:}\n\ + \n\ +snippet cfort\n\ + ${2:item1,item2,item3}\n\ + \n\ + ${5:}\n\ + \n\ +snippet cparam\n\ + \n\ +snippet cparam+\n\ + \n\ + cparam+${3}\n\ +snippet cimport\n\ + \n\ +snippet cimport+\n\ + \n\ + \n\ + cparam+${4}\n\ + \n\ +snippet curl\n\ + \n\ + ${3}\n\ +snippet curl+\n\ + \n\ + \n\ + cparam+${6}\n\ + \n\ + ${3}\n\ +snippet credirect\n\ + \n\ +snippet contains\n\ + ${fn:contains(${1:string}, ${2:substr})}\n\ +snippet contains:i\n\ + ${fn:containsIgnoreCase(${1:string}, ${2:substr})}\n\ +snippet endswith\n\ + ${fn:endsWith(${1:string}, ${2:suffix})}\n\ +snippet escape\n\ + ${fn:escapeXml(${1:string})}\n\ +snippet indexof\n\ + ${fn:indexOf(${1:string}, ${2:substr})}\n\ +snippet join\n\ + ${fn:join(${1:collection}, ${2:delims})}\n\ +snippet length\n\ + ${fn:length(${1:collection_or_string})}\n\ +snippet replace\n\ + ${fn:replace(${1:string}, ${2:substr}, ${3:replace})}\n\ +snippet split\n\ + ${fn:split(${1:string}, ${2:delims})}\n\ +snippet startswith\n\ + ${fn:startsWith(${1:string}, ${2:prefix})}\n\ +snippet substr\n\ + ${fn:substring(${1:string}, ${2:begin}, ${3:end})}\n\ +snippet substr:a\n\ + ${fn:substringAfter(${1:string}, ${2:substr})}\n\ +snippet substr:b\n\ + ${fn:substringBefore(${1:string}, ${2:substr})}\n\ +snippet lc\n\ + ${fn:toLowerCase(${1:string})}\n\ +snippet uc\n\ + ${fn:toUpperCase(${1:string})}\n\ +snippet trim\n\ + ${fn:trim(${1:string})}\n\ +"; +exports.scope = "jsp"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsx.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsx.js new file mode 100644 index 00000000..5e9957da --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/jsx.js @@ -0,0 +1,7 @@ +define("ace/snippets/jsx",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "jsx"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/julia.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/julia.js new file mode 100644 index 00000000..17a6554e --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/julia.js @@ -0,0 +1,7 @@ +define("ace/snippets/julia",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "julia"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/latex.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/latex.js new file mode 100644 index 00000000..5e152b31 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/latex.js @@ -0,0 +1,7 @@ +define("ace/snippets/latex",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "latex"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lean.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lean.js new file mode 100644 index 00000000..21eec75f --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lean.js @@ -0,0 +1,7 @@ +define("ace/snippets/lean",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "lean"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/less.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/less.js new file mode 100644 index 00000000..af4ce7ca --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/less.js @@ -0,0 +1,7 @@ +define("ace/snippets/less",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "less"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/liquid.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/liquid.js new file mode 100644 index 00000000..a86117c2 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/liquid.js @@ -0,0 +1,7 @@ +define("ace/snippets/liquid",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "liquid"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lisp.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lisp.js new file mode 100644 index 00000000..c02fd8dc --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lisp.js @@ -0,0 +1,7 @@ +define("ace/snippets/lisp",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "lisp"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/live_script.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/live_script.js new file mode 100644 index 00000000..9ab33767 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/live_script.js @@ -0,0 +1,7 @@ +define("ace/snippets/live_script",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = ""; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/livescript.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/livescript.js new file mode 100644 index 00000000..4a254bd7 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/livescript.js @@ -0,0 +1,7 @@ +define("ace/snippets/livescript",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "livescript"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/logiql.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/logiql.js new file mode 100644 index 00000000..9a6b7923 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/logiql.js @@ -0,0 +1,7 @@ +define("ace/snippets/logiql",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "logiql"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lsl.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lsl.js new file mode 100644 index 00000000..8830c6c7 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lsl.js @@ -0,0 +1,1073 @@ +define("ace/snippets/lsl",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet @\n\ + @${1:label};\n\ +snippet CAMERA_ACTIVE\n\ + CAMERA_ACTIVE, ${1:integer isActive}, $0\n\ +snippet CAMERA_BEHINDNESS_ANGLE\n\ + CAMERA_BEHINDNESS_ANGLE, ${1:float degrees}, $0\n\ +snippet CAMERA_BEHINDNESS_LAG\n\ + CAMERA_BEHINDNESS_LAG, ${1:float seconds}, $0\n\ +snippet CAMERA_DISTANCE\n\ + CAMERA_DISTANCE, ${1:float meters}, $0\n\ +snippet CAMERA_FOCUS\n\ + CAMERA_FOCUS, ${1:vector position}, $0\n\ +snippet CAMERA_FOCUS_LAG\n\ + CAMERA_FOCUS_LAG, ${1:float seconds}, $0\n\ +snippet CAMERA_FOCUS_LOCKED\n\ + CAMERA_FOCUS_LOCKED, ${1:integer isLocked}, $0\n\ +snippet CAMERA_FOCUS_OFFSET\n\ + CAMERA_FOCUS_OFFSET, ${1:vector meters}, $0\n\ +snippet CAMERA_FOCUS_THRESHOLD\n\ + CAMERA_FOCUS_THRESHOLD, ${1:float meters}, $0\n\ +snippet CAMERA_PITCH\n\ + CAMERA_PITCH, ${1:float degrees}, $0\n\ +snippet CAMERA_POSITION\n\ + CAMERA_POSITION, ${1:vector position}, $0\n\ +snippet CAMERA_POSITION_LAG\n\ + CAMERA_POSITION_LAG, ${1:float seconds}, $0\n\ +snippet CAMERA_POSITION_LOCKED\n\ + CAMERA_POSITION_LOCKED, ${1:integer isLocked}, $0\n\ +snippet CAMERA_POSITION_THRESHOLD\n\ + CAMERA_POSITION_THRESHOLD, ${1:float meters}, $0\n\ +snippet CHARACTER_AVOIDANCE_MODE\n\ + CHARACTER_AVOIDANCE_MODE, ${1:integer flags}, $0\n\ +snippet CHARACTER_DESIRED_SPEED\n\ + CHARACTER_DESIRED_SPEED, ${1:float speed}, $0\n\ +snippet CHARACTER_DESIRED_TURN_SPEED\n\ + CHARACTER_DESIRED_TURN_SPEED, ${1:float speed}, $0\n\ +snippet CHARACTER_LENGTH\n\ + CHARACTER_LENGTH, ${1:float length}, $0\n\ +snippet CHARACTER_MAX_TURN_RADIUS\n\ + CHARACTER_MAX_TURN_RADIUS, ${1:float radius}, $0\n\ +snippet CHARACTER_ORIENTATION\n\ + CHARACTER_ORIENTATION, ${1:integer orientation}, $0\n\ +snippet CHARACTER_RADIUS\n\ + CHARACTER_RADIUS, ${1:float radius}, $0\n\ +snippet CHARACTER_STAY_WITHIN_PARCEL\n\ + CHARACTER_STAY_WITHIN_PARCEL, ${1:boolean stay}, $0\n\ +snippet CHARACTER_TYPE\n\ + CHARACTER_TYPE, ${1:integer type}, $0\n\ +snippet HTTP_BODY_MAXLENGTH\n\ + HTTP_BODY_MAXLENGTH, ${1:integer length}, $0\n\ +snippet HTTP_CUSTOM_HEADER\n\ + HTTP_CUSTOM_HEADER, ${1:string name}, ${2:string value}, $0\n\ +snippet HTTP_METHOD\n\ + HTTP_METHOD, ${1:string method}, $0\n\ +snippet HTTP_MIMETYPE\n\ + HTTP_MIMETYPE, ${1:string mimeType}, $0\n\ +snippet HTTP_PRAGMA_NO_CACHE\n\ + HTTP_PRAGMA_NO_CACHE, ${1:integer send_header}, $0\n\ +snippet HTTP_VERBOSE_THROTTLE\n\ + HTTP_VERBOSE_THROTTLE, ${1:integer noisy}, $0\n\ +snippet HTTP_VERIFY_CERT\n\ + HTTP_VERIFY_CERT, ${1:integer verify}, $0\n\ +snippet RC_DATA_FLAGS\n\ + RC_DATA_FLAGS, ${1:integer flags}, $0\n\ +snippet RC_DETECT_PHANTOM\n\ + RC_DETECT_PHANTOM, ${1:integer dectedPhantom}, $0\n\ +snippet RC_MAX_HITS\n\ + RC_MAX_HITS, ${1:integer maxHits}, $0\n\ +snippet RC_REJECT_TYPES\n\ + RC_REJECT_TYPES, ${1:integer filterMask}, $0\n\ +snippet at_rot_target\n\ + at_rot_target(${1:integer handle}, ${2:rotation targetrot}, ${3:rotation ourrot})\n\ + {\n\ + $0\n\ + }\n\ +snippet at_target\n\ + at_target(${1:integer tnum}, ${2:vector targetpos}, ${3:vector ourpos})\n\ + {\n\ + $0\n\ + }\n\ +snippet attach\n\ + attach(${1:key id})\n\ + {\n\ + $0\n\ + }\n\ +snippet changed\n\ + changed(${1:integer change})\n\ + {\n\ + $0\n\ + }\n\ +snippet collision\n\ + collision(${1:integer index})\n\ + {\n\ + $0\n\ + }\n\ +snippet collision_end\n\ + collision_end(${1:integer index})\n\ + {\n\ + $0\n\ + }\n\ +snippet collision_start\n\ + collision_start(${1:integer index})\n\ + {\n\ + $0\n\ + }\n\ +snippet control\n\ + control(${1:key id}, ${2:integer level}, ${3:integer edge})\n\ + {\n\ + $0\n\ + }\n\ +snippet dataserver\n\ + dataserver(${1:key query_id}, ${2:string data})\n\ + {\n\ + $0\n\ + }\n\ +snippet do\n\ + do\n\ + {\n\ + $0\n\ + }\n\ + while (${1:condition});\n\ +snippet else\n\ + else\n\ + {\n\ + $0\n\ + }\n\ +snippet email\n\ + email(${1:string time}, ${2:string address}, ${3:string subject}, ${4:string message}, ${5:integer num_left})\n\ + {\n\ + $0\n\ + }\n\ +snippet experience_permissions\n\ + experience_permissions(${1:key agent_id})\n\ + {\n\ + $0\n\ + }\n\ +snippet experience_permissions_denied\n\ + experience_permissions_denied(${1:key agent_id}, ${2:integer reason})\n\ + {\n\ + $0\n\ + }\n\ +snippet for\n\ + for (${1:start}; ${3:condition}; ${3:step})\n\ + {\n\ + $0\n\ + }\n\ +snippet http_request\n\ + http_request(${1:key request_id}, ${2:string method}, ${3:string body})\n\ + {\n\ + $0\n\ + }\n\ +snippet http_response\n\ + http_response(${1:key request_id}, ${2:integer status}, ${3:list metadata}, ${4:string body})\n\ + {\n\ + $0\n\ + }\n\ +snippet if\n\ + if (${1:condition})\n\ + {\n\ + $0\n\ + }\n\ +snippet jump\n\ + jump ${1:label};\n\ +snippet land_collision\n\ + land_collision(${1:vector pos})\n\ + {\n\ + $0\n\ + }\n\ +snippet land_collision_end\n\ + land_collision_end(${1:vector pos})\n\ + {\n\ + $0\n\ + }\n\ +snippet land_collision_start\n\ + land_collision_start(${1:vector pos})\n\ + {\n\ + $0\n\ + }\n\ +snippet link_message\n\ + link_message(${1:integer sender_num}, ${2:integer num}, ${3:string str}, ${4:key id})\n\ + {\n\ + $0\n\ + }\n\ +snippet listen\n\ + listen(${1:integer channel}, ${2:string name}, ${3:key id}, ${4:string message})\n\ + {\n\ + $0\n\ + }\n\ +snippet llAbs\n\ + llAbs(${1:integer val})\n\ +snippet llAcos\n\ + llAcos(${1:float val})\n\ +snippet llAddToLandBanList\n\ + llAddToLandBanList(${1:key agent}, ${2:float hours});\n\ +snippet llAddToLandPassList\n\ + llAddToLandPassList(${1:key agent}, ${2:float hours});\n\ +snippet llAdjustSoundVolume\n\ + llAdjustSoundVolume(${1:float volume});\n\ +snippet llAgentInExperience\n\ + llAgentInExperience(${1:key agent})\n\ +snippet llAllowInventoryDrop\n\ + llAllowInventoryDrop(${1:integer add});\n\ +snippet llAngleBetween\n\ + llAngleBetween(${1:rotation a}, ${2:rotation b})\n\ +snippet llApplyImpulse\n\ + llApplyImpulse(${1:vector force}, ${2:integer local});\n\ +snippet llApplyRotationalImpulse\n\ + llApplyRotationalImpulse(${1:vector force}, ${2:integer local});\n\ +snippet llAsin\n\ + llAsin(${1:float val})\n\ +snippet llAtan2\n\ + llAtan2(${1:float y}, ${2:float x})\n\ +snippet llAttachToAvatar\n\ + llAttachToAvatar(${1:integer attach_point});\n\ +snippet llAttachToAvatarTemp\n\ + llAttachToAvatarTemp(${1:integer attach_point});\n\ +snippet llAvatarOnLinkSitTarget\n\ + llAvatarOnLinkSitTarget(${1:integer link})\n\ +snippet llAvatarOnSitTarget\n\ + llAvatarOnSitTarget()\n\ +snippet llAxes2Rot\n\ + llAxes2Rot(${1:vector fwd}, ${2:vector left}, ${3:vector up})\n\ +snippet llAxisAngle2Rot\n\ + llAxisAngle2Rot(${1:vector axis}, ${2:float angle})\n\ +snippet llBase64ToInteger\n\ + llBase64ToInteger(${1:string str})\n\ +snippet llBase64ToString\n\ + llBase64ToString(${1:string str})\n\ +snippet llBreakAllLinks\n\ + llBreakAllLinks();\n\ +snippet llBreakLink\n\ + llBreakLink(${1:integer link});\n\ +snippet llCastRay\n\ + llCastRay(${1:vector start}, ${2:vector end}, ${3:list options});\n\ +snippet llCeil\n\ + llCeil(${1:float val})\n\ +snippet llClearCameraParams\n\ + llClearCameraParams();\n\ +snippet llClearLinkMedia\n\ + llClearLinkMedia(${1:integer link}, ${2:integer face});\n\ +snippet llClearPrimMedia\n\ + llClearPrimMedia(${1:integer face});\n\ +snippet llCloseRemoteDataChannel\n\ + llCloseRemoteDataChannel(${1:key channel});\n\ +snippet llCollisionFilter\n\ + llCollisionFilter(${1:string name}, ${2:key id}, ${3:integer accept});\n\ +snippet llCollisionSound\n\ + llCollisionSound(${1:string impact_sound}, ${2:float impact_volume});\n\ +snippet llCos\n\ + llCos(${1:float theta})\n\ +snippet llCreateCharacter\n\ + llCreateCharacter(${1:list options});\n\ +snippet llCreateKeyValue\n\ + llCreateKeyValue(${1:string k})\n\ +snippet llCreateLink\n\ + llCreateLink(${1:key target}, ${2:integer parent});\n\ +snippet llCSV2List\n\ + llCSV2List(${1:string src})\n\ +snippet llDataSizeKeyValue\n\ + llDataSizeKeyValue()\n\ +snippet llDeleteCharacter\n\ + llDeleteCharacter();\n\ +snippet llDeleteKeyValue\n\ + llDeleteKeyValue(${1:string k})\n\ +snippet llDeleteSubList\n\ + llDeleteSubList(${1:list src}, ${2:integer start}, ${3:integer end})\n\ +snippet llDeleteSubString\n\ + llDeleteSubString(${1:string src}, ${2:integer start}, ${3:integer end})\n\ +snippet llDetachFromAvatar\n\ + llDetachFromAvatar();\n\ +snippet llDetectedGrab\n\ + llDetectedGrab(${1:integer number})\n\ +snippet llDetectedGroup\n\ + llDetectedGroup(${1:integer number})\n\ +snippet llDetectedKey\n\ + llDetectedKey(${1:integer number})\n\ +snippet llDetectedLinkNumber\n\ + llDetectedLinkNumber(${1:integer number})\n\ +snippet llDetectedName\n\ + llDetectedName(${1:integer number})\n\ +snippet llDetectedOwner\n\ + llDetectedOwner(${1:integer number})\n\ +snippet llDetectedPos\n\ + llDetectedPosl(${1:integer number})\n\ +snippet llDetectedRot\n\ + llDetectedRot(${1:integer number})\n\ +snippet llDetectedTouchBinormal\n\ + llDetectedTouchBinormal(${1:integer number})\n\ +snippet llDetectedTouchFace\n\ + llDetectedTouchFace(${1:integer number})\n\ +snippet llDetectedTouchNormal\n\ + llDetectedTouchNormal(${1:integer number})\n\ +snippet llDetectedTouchPos\n\ + llDetectedTouchPos(${1:integer number})\n\ +snippet llDetectedTouchST\n\ + llDetectedTouchST(${1:integer number})\n\ +snippet llDetectedTouchUV\n\ + llDetectedTouchUV(${1:integer number})\n\ +snippet llDetectedType\n\ + llDetectedType(${1:integer number})\n\ +snippet llDetectedVel\n\ + llDetectedVel(${1:integer number})\n\ +snippet llDialog\n\ + llDialog(${1:key agent}, ${2:string message}, ${3:list buttons}, ${4:integer channel});\n\ +snippet llDie\n\ + llDie();\n\ +snippet llDumpList2String\n\ + llDumpList2String(${1:list src}, ${2:string separator})\n\ +snippet llEdgeOfWorld\n\ + llEdgeOfWorld(${1:vector pos}, ${2:vector dir})\n\ +snippet llEjectFromLand\n\ + llEjectFromLand(${1:key agent});\n\ +snippet llEmail\n\ + llEmail(${1:string address}, ${2:string subject}, ${3:string message});\n\ +snippet llEscapeURL\n\ + llEscapeURL(${1:string url})\n\ +snippet llEuler2Rot\n\ + llEuler2Rot(${1:vector v})\n\ +snippet llExecCharacterCmd\n\ + llExecCharacterCmd(${1:integer command}, ${2:list options});\n\ +snippet llEvade\n\ + llEvade(${1:key target}, ${2:list options});\n\ +snippet llFabs\n\ + llFabs(${1:float val})\n\ +snippet llFleeFrom\n\ + llFleeFrom(${1:vector position}, ${2:float distance}, ${3:list options});\n\ +snippet llFloor\n\ + llFloor(${1:float val})\n\ +snippet llForceMouselook\n\ + llForceMouselook(${1:integer mouselook});\n\ +snippet llFrand\n\ + llFrand(${1:float mag})\n\ +snippet llGenerateKey\n\ + llGenerateKey()\n\ +snippet llGetAccel\n\ + llGetAccel()\n\ +snippet llGetAgentInfo\n\ + llGetAgentInfo(${1:key id})\n\ +snippet llGetAgentLanguage\n\ + llGetAgentLanguage(${1:key agent})\n\ +snippet llGetAgentList\n\ + llGetAgentList(${1:integer scope}, ${2:list options})\n\ +snippet llGetAgentSize\n\ + llGetAgentSize(${1:key agent})\n\ +snippet llGetAlpha\n\ + llGetAlpha(${1:integer face})\n\ +snippet llGetAndResetTime\n\ + llGetAndResetTime()\n\ +snippet llGetAnimation\n\ + llGetAnimation(${1:key id})\n\ +snippet llGetAnimationList\n\ + llGetAnimationList(${1:key agent})\n\ +snippet llGetAnimationOverride\n\ + llGetAnimationOverride(${1:string anim_state})\n\ +snippet llGetAttached\n\ + llGetAttached()\n\ +snippet llGetBoundingBox\n\ + llGetBoundingBox(${1:key object})\n\ +snippet llGetCameraPos\n\ + llGetCameraPos()\n\ +snippet llGetCameraRot\n\ + llGetCameraRot()\n\ +snippet llGetCenterOfMass\n\ + llGetCenterOfMass()\n\ +snippet llGetClosestNavPoint\n\ + llGetClosestNavPoint(${1:vector point}, ${2:list options})\n\ +snippet llGetColor\n\ + llGetColor(${1:integer face})\n\ +snippet llGetCreator\n\ + llGetCreator()\n\ +snippet llGetDate\n\ + llGetDate()\n\ +snippet llGetDisplayName\n\ + llGetDisplayName(${1:key id})\n\ +snippet llGetEnergy\n\ + llGetEnergy()\n\ +snippet llGetEnv\n\ + llGetEnv(${1:string name})\n\ +snippet llGetExperienceDetails\n\ + llGetExperienceDetails(${1:key experience_id})\n\ +snippet llGetExperienceErrorMessage\n\ + llGetExperienceErrorMessage(${1:integer error})\n\ +snippet llGetForce\n\ + llGetForce()\n\ +snippet llGetFreeMemory\n\ + llGetFreeMemory()\n\ +snippet llGetFreeURLs\n\ + llGetFreeURLs()\n\ +snippet llGetGeometricCenter\n\ + llGetGeometricCenter()\n\ +snippet llGetGMTclock\n\ + llGetGMTclock()\n\ +snippet llGetHTTPHeader\n\ + llGetHTTPHeader(${1:key request_id}, ${2:string header})\n\ +snippet llGetInventoryCreator\n\ + llGetInventoryCreator(${1:string item})\n\ +snippet llGetInventoryKey\n\ + llGetInventoryKey(${1:string name})\n\ +snippet llGetInventoryName\n\ + llGetInventoryName(${1:integer type}, ${2:integer number})\n\ +snippet llGetInventoryNumber\n\ + llGetInventoryNumber(${1:integer type})\n\ +snippet llGetInventoryPermMask\n\ + llGetInventoryPermMask(${1:string item}, ${2:integer mask})\n\ +snippet llGetInventoryType\n\ + llGetInventoryType(${1:string name})\n\ +snippet llGetKey\n\ + llGetKey()\n\ +snippet llGetLandOwnerAt\n\ + llGetLandOwnerAt(${1:vector pos})\n\ +snippet llGetLinkKey\n\ + llGetLinkKey(${1:integer link})\n\ +snippet llGetLinkMedia\n\ + llGetLinkMedia(${1:integer link}, ${2:integer face}, ${3:list params})\n\ +snippet llGetLinkName\n\ + llGetLinkName(${1:integer link})\n\ +snippet llGetLinkNumber\n\ + llGetLinkNumber()\n\ +snippet llGetLinkNumberOfSides\n\ + llGetLinkNumberOfSides(${1:integer link})\n\ +snippet llGetLinkPrimitiveParams\n\ + llGetLinkPrimitiveParams(${1:integer link}, ${2:list params})\n\ +snippet llGetListEntryType\n\ + llGetListEntryType(${1:list src}, ${2:integer index})\n\ +snippet llGetListLength\n\ + llGetListLength(${1:list src})\n\ +snippet llGetLocalPos\n\ + llGetLocalPos()\n\ +snippet llGetLocalRot\n\ + llGetLocalRot()\n\ +snippet llGetMass\n\ + llGetMass()\n\ +snippet llGetMassMKS\n\ + llGetMassMKS()\n\ +snippet llGetMaxScaleFactor\n\ + llGetMaxScaleFactor()\n\ +snippet llGetMemoryLimit\n\ + llGetMemoryLimit()\n\ +snippet llGetMinScaleFactor\n\ + llGetMinScaleFactor()\n\ +snippet llGetNextEmail\n\ + llGetNextEmail(${1:string address}, ${2:string subject});\n\ +snippet llGetNotecardLine\n\ + llGetNotecardLine(${1:string name}, ${2:integer line})\n\ +snippet llGetNumberOfNotecardLines\n\ + llGetNumberOfNotecardLines(${1:string name})\n\ +snippet llGetNumberOfPrims\n\ + llGetNumberOfPrims()\n\ +snippet llGetNumberOfSides\n\ + llGetNumberOfSides()\n\ +snippet llGetObjectDesc\n\ + llGetObjectDesc()\n\ +snippet llGetObjectDetails\n\ + llGetObjectDetails(${1:key id}, ${2:list params})\n\ +snippet llGetObjectMass\n\ + llGetObjectMass(${1:key id})\n\ +snippet llGetObjectName\n\ + llGetObjectName()\n\ +snippet llGetObjectPermMask\n\ + llGetObjectPermMask(${1:integer mask})\n\ +snippet llGetObjectPrimCount\n\ + llGetObjectPrimCount(${1:key prim})\n\ +snippet llGetOmega\n\ + llGetOmega()\n\ +snippet llGetOwner\n\ + llGetOwner()\n\ +snippet llGetOwnerKey\n\ + llGetOwnerKey(${1:key id})\n\ +snippet llGetParcelDetails\n\ + llGetParcelDetails(${1:vector pos}, ${2:list params})\n\ +snippet llGetParcelFlags\n\ + llGetParcelFlags(${1:vector pos})\n\ +snippet llGetParcelMaxPrims\n\ + llGetParcelMaxPrims(${1:vector pos}, ${2:integer sim_wide})\n\ +snippet llGetParcelMusicURL\n\ + llGetParcelMusicURL()\n\ +snippet llGetParcelPrimCount\n\ + llGetParcelPrimCount(${1:vector pos}, ${2:integer category}, ${3:integer sim_wide})\n\ +snippet llGetParcelPrimOwners\n\ + llGetParcelPrimOwners(${1:vector pos})\n\ +snippet llGetPermissions\n\ + llGetPermissions()\n\ +snippet llGetPermissionsKey\n\ + llGetPermissionsKey()\n\ +snippet llGetPhysicsMaterial\n\ + llGetPhysicsMaterial()\n\ +snippet llGetPos\n\ + llGetPos()\n\ +snippet llGetPrimitiveParams\n\ + llGetPrimitiveParams(${1:list params})\n\ +snippet llGetPrimMediaParams\n\ + llGetPrimMediaParams(${1:integer face}, ${2:list params})\n\ +snippet llGetRegionAgentCount\n\ + llGetRegionAgentCount()\n\ +snippet llGetRegionCorner\n\ + llGetRegionCorner()\n\ +snippet llGetRegionFlags\n\ + llGetRegionFlags()\n\ +snippet llGetRegionFPS\n\ + llGetRegionFPS()\n\ +snippet llGetRegionName\n\ + llGetRegionName()\n\ +snippet llGetRegionTimeDilation\n\ + llGetRegionTimeDilation()\n\ +snippet llGetRootPosition\n\ + llGetRootPosition()\n\ +snippet llGetRootRotation\n\ + llGetRootRotation()\n\ +snippet llGetRot\n\ + llGetRot()\n\ +snippet llGetScale\n\ + llGetScale()\n\ +snippet llGetScriptName\n\ + llGetScriptName()\n\ +snippet llGetScriptState\n\ + llGetScriptState(${1:string script})\n\ +snippet llGetSimStats\n\ + llGetSimStats(${1:integer stat_type})\n\ +snippet llGetSimulatorHostname\n\ + llGetSimulatorHostname()\n\ +snippet llGetSPMaxMemory\n\ + llGetSPMaxMemory()\n\ +snippet llGetStartParameter\n\ + llGetStartParameter()\n\ +snippet llGetStaticPath\n\ + llGetStaticPath(${1:vector start}, ${2:vector end}, ${3:float radius}, ${4:list params})\n\ +snippet llGetStatus\n\ + llGetStatus(${1:integer status})\n\ +snippet llGetSubString\n\ + llGetSubString(${1:string src}, ${2:integer start}, ${3:integer end})\n\ +snippet llGetSunDirection\n\ + llGetSunDirection()\n\ +snippet llGetTexture\n\ + llGetTexture(${1:integer face})\n\ +snippet llGetTextureOffset\n\ + llGetTextureOffset(${1:integer face})\n\ +snippet llGetTextureRot\n\ + llGetTextureRot(${1:integer face})\n\ +snippet llGetTextureScale\n\ + llGetTextureScale(${1:integer face})\n\ +snippet llGetTime\n\ + llGetTime()\n\ +snippet llGetTimeOfDay\n\ + llGetTimeOfDay()\n\ +snippet llGetTimestamp\n\ + llGetTimestamp()\n\ +snippet llGetTorque\n\ + llGetTorque()\n\ +snippet llGetUnixTime\n\ + llGetUnixTime()\n\ +snippet llGetUsedMemory\n\ + llGetUsedMemory()\n\ +snippet llGetUsername\n\ + llGetUsername(${1:key id})\n\ +snippet llGetVel\n\ + llGetVel()\n\ +snippet llGetWallclock\n\ + llGetWallclock()\n\ +snippet llGiveInventory\n\ + llGiveInventory(${1:key destination}, ${2:string inventory});\n\ +snippet llGiveInventoryList\n\ + llGiveInventoryList(${1:key target}, ${2:string folder}, ${3:list inventory});\n\ +snippet llGiveMoney\n\ + llGiveMoney(${1:key destination}, ${2:integer amount})\n\ +snippet llGround\n\ + llGround(${1:vector offset})\n\ +snippet llGroundContour\n\ + llGroundContour(${1:vector offset})\n\ +snippet llGroundNormal\n\ + llGroundNormal(${1:vector offset})\n\ +snippet llGroundRepel\n\ + llGroundRepel(${1:float height}, ${2:integer water}, ${3:float tau});\n\ +snippet llGroundSlope\n\ + llGroundSlope(${1:vector offset})\n\ +snippet llHTTPRequest\n\ + llHTTPRequest(${1:string url}, ${2:list parameters}, ${3:string body})\n\ +snippet llHTTPResponse\n\ + llHTTPResponse(${1:key request_id}, ${2:integer status}, ${3:string body});\n\ +snippet llInsertString\n\ + llInsertString(${1:string dst}, ${2:integer pos}, ${3:string src})\n\ +snippet llInstantMessage\n\ + llInstantMessage(${1:key user}, ${2:string message});\n\ +snippet llIntegerToBase64\n\ + llIntegerToBase64(${1:integer number})\n\ +snippet llJson2List\n\ + llJson2List(${1:string json})\n\ +snippet llJsonGetValue\n\ + llJsonGetValue(${1:string json}, ${2:list specifiers})\n\ +snippet llJsonSetValue\n\ + llJsonSetValue(${1:string json}, ${2:list specifiers}, ${3:string newValue})\n\ +snippet llJsonValueType\n\ + llJsonValueType(${1:string json}, ${2:list specifiers})\n\ +snippet llKey2Name\n\ + llKey2Name(${1:key id})\n\ +snippet llKeyCountKeyValue\n\ + llKeyCountKeyValue()\n\ +snippet llKeysKeyValue\n\ + llKeysKeyValue(${1:integer first}, ${2:integer count})\n\ +snippet llLinkParticleSystem\n\ + llLinkParticleSystem(${1:integer link}, ${2:list rules});\n\ +snippet llLinkSitTarget\n\ + llLinkSitTarget(${1:integer link}, ${2:vector offset}, ${3:rotation rot});\n\ +snippet llList2CSV\n\ + llList2CSV(${1:list src})\n\ +snippet llList2Float\n\ + llList2Float(${1:list src}, ${2:integer index})\n\ +snippet llList2Integer\n\ + llList2Integer(${1:list src}, ${2:integer index})\n\ +snippet llList2Json\n\ + llList2Json(${1:string type}, ${2:list values})\n\ +snippet llList2Key\n\ + llList2Key(${1:list src}, ${2:integer index})\n\ +snippet llList2List\n\ + llList2List(${1:list src}, ${2:integer start}, ${3:integer end})\n\ +snippet llList2ListStrided\n\ + llList2ListStrided(${1:list src}, ${2:integer start}, ${3:integer end}, ${4:integer stride})\n\ +snippet llList2Rot\n\ + llList2Rot(${1:list src}, ${2:integer index})\n\ +snippet llList2String\n\ + llList2String(${1:list src}, ${2:integer index})\n\ +snippet llList2Vector\n\ + llList2Vector(${1:list src}, ${2:integer index})\n\ +snippet llListen\n\ + llListen(${1:integer channel}, ${2:string name}, ${3:key id}, ${4:string msg})\n\ +snippet llListenControl\n\ + llListenControl(${1:integer handle}, ${2:integer active});\n\ +snippet llListenRemove\n\ + llListenRemove(${1:integer handle});\n\ +snippet llListFindList\n\ + llListFindList(${1:list src}, ${2:list test})\n\ +snippet llListInsertList\n\ + llListInsertList(${1:list dest}, ${2:list src}, ${3:integer start})\n\ +snippet llListRandomize\n\ + llListRandomize(${1:list src}, ${2:integer stride})\n\ +snippet llListReplaceList\n\ + llListReplaceList(${1:list dest}, ${2:list src}, ${3:integer start}, ${4:integer end})\n\ +snippet llListSort\n\ + llListSort(${1:list src}, ${2:integer stride}, ${3:integer ascending})\n\ +snippet llListStatistics\n\ + llListStatistics(${1:integer operation}, ${2:list src})\n\ +snippet llLoadURL\n\ + llLoadURL(${1:key agent}, ${2:string message}, ${3:string url});\n\ +snippet llLog\n\ + llLog(${1:float val})\n\ +snippet llLog10\n\ + llLog10(${1:float val})\n\ +snippet llLookAt\n\ + llLookAt(${1:vector target}, ${2:float strength}, ${3:float damping});\n\ +snippet llLoopSound\n\ + llLoopSound(${1:string sound}, ${2:float volume});\n\ +snippet llLoopSoundMaster\n\ + llLoopSoundMaster(${1:string sound}, ${2:float volume});\n\ +snippet llLoopSoundSlave\n\ + llLoopSoundSlave(${1:string sound}, ${2:float volume});\n\ +snippet llManageEstateAccess\n\ + llManageEstateAccess(${1:integer action}, ${2:key agent})\n\ +snippet llMapDestination\n\ + llMapDestination(${1:string simname}, ${2:vector pos}, ${3:vector look_at});\n\ +snippet llMD5String\n\ + llMD5String(${1:string src}, ${2:integer nonce})\n\ +snippet llMessageLinked\n\ + llMessageLinked(${1:integer link}, ${2:integer num}, ${3:string str}, ${4:key id});\n\ +snippet llMinEventDelay\n\ + llMinEventDelay(${1:float delay});\n\ +snippet llModifyLand\n\ + llModifyLand(${1:integer action}, ${2:integer brush});\n\ +snippet llModPow\n\ + llModPow(${1:integer a}, ${2:integer b}, ${3:integer c})\n\ +snippet llMoveToTarget\n\ + llMoveToTarget(${1:vector target}, ${2:float tau});\n\ +snippet llNavigateTo\n\ + llNavigateTo(${1:vector pos}, ${2:list options});\n\ +snippet llOffsetTexture\n\ + llOffsetTexture(${1:float u}, ${2:float v}, ${3:integer face});\n\ +snippet llOpenRemoteDataChannel\n\ + llOpenRemoteDataChannel();\n\ +snippet llOverMyLand\n\ + llOverMyLand(${1:key id})\n\ +snippet llOwnerSay\n\ + llOwnerSay(${1:string msg});\n\ +snippet llParcelMediaCommandList\n\ + llParcelMediaCommandList(${1:list commandList});\n\ +snippet llParcelMediaQuery\n\ + llParcelMediaQuery(${1:list query})\n\ +snippet llParseString2List\n\ + llParseString2List(${1:string src}, ${2:list separators}, ${3:list spacers})\n\ +snippet llParseStringKeepNulls\n\ + llParseStringKeepNulls(${1:string src}, ${2:list separators}, ${3:list spacers})\n\ +snippet llParticleSystem\n\ + llParticleSystem(${1:list rules});\n\ +snippet llPassCollisions\n\ + llPassCollisions(${1:integer pass});\n\ +snippet llPassTouches\n\ + llPassTouches(${1:integer pass});\n\ +snippet llPatrolPoints\n\ + llPatrolPoints(${1:list patrolPoints}, ${2:list options});\n\ +snippet llPlaySound\n\ + llPlaySound(${1:string sound}, ${2:float volume});\n\ +snippet llPlaySoundSlave\n\ + llPlaySoundSlave(${1:string sound}, ${2:float volume});\n\ +snippet llPow\n\ + llPow(${1:float base}, ${2:float exponent})\n\ +snippet llPreloadSound\n\ + llPreloadSound(${1:string sound});\n\ +snippet llPursue\n\ + llPursue(${1:key target}, ${2:list options});\n\ +snippet llPushObject\n\ + llPushObject(${1:key target}, ${2:vector impulse}, ${3:vector ang_impulse}, ${4:integer local});\n\ +snippet llReadKeyValue\n\ + llReadKeyValue(${1:string k})\n\ +snippet llRegionSay\n\ + llRegionSay(${1:integer channel}, ${2:string msg});\n\ +snippet llRegionSayTo\n\ + llRegionSayTo(${1:key target}, ${2:integer channel}, ${3:string msg});\n\ +snippet llReleaseControls\n\ + llReleaseControls();\n\ +snippet llReleaseURL\n\ + llReleaseURL(${1:string url});\n\ +snippet llRemoteDataReply\n\ + llRemoteDataReply(${1:key channel}, ${2:key message_id}, ${3:string sdata}, ${4:integer idata});\n\ +snippet llRemoteLoadScriptPin\n\ + llRemoteLoadScriptPin(${1:key target}, ${2:string name}, ${3:integer pin}, ${4:integer running}, ${5:integer start_param});\n\ +snippet llRemoveFromLandBanList\n\ + llRemoveFromLandBanList(${1:key agent});\n\ +snippet llRemoveFromLandPassList\n\ + llRemoveFromLandPassList(${1:key agent});\n\ +snippet llRemoveInventory\n\ + llRemoveInventory(${1:string item});\n\ +snippet llRemoveVehicleFlags\n\ + llRemoveVehicleFlags(${1:integer flags});\n\ +snippet llRequestAgentData\n\ + llRequestAgentData(${1:key id}, ${2:integer data})\n\ +snippet llRequestDisplayName\n\ + llRequestDisplayName(${1:key id})\n\ +snippet llRequestExperiencePermissions\n\ + llRequestExperiencePermissions(${1:key agent}, ${2:string name})\n\ +snippet llRequestInventoryData\n\ + llRequestInventoryData(${1:string name})\n\ +snippet llRequestPermissions\n\ + llRequestPermissions(${1:key agent}, ${2:integer permissions})\n\ +snippet llRequestSecureURL\n\ + llRequestSecureURL()\n\ +snippet llRequestSimulatorData\n\ + llRequestSimulatorData(${1:string region}, ${2:integer data})\n\ +snippet llRequestURL\n\ + llRequestURL()\n\ +snippet llRequestUsername\n\ + llRequestUsername(${1:key id})\n\ +snippet llResetAnimationOverride\n\ + llResetAnimationOverride(${1:string anim_state});\n\ +snippet llResetLandBanList\n\ + llResetLandBanList();\n\ +snippet llResetLandPassList\n\ + llResetLandPassList();\n\ +snippet llResetOtherScript\n\ + llResetOtherScript(${1:string name});\n\ +snippet llResetScript\n\ + llResetScript();\n\ +snippet llResetTime\n\ + llResetTime();\n\ +snippet llReturnObjectsByID\n\ + llReturnObjectsByID(${1:list objects})\n\ +snippet llReturnObjectsByOwner\n\ + llReturnObjectsByOwner(${1:key owner}, ${2:integer scope})\n\ +snippet llRezAtRoot\n\ + llRezAtRoot(${1:string inventory}, ${2:vector position}, ${3:vector velocity}, ${4:rotation rot}, ${5:integer param});\n\ +snippet llRezObject\n\ + llRezObject(${1:string inventory}, ${2:vector pos}, ${3:vector vel}, ${4:rotation rot}, ${5:integer param});\n\ +snippet llRot2Angle\n\ + llRot2Angle(${1:rotation rot})\n\ +snippet llRot2Axis\n\ + llRot2Axis(${1:rotation rot})\n\ +snippet llRot2Euler\n\ + llRot2Euler(${1:rotation quat})\n\ +snippet llRot2Fwd\n\ + llRot2Fwd(${1:rotation q})\n\ +snippet llRot2Left\n\ + llRot2Left(${1:rotation q})\n\ +snippet llRot2Up\n\ + llRot2Up(${1:rotation q})\n\ +snippet llRotateTexture\n\ + llRotateTexture(${1:float angle}, ${2:integer face});\n\ +snippet llRotBetween\n\ + llRotBetween(${1:vector start}, ${2:vector end})\n\ +snippet llRotLookAt\n\ + llRotLookAt(${1:rotation target_direction}, ${2:float strength}, ${3:float damping});\n\ +snippet llRotTarget\n\ + llRotTarget(${1:rotation rot}, ${2:float error})\n\ +snippet llRotTargetRemove\n\ + llRotTargetRemove(${1:integer handle});\n\ +snippet llRound\n\ + llRound(${1:float val})\n\ +snippet llSameGroup\n\ + llSameGroup(${1:key group})\n\ +snippet llSay\n\ + llSay(${1:integer channel}, ${2:string msg});\n\ +snippet llScaleByFactor\n\ + llScaleByFactor(${1:float scaling_factor})\n\ +snippet llScaleTexture\n\ + llScaleTexture(${1:float u}, ${2:float v}, ${3:integer face});\n\ +snippet llScriptDanger\n\ + llScriptDanger(${1:vector pos})\n\ +snippet llScriptProfiler\n\ + llScriptProfiler(${1:integer flags});\n\ +snippet llSendRemoteData\n\ + llSendRemoteData(${1:key channel}, ${2:string dest}, ${3:integer idata}, ${4:string sdata})\n\ +snippet llSensor\n\ + llSensor(${1:string name}, ${2:key id}, ${3:integer type}, ${4:float range}, ${5:float arc});\n\ +snippet llSensorRepeat\n\ + llSensorRepeat(${1:string name}, ${2:key id}, ${3:integer type}, ${4:float range}, ${5:float arc}, ${6:float rate});\n\ +snippet llSetAlpha\n\ + llSetAlpha(${1:float alpha}, ${2:integer face});\n\ +snippet llSetAngularVelocity\n\ + llSetAngularVelocity(${1:vector force}, ${2:integer local});\n\ +snippet llSetAnimationOverride\n\ + llSetAnimationOverride(${1:string anim_state}, ${2:string anim})\n\ +snippet llSetBuoyancy\n\ + llSetBuoyancy(${1:float buoyancy});\n\ +snippet llSetCameraAtOffset\n\ + llSetCameraAtOffset(${1:vector offset});\n\ +snippet llSetCameraEyeOffset\n\ + llSetCameraEyeOffset(${1:vector offset});\n\ +snippet llSetCameraParams\n\ + llSetCameraParams(${1:list rules});\n\ +snippet llSetClickAction\n\ + llSetClickAction(${1:integer action});\n\ +snippet llSetColor\n\ + llSetColor(${1:vector color}, ${2:integer face});\n\ +snippet llSetContentType\n\ + llSetContentType(${1:key request_id}, ${2:integer content_type});\n\ +snippet llSetDamage\n\ + llSetDamage(${1:float damage});\n\ +snippet llSetForce\n\ + llSetForce(${1:vector force}, ${2:integer local});\n\ +snippet llSetForceAndTorque\n\ + llSetForceAndTorque(${1:vector force}, ${2:vector torque}, ${3:integer local});\n\ +snippet llSetHoverHeight\n\ + llSetHoverHeight(${1:float height}, ${2:integer water}, ${3:float tau});\n\ +snippet llSetKeyframedMotion\n\ + llSetKeyframedMotion(${1:list keyframes}, ${2:list options});\n\ +snippet llSetLinkAlpha\n\ + llSetLinkAlpha(${1:integer link}, ${2:float alpha}, ${3:integer face});\n\ +snippet llSetLinkCamera\n\ + llSetLinkCamera(${1:integer link}, ${2:vector eye}, ${3:vector at});\n\ +snippet llSetLinkColor\n\ + llSetLinkColor(${1:integer link}, ${2:vector color}, ${3:integer face});\n\ +snippet llSetLinkMedia\n\ + llSetLinkMedia(${1:integer link}, ${2:integer face}, ${3:list params});\n\ +snippet llSetLinkPrimitiveParams\n\ + llSetLinkPrimitiveParams(${1:integer link}, ${2:list rules});\n\ +snippet llSetLinkPrimitiveParamsFast\n\ + llSetLinkPrimitiveParamsFast(${1:integer link}, ${2:list rules});\n\ +snippet llSetLinkTexture\n\ + llSetLinkTexture(${1:integer link}, ${2:string texture}, ${3:integer face});\n\ +snippet llSetLinkTextureAnim\n\ + llSetLinkTextureAnim(${1:integer link}, ${2:integer mode}, ${3:integer face}, ${4:integer sizex}, ${5:integer sizey}, ${6:float start}, ${7:float length}, ${8:float rate});\n\ +snippet llSetLocalRot\n\ + llSetLocalRot(${1:rotation rot});\n\ +snippet llSetMemoryLimit\n\ + llSetMemoryLimit(${1:integer limit})\n\ +snippet llSetObjectDesc\n\ + llSetObjectDesc(${1:string description});\n\ +snippet llSetObjectName\n\ + llSetObjectName(${1:string name});\n\ +snippet llSetParcelMusicURL\n\ + llSetParcelMusicURL(${1:string url});\n\ +snippet llSetPayPrice\n\ + llSetPayPrice(${1:integer price}, [${2:integer price_button_a}, ${3:integer price_button_b}, ${4:integer price_button_c}, ${5:integer price_button_d}]);\n\ +snippet llSetPhysicsMaterial\n\ + llSetPhysicsMaterial(${1:integer mask}, ${2:float gravity_multiplier}, ${3:float restitution}, ${4:float friction}, ${5:float density});\n\ +snippet llSetPos\n\ + llSetPos(${1:vector pos});\n\ +snippet llSetPrimitiveParams\n\ + llSetPrimitiveParams(${1:list rules});\n\ +snippet llSetPrimMediaParams\n\ + llSetPrimMediaParams(${1:integer face}, ${2:list params});\n\ +snippet llSetRegionPos\n\ + llSetRegionPos(${1:vector position})\n\ +snippet llSetRemoteScriptAccessPin\n\ + llSetRemoteScriptAccessPin(${1:integer pin});\n\ +snippet llSetRot\n\ + llSetRot(${1:rotation rot});\n\ +snippet llSetScale\n\ + llSetScale(${1:vector size});\n\ +snippet llSetScriptState\n\ + llSetScriptState(${1:string name}, ${2:integer run});\n\ +snippet llSetSitText\n\ + llSetSitText(${1:string text});\n\ +snippet llSetSoundQueueing\n\ + llSetSoundQueueing(${1:integer queue});\n\ +snippet llSetSoundRadius\n\ + llSetSoundRadius(${1:float radius});\n\ +snippet llSetStatus\n\ + llSetStatus(${1:integer status}, ${2:integer value});\n\ +snippet llSetText\n\ + llSetText(${1:string text}, ${2:vector color}, ${3:float alpha});\n\ +snippet llSetTexture\n\ + llSetTexture(${1:string texture}, ${2:integer face});\n\ +snippet llSetTextureAnim\n\ + llSetTextureAnim(${1:integer mode}, ${2:integer face}, ${3:integer sizex}, ${4:integer sizey}, ${5:float start}, ${6:float length}, ${7:float rate});\n\ +snippet llSetTimerEvent\n\ + llSetTimerEvent(${1:float sec});\n\ +snippet llSetTorque\n\ + llSetTorque(${1:vector torque}, ${2:integer local});\n\ +snippet llSetTouchText\n\ + llSetTouchText(${1:string text});\n\ +snippet llSetVehicleFlags\n\ + llSetVehicleFlags(${1:integer flags});\n\ +snippet llSetVehicleFloatParam\n\ + llSetVehicleFloatParam(${1:integer param}, ${2:float value});\n\ +snippet llSetVehicleRotationParam\n\ + llSetVehicleRotationParam(${1:integer param}, ${2:rotation rot});\n\ +snippet llSetVehicleType\n\ + llSetVehicleType(${1:integer type});\n\ +snippet llSetVehicleVectorParam\n\ + llSetVehicleVectorParam(${1:integer param}, ${2:vector vec});\n\ +snippet llSetVelocity\n\ + llSetVelocity(${1:vector force}, ${2:integer local});\n\ +snippet llSHA1String\n\ + llSHA1String(${1:string src})\n\ +snippet llShout\n\ + llShout(${1:integer channel}, ${2:string msg});\n\ +snippet llSin\n\ + llSin(${1:float theta})\n\ +snippet llSitTarget\n\ + llSitTarget(${1:vector offset}, ${2:rotation rot});\n\ +snippet llSleep\n\ + llSleep(${1:float sec});\n\ +snippet llSqrt\n\ + llSqrt(${1:float val})\n\ +snippet llStartAnimation\n\ + llStartAnimation(${1:string anim});\n\ +snippet llStopAnimation\n\ + llStopAnimation(${1:string anim});\n\ +snippet llStopHover\n\ + llStopHover();\n\ +snippet llStopLookAt\n\ + llStopLookAt();\n\ +snippet llStopMoveToTarget\n\ + llStopMoveToTarget();\n\ +snippet llStopSound\n\ + llStopSound();\n\ +snippet llStringLength\n\ + llStringLength(${1:string str})\n\ +snippet llStringToBase64\n\ + llStringToBase64(${1:string str})\n\ +snippet llStringTrim\n\ + llStringTrim(${1:string src}, ${2:integer type})\n\ +snippet llSubStringIndex\n\ + llSubStringIndex(${1:string source}, ${2:string pattern})\n\ +snippet llTakeControls\n\ + llTakeControls(${1:integer controls}, ${2:integer accept}, ${3:integer pass_on});\n\ +snippet llTan\n\ + llTan(${1:float theta})\n\ +snippet llTarget\n\ + llTarget(${1:vector position}, ${2:float range})\n\ +snippet llTargetOmega\n\ + llTargetOmega(${1:vector axis}, ${2:float spinrate}, ${3:float gain});\n\ +snippet llTargetRemove\n\ + llTargetRemove(${1:integer handle});\n\ +snippet llTeleportAgent\n\ + llTeleportAgent(${1:key agent}, ${2:string landmark}, ${3:vector position}, ${4:vector look_at});\n\ +snippet llTeleportAgentGlobalCoords\n\ + llTeleportAgentGlobalCoords(${1:key agent}, ${2:vector global_coordinates}, ${3:vector region_coordinates}, ${4:vector look_at});\n\ +snippet llTeleportAgentHome\n\ + llTeleportAgentHome(${1:key agent});\n\ +snippet llTextBox\n\ + llTextBox(${1:key agent}, ${2:string message}, ${3:integer channel});\n\ +snippet llToLower\n\ + llToLower(${1:string src})\n\ +snippet llToUpper\n\ + llToUpper(${1:string src})\n\ +snippet llTransferLindenDollars\n\ + llTransferLindenDollars(${1:key destination}, ${2:integer amount})\n\ +snippet llTriggerSound\n\ + llTriggerSound(${1:string sound}, ${2:float volume});\n\ +snippet llTriggerSoundLimited\n\ + llTriggerSoundLimited(${1:string sound}, ${2:float volume}, ${3:vector top_north_east}, ${4:vector bottom_south_west});\n\ +snippet llUnescapeURL\n\ + llUnescapeURL(${1:string url})\n\ +snippet llUnSit\n\ + llUnSit(${1:key id});\n\ +snippet llUpdateCharacter\n\ + llUpdateCharacter(${1:list options})\n\ +snippet llUpdateKeyValue\n\ + llUpdateKeyValue(${1:string k}, ${2:string v}, ${3:integer checked}, ${4:string ov})\n\ +snippet llVecDist\n\ + llVecDist(${1:vector vec_a}, ${2:vector vec_b})\n\ +snippet llVecMag\n\ + llVecMag(${1:vector vec})\n\ +snippet llVecNorm\n\ + llVecNorm(${1:vector vec})\n\ +snippet llVolumeDetect\n\ + llVolumeDetect(${1:integer detect});\n\ +snippet llWanderWithin\n\ + llWanderWithin(${1:vector origin}, ${2:vector dist}, ${3:list options});\n\ +snippet llWater\n\ + llWater(${1:vector offset});\n\ +snippet llWhisper\n\ + llWhisper(${1:integer channel}, ${2:string msg});\n\ +snippet llWind\n\ + llWind(${1:vector offset});\n\ +snippet llXorBase64\n\ + llXorBase64(${1:string str1}, ${2:string str2})\n\ +snippet money\n\ + money(${1:key id}, ${2:integer amount})\n\ + {\n\ + $0\n\ + }\n\ +snippet object_rez\n\ + object_rez(${1:key id})\n\ + {\n\ + $0\n\ + }\n\ +snippet on_rez\n\ + on_rez(${1:integer start_param})\n\ + {\n\ + $0\n\ + }\n\ +snippet path_update\n\ + path_update(${1:integer type}, ${2:list reserved})\n\ + {\n\ + $0\n\ + }\n\ +snippet remote_data\n\ + remote_data(${1:integer event_type}, ${2:key channel}, ${3:key message_id}, ${4:string sender}, ${5:integer idata}, ${6:string sdata})\n\ + {\n\ + $0\n\ + }\n\ +snippet run_time_permissions\n\ + run_time_permissions(${1:integer perm})\n\ + {\n\ + $0\n\ + }\n\ +snippet sensor\n\ + sensor(${1:integer index})\n\ + {\n\ + $0\n\ + }\n\ +snippet state\n\ + state ${1:name}\n\ +snippet touch\n\ + touch(${1:integer index})\n\ + {\n\ + $0\n\ + }\n\ +snippet touch_end\n\ + touch_end(${1:integer index})\n\ + {\n\ + $0\n\ + }\n\ +snippet touch_start\n\ + touch_start(${1:integer index})\n\ + {\n\ + $0\n\ + }\n\ +snippet transaction_result\n\ + transaction_result(${1:key id}, ${2:integer success}, ${3:string data})\n\ + {\n\ + $0\n\ + }\n\ +snippet while\n\ + while (${1:condition})\n\ + {\n\ + $0\n\ + }\n\ +"; +exports.scope = "lsl"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lua.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lua.js new file mode 100644 index 00000000..a4678bb9 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lua.js @@ -0,0 +1,28 @@ +define("ace/snippets/lua",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet #!\n\ + #!/usr/bin/env lua\n\ + $1\n\ +snippet local\n\ + local ${1:x} = ${2:1}\n\ +snippet fun\n\ + function ${1:fname}(${2:...})\n\ + ${3:-- body}\n\ + end\n\ +snippet for\n\ + for ${1:i}=${2:1},${3:10} do\n\ + ${4:print(i)}\n\ + end\n\ +snippet forp\n\ + for ${1:i},${2:v} in pairs(${3:table_name}) do\n\ + ${4:-- body}\n\ + end\n\ +snippet fori\n\ + for ${1:i},${2:v} in ipairs(${3:table_name}) do\n\ + ${4:-- body}\n\ + end\n\ +"; +exports.scope = "lua"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/luapage.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/luapage.js new file mode 100644 index 00000000..02134aae --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/luapage.js @@ -0,0 +1,7 @@ +define("ace/snippets/luapage",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "luapage"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lucene.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lucene.js new file mode 100644 index 00000000..47151fc1 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/lucene.js @@ -0,0 +1,7 @@ +define("ace/snippets/lucene",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "lucene"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/makefile.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/makefile.js new file mode 100644 index 00000000..a1f40999 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/makefile.js @@ -0,0 +1,11 @@ +define("ace/snippets/makefile",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet ifeq\n\ + ifeq (${1:cond0},${2:cond1})\n\ + ${3:code}\n\ + endif\n\ +"; +exports.scope = "makefile"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/markdown.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/markdown.js new file mode 100644 index 00000000..0eceacaa --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/markdown.js @@ -0,0 +1,95 @@ +define("ace/snippets/markdown",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# Markdown\n\ +\n\ +# Includes octopress (http://octopress.org/) snippets\n\ +\n\ +snippet [\n\ + [${1:text}](http://${2:address} \"${3:title}\")\n\ +snippet [*\n\ + [${1:link}](${2:`@*`} \"${3:title}\")${4}\n\ +\n\ +snippet [:\n\ + [${1:id}]: http://${2:url} \"${3:title}\"\n\ +snippet [:*\n\ + [${1:id}]: ${2:`@*`} \"${3:title}\"\n\ +\n\ +snippet ![\n\ + ![${1:alttext}](${2:/images/image.jpg} \"${3:title}\")\n\ +snippet ![*\n\ + ![${1:alt}](${2:`@*`} \"${3:title}\")${4}\n\ +\n\ +snippet ![:\n\ + ![${1:id}]: ${2:url} \"${3:title}\"\n\ +snippet ![:*\n\ + ![${1:id}]: ${2:`@*`} \"${3:title}\"\n\ +\n\ +snippet ===\n\ +regex /^/=+/=*//\n\ + ${PREV_LINE/./=/g}\n\ + \n\ + ${0}\n\ +snippet ---\n\ +regex /^/-+/-*//\n\ + ${PREV_LINE/./-/g}\n\ + \n\ + ${0}\n\ +snippet blockquote\n\ + {% blockquote %}\n\ + ${1:quote}\n\ + {% endblockquote %}\n\ +\n\ +snippet blockquote-author\n\ + {% blockquote ${1:author}, ${2:title} %}\n\ + ${3:quote}\n\ + {% endblockquote %}\n\ +\n\ +snippet blockquote-link\n\ + {% blockquote ${1:author} ${2:URL} ${3:link_text} %}\n\ + ${4:quote}\n\ + {% endblockquote %}\n\ +\n\ +snippet bt-codeblock-short\n\ + ```\n\ + ${1:code_snippet}\n\ + ```\n\ +\n\ +snippet bt-codeblock-full\n\ + ``` ${1:language} ${2:title} ${3:URL} ${4:link_text}\n\ + ${5:code_snippet}\n\ + ```\n\ +\n\ +snippet codeblock-short\n\ + {% codeblock %}\n\ + ${1:code_snippet}\n\ + {% endcodeblock %}\n\ +\n\ +snippet codeblock-full\n\ + {% codeblock ${1:title} lang:${2:language} ${3:URL} ${4:link_text} %}\n\ + ${5:code_snippet}\n\ + {% endcodeblock %}\n\ +\n\ +snippet gist-full\n\ + {% gist ${1:gist_id} ${2:filename} %}\n\ +\n\ +snippet gist-short\n\ + {% gist ${1:gist_id} %}\n\ +\n\ +snippet img\n\ + {% img ${1:class} ${2:URL} ${3:width} ${4:height} ${5:title_text} ${6:alt_text} %}\n\ +\n\ +snippet youtube\n\ + {% youtube ${1:video_id} %}\n\ +\n\ +# The quote should appear only once in the text. It is inherently part of it.\n\ +# See http://octopress.org/docs/plugins/pullquote/ for more info.\n\ +\n\ +snippet pullquote\n\ + {% pullquote %}\n\ + ${1:text} {\" ${2:quote} \"} ${3:text}\n\ + {% endpullquote %}\n\ +"; +exports.scope = "markdown"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mask.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mask.js new file mode 100644 index 00000000..c03d2a0f --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mask.js @@ -0,0 +1,7 @@ +define("ace/snippets/mask",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "mask"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/matlab.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/matlab.js new file mode 100644 index 00000000..15b63a82 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/matlab.js @@ -0,0 +1,7 @@ +define("ace/snippets/matlab",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "matlab"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mel.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mel.js new file mode 100644 index 00000000..cda71654 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mel.js @@ -0,0 +1,7 @@ +define("ace/snippets/mel",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "mel"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mips_assembler.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mips_assembler.js new file mode 100644 index 00000000..9ced9202 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mips_assembler.js @@ -0,0 +1,7 @@ +define("ace/snippets/mips_assembler",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "mips_assembler"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mipsassembler.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mipsassembler.js new file mode 100644 index 00000000..7c06b691 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mipsassembler.js @@ -0,0 +1,7 @@ +define("ace/snippets/mipsassembler",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = ""; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mushcode.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mushcode.js new file mode 100644 index 00000000..2efb023a --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mushcode.js @@ -0,0 +1,7 @@ +define("ace/snippets/mushcode",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "mushcode"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mysql.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mysql.js new file mode 100644 index 00000000..5c810d0c --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/mysql.js @@ -0,0 +1,7 @@ +define("ace/snippets/mysql",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "mysql"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/nix.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/nix.js new file mode 100644 index 00000000..ff789601 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/nix.js @@ -0,0 +1,7 @@ +define("ace/snippets/nix",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "nix"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/objectivec.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/objectivec.js new file mode 100644 index 00000000..7270a4fb --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/objectivec.js @@ -0,0 +1,7 @@ +define("ace/snippets/objectivec",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "objectivec"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ocaml.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ocaml.js new file mode 100644 index 00000000..bf2fba96 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ocaml.js @@ -0,0 +1,7 @@ +define("ace/snippets/ocaml",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "ocaml"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/pascal.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/pascal.js new file mode 100644 index 00000000..c5855014 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/pascal.js @@ -0,0 +1,7 @@ +define("ace/snippets/pascal",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "pascal"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/perl.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/perl.js new file mode 100644 index 00000000..e5da0bc4 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/perl.js @@ -0,0 +1,354 @@ +define("ace/snippets/perl",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# #!/usr/bin/perl\n\ +snippet #!\n\ + #!/usr/bin/env perl\n\ +\n\ +# Hash Pointer\n\ +snippet .\n\ + =>\n\ +# Function\n\ +snippet sub\n\ + sub ${1:function_name} {\n\ + ${2:#body ...}\n\ + }\n\ +# Conditional\n\ +snippet if\n\ + if (${1}) {\n\ + ${2:# body...}\n\ + }\n\ +# Conditional if..else\n\ +snippet ife\n\ + if (${1}) {\n\ + ${2:# body...}\n\ + }\n\ + else {\n\ + ${3:# else...}\n\ + }\n\ +# Conditional if..elsif..else\n\ +snippet ifee\n\ + if (${1}) {\n\ + ${2:# body...}\n\ + }\n\ + elsif (${3}) {\n\ + ${4:# elsif...}\n\ + }\n\ + else {\n\ + ${5:# else...}\n\ + }\n\ +# Conditional One-line\n\ +snippet xif\n\ + ${1:expression} if ${2:condition};${3}\n\ +# Unless conditional\n\ +snippet unless\n\ + unless (${1}) {\n\ + ${2:# body...}\n\ + }\n\ +# Unless conditional One-line\n\ +snippet xunless\n\ + ${1:expression} unless ${2:condition};${3}\n\ +# Try/Except\n\ +snippet eval\n\ + local $@;\n\ + eval {\n\ + ${1:# do something risky...}\n\ + };\n\ + if (my $e = $@) {\n\ + ${2:# handle failure...}\n\ + }\n\ +# While Loop\n\ +snippet wh\n\ + while (${1}) {\n\ + ${2:# body...}\n\ + }\n\ +# While Loop One-line\n\ +snippet xwh\n\ + ${1:expression} while ${2:condition};${3}\n\ +# C-style For Loop\n\ +snippet cfor\n\ + for (my $${2:var} = 0; $$2 < ${1:count}; $$2${3:++}) {\n\ + ${4:# body...}\n\ + }\n\ +# For loop one-line\n\ +snippet xfor\n\ + ${1:expression} for @${2:array};${3}\n\ +# Foreach Loop\n\ +snippet for\n\ + foreach my $${1:x} (@${2:array}) {\n\ + ${3:# body...}\n\ + }\n\ +# Foreach Loop One-line\n\ +snippet fore\n\ + ${1:expression} foreach @${2:array};${3}\n\ +# Package\n\ +snippet package\n\ + package ${1:`substitute(Filename('', 'Page Title'), '^.', '\\u&', '')`};\n\ +\n\ + ${2}\n\ +\n\ + 1;\n\ +\n\ + __END__\n\ +# Package syntax perl >= 5.14\n\ +snippet packagev514\n\ + package ${1:`substitute(Filename('', 'Page Title'), '^.', '\\u&', '')`} ${2:0.99};\n\ +\n\ + ${3}\n\ +\n\ + 1;\n\ +\n\ + __END__\n\ +#moose\n\ +snippet moose\n\ + use Moose;\n\ + use namespace::autoclean;\n\ + ${1:#}BEGIN {extends '${2:ParentClass}'};\n\ +\n\ + ${3}\n\ +# parent\n\ +snippet parent\n\ + use parent qw(${1:Parent Class});\n\ +# Read File\n\ +snippet slurp\n\ + my $${1:var} = do { local $/; open my $file, '<', \"${2:file}\"; <$file> };\n\ + ${3}\n\ +# strict warnings\n\ +snippet strwar\n\ + use strict;\n\ + use warnings;\n\ +# older versioning with perlcritic bypass\n\ +snippet vers\n\ + ## no critic\n\ + our $VERSION = '${1:version}';\n\ + eval $VERSION;\n\ + ## use critic\n\ +# new 'switch' like feature\n\ +snippet switch\n\ + use feature 'switch';\n\ +\n\ +# Anonymous subroutine\n\ +snippet asub\n\ + sub {\n\ + ${1:# body }\n\ + }\n\ +\n\ +\n\ +\n\ +# Begin block\n\ +snippet begin\n\ + BEGIN {\n\ + ${1:# begin body}\n\ + }\n\ +\n\ +# call package function with some parameter\n\ +snippet pkgmv\n\ + __PACKAGE__->${1:package_method}(${2:var})\n\ +\n\ +# call package function without a parameter\n\ +snippet pkgm\n\ + __PACKAGE__->${1:package_method}()\n\ +\n\ +# call package \"get_\" function without a parameter\n\ +snippet pkget\n\ + __PACKAGE__->get_${1:package_method}()\n\ +\n\ +# call package function with a parameter\n\ +snippet pkgetv\n\ + __PACKAGE__->get_${1:package_method}(${2:var})\n\ +\n\ +# complex regex\n\ +snippet qrx\n\ + qr/\n\ + ${1:regex}\n\ + /xms\n\ +\n\ +#simpler regex\n\ +snippet qr/\n\ + qr/${1:regex}/x\n\ +\n\ +#given\n\ +snippet given\n\ + given ($${1:var}) {\n\ + ${2:# cases}\n\ + ${3:# default}\n\ + }\n\ +\n\ +# switch-like case\n\ +snippet when\n\ + when (${1:case}) {\n\ + ${2:# body}\n\ + }\n\ +\n\ +# hash slice\n\ +snippet hslice\n\ + @{ ${1:hash} }{ ${2:array} }\n\ +\n\ +\n\ +# map\n\ +snippet map\n\ + map { ${2: body } } ${1: @array } ;\n\ +\n\ +\n\ +\n\ +# Pod stub\n\ +snippet ppod\n\ + =head1 NAME\n\ +\n\ + ${1:ClassName} - ${2:ShortDesc}\n\ +\n\ + =head1 SYNOPSIS\n\ +\n\ + use $1;\n\ +\n\ + ${3:# synopsis...}\n\ +\n\ + =head1 DESCRIPTION\n\ +\n\ + ${4:# longer description...}\n\ +\n\ +\n\ + =head1 INTERFACE\n\ +\n\ +\n\ + =head1 DEPENDENCIES\n\ +\n\ +\n\ + =head1 SEE ALSO\n\ +\n\ +\n\ +# Heading for a subroutine stub\n\ +snippet psub\n\ + =head2 ${1:MethodName}\n\ +\n\ + ${2:Summary....}\n\ +\n\ +# Heading for inline subroutine pod\n\ +snippet psubi\n\ + =head2 ${1:MethodName}\n\ +\n\ + ${2:Summary...}\n\ +\n\ +\n\ + =cut\n\ +# inline documented subroutine\n\ +snippet subpod\n\ + =head2 $1\n\ +\n\ + Summary of $1\n\ +\n\ + =cut\n\ +\n\ + sub ${1:subroutine_name} {\n\ + ${2:# body...}\n\ + }\n\ +# Subroutine signature\n\ +snippet parg\n\ + =over 2\n\ +\n\ + =item\n\ + Arguments\n\ +\n\ +\n\ + =over 3\n\ +\n\ + =item\n\ + C<${1:DataStructure}>\n\ +\n\ + ${2:Sample}\n\ +\n\ +\n\ + =back\n\ +\n\ +\n\ + =item\n\ + Return\n\ +\n\ + =over 3\n\ +\n\ +\n\ + =item\n\ + C<${3:...return data}>\n\ +\n\ +\n\ + =back\n\ +\n\ +\n\ + =back\n\ +\n\ +\n\ +\n\ +# Moose has\n\ +snippet has\n\ + has ${1:attribute} => (\n\ + is => '${2:ro|rw}',\n\ + isa => '${3:Str|Int|HashRef|ArrayRef|etc}',\n\ + default => sub {\n\ + ${4:defaultvalue}\n\ + },\n\ + ${5:# other attributes}\n\ + );\n\ +\n\ +\n\ +# override\n\ +snippet override\n\ + override ${1:attribute} => sub {\n\ + ${2:# my $self = shift;};\n\ + ${3:# my ($self, $args) = @_;};\n\ + };\n\ +\n\ +\n\ +# use test classes\n\ +snippet tuse\n\ + use Test::More;\n\ + use Test::Deep; # (); # uncomment to stop prototype errors\n\ + use Test::Exception;\n\ +\n\ +# local test lib\n\ +snippet tlib\n\ + use lib qw{ ./t/lib };\n\ +\n\ +#test methods\n\ +snippet tmeths\n\ + $ENV{TEST_METHOD} = '${1:regex}';\n\ +\n\ +# runtestclass\n\ +snippet trunner\n\ + use ${1:test_class};\n\ + $1->runtests();\n\ +\n\ +# Test::Class-style test\n\ +snippet tsub\n\ + sub t${1:number}_${2:test_case} :Test(${3:num_of_tests}) {\n\ + my $self = shift;\n\ + ${4:# body}\n\ +\n\ + }\n\ +\n\ +# Test::Routine-style test\n\ +snippet trsub\n\ + test ${1:test_name} => { description => '${2:Description of test.}'} => sub {\n\ + my ($self) = @_;\n\ + ${3:# test code}\n\ + };\n\ +\n\ +#prep test method\n\ +snippet tprep\n\ + sub prep${1:number}_${2:test_case} :Test(startup) {\n\ + my $self = shift;\n\ + ${4:# body}\n\ + }\n\ +\n\ +# cause failures to print stack trace\n\ +snippet debug_trace\n\ + use Carp; # 'verbose';\n\ + # cloak \"die\"\n\ + # warn \"warning\"\n\ + $SIG{'__DIE__'} = sub {\n\ + require Carp; Carp::confess\n\ + };\n\ +\n\ +"; +exports.scope = "perl"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/pgsql.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/pgsql.js new file mode 100644 index 00000000..2fea6cc0 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/pgsql.js @@ -0,0 +1,7 @@ +define("ace/snippets/pgsql",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "pgsql"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/php.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/php.js new file mode 100644 index 00000000..a93283f3 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/php.js @@ -0,0 +1,283 @@ +define("ace/snippets/php",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet \n\ +# this one is for php5.4\n\ +snippet \n\ +snippet ns\n\ + namespace ${1:Foo\\Bar\\Baz};\n\ + ${2}\n\ +snippet use\n\ + use ${1:Foo\\Bar\\Baz};\n\ + ${2}\n\ +snippet c\n\ + ${1:abstract }class ${2:$FILENAME}\n\ + {\n\ + ${3}\n\ + }\n\ +snippet i\n\ + interface ${1:$FILENAME}\n\ + {\n\ + ${2}\n\ + }\n\ +snippet t.\n\ + $this->${1}\n\ +snippet f\n\ + function ${1:foo}(${2:array }${3:$bar})\n\ + {\n\ + ${4}\n\ + }\n\ +# method\n\ +snippet m\n\ + ${1:abstract }${2:protected}${3: static} function ${4:foo}(${5:array }${6:$bar})\n\ + {\n\ + ${7}\n\ + }\n\ +# setter method\n\ +snippet sm \n\ + ${5:public} function set${6:$2}(${7:$2 }$$1)\n\ + {\n\ + $this->${8:$1} = $$1;\n\ + return $this;\n\ + }${9}\n\ +# getter method\n\ +snippet gm\n\ + ${3:public} function get${4:$2}()\n\ + {\n\ + return $this->${5:$1};\n\ + }${6}\n\ +#setter\n\ +snippet $s\n\ + ${1:$foo}->set${2:Bar}(${3});\n\ +#getter\n\ +snippet $g\n\ + ${1:$foo}->get${2:Bar}();\n\ +\n\ +# Tertiary conditional\n\ +snippet =?:\n\ + $${1:foo} = ${2:true} ? ${3:a} : ${4};\n\ +snippet ?:\n\ + ${1:true} ? ${2:a} : ${3}\n\ +\n\ +snippet C\n\ + $_COOKIE['${1:variable}']${2}\n\ +snippet E\n\ + $_ENV['${1:variable}']${2}\n\ +snippet F\n\ + $_FILES['${1:variable}']${2}\n\ +snippet G\n\ + $_GET['${1:variable}']${2}\n\ +snippet P\n\ + $_POST['${1:variable}']${2}\n\ +snippet R\n\ + $_REQUEST['${1:variable}']${2}\n\ +snippet S\n\ + $_SERVER['${1:variable}']${2}\n\ +snippet SS\n\ + $_SESSION['${1:variable}']${2}\n\ + \n\ +# the following are old ones\n\ +snippet inc\n\ + include '${1:file}';${2}\n\ +snippet inc1\n\ + include_once '${1:file}';${2}\n\ +snippet req\n\ + require '${1:file}';${2}\n\ +snippet req1\n\ + require_once '${1:file}';${2}\n\ +# Start Docblock\n\ +snippet /*\n\ +# Class - post doc\n\ +snippet doc_cp${5}\n\ +# Class Variable - post doc\n\ +snippet doc_vp${3}\n\ +# Class Variable\n\ +snippet doc_v\n\ + ${1:var} $${2};${5}\n\ +# Class\n\ +snippet doc_c\n\ + ${1:}class ${2:}\n\ + {\n\ + ${7}\n\ + } // END $1class $2\n\ +# Constant Definition - post doc\n\ +snippet doc_dp${2}\n\ +# Constant Definition\n\ +snippet doc_d\n\ + define(${1}, ${2});${4}\n\ +# Function - post doc\n\ +snippet doc_fp${4}\n\ +# Function signature\n\ +snippet doc_s\n\ + ${1}function ${2}(${3});${7}\n\ +# Function\n\ +snippet doc_f\n\ + ${1}function ${2}(${3})\n\ + {${7}\n\ + }\n\ +# Header\n\ +snippet doc_h\n\ + \n\ +# Interface\n\ +snippet interface\n\ + interface ${1:$FILENAME}\n\ + {\n\ + ${5}\n\ + }\n\ +# class ...\n\ +snippet class\n\ + class ${2:$FILENAME}\n\ + {\n\ + ${3}\n\ + ${5:public} function ${6:__construct}(${7:argument})\n\ + {\n\ + ${8:// code...}\n\ + }\n\ + }\n\ +# define(...)\n\ +snippet def\n\ + define('${1}'${2});${3}\n\ +# defined(...)\n\ +snippet def?\n\ + ${1}defined('${2}')${3}\n\ +snippet wh\n\ + while (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + }\n\ +# do ... while\n\ +snippet do\n\ + do {\n\ + ${2:// code... }\n\ + } while (${1:/* condition */});\n\ +snippet if\n\ + if (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + }\n\ +snippet ifil\n\ + \n\ + ${2:}\n\ + \n\ +snippet ife\n\ + if (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + } else {\n\ + ${3:// code...}\n\ + }\n\ + ${4}\n\ +snippet ifeil\n\ + \n\ + ${2:}\n\ + \n\ + ${3:}\n\ + \n\ + ${4}\n\ +snippet else\n\ + else {\n\ + ${1:// code...}\n\ + }\n\ +snippet elseif\n\ + elseif (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + }\n\ +snippet switch\n\ + switch ($${1:variable}) {\n\ + case '${2:value}':\n\ + ${3:// code...}\n\ + break;\n\ + ${5}\n\ + default:\n\ + ${4:// code...}\n\ + break;\n\ + }\n\ +snippet case\n\ + case '${1:value}':\n\ + ${2:// code...}\n\ + break;${3}\n\ +snippet for\n\ + for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) {\n\ + ${4: // code...}\n\ + }\n\ +snippet foreach\n\ + foreach ($${1:variable} as $${2:value}) {\n\ + ${3:// code...}\n\ + }\n\ +snippet foreachil\n\ + \n\ + ${3:}\n\ + \n\ +snippet foreachk\n\ + foreach ($${1:variable} as $${2:key} => $${3:value}) {\n\ + ${4:// code...}\n\ + }\n\ +snippet foreachkil\n\ + $${3:value}): ?>\n\ + ${4:}\n\ + \n\ +# $... = array (...)\n\ +snippet array\n\ + $${1:arrayName} = array('${2}' => ${3});${4}\n\ +snippet try\n\ + try {\n\ + ${2}\n\ + } catch (${1:Exception} $e) {\n\ + }\n\ +# lambda with closure\n\ +snippet lambda\n\ + ${1:static }function (${2:args}) use (${3:&$x, $y /*put vars in scope (closure) */}) {\n\ + ${4}\n\ + };\n\ +# pre_dump();\n\ +snippet pd\n\ + echo '
    '; var_dump(${1}); echo '
    ';\n\ +# pre_dump(); die();\n\ +snippet pdd\n\ + echo '
    '; var_dump(${1}); echo '
    '; die(${2:});\n\ +snippet vd\n\ + var_dump(${1});\n\ +snippet vdd\n\ + var_dump(${1}); die(${2:});\n\ +snippet http_redirect\n\ + header (\"HTTP/1.1 301 Moved Permanently\"); \n\ + header (\"Location: \".URL); \n\ + exit();\n\ +# Getters & Setters\n\ +snippet gs\n\ + public function get${3:$2}()\n\ + {\n\ + return $this->${4:$1};\n\ + }\n\ + public function set$3(${7:$2 }$$1)\n\ + {\n\ + $this->$4 = $$1;\n\ + return $this;\n\ + }${8}\n\ +# anotation, get, and set, useful for doctrine\n\ +snippet ags\n\ + ${2:protected} $${3:foo};\n\ +\n\ + public function get${4:$3}()\n\ + {\n\ + return $this->$3;\n\ + }\n\ +\n\ + public function set$4(${5:$4 }$${6:$3})\n\ + {\n\ + $this->$3 = $$6;\n\ + return $this;\n\ + }\n\ +snippet rett\n\ + return true;\n\ +snippet retf\n\ + return false;\n\ +"; +exports.scope = "php"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/plain_text.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/plain_text.js new file mode 100644 index 00000000..d0309cf3 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/plain_text.js @@ -0,0 +1,7 @@ +define("ace/snippets/plain_text",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "plain_text"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/powershell.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/powershell.js new file mode 100644 index 00000000..b1c2037a --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/powershell.js @@ -0,0 +1,7 @@ +define("ace/snippets/powershell",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "powershell"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/praat.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/praat.js new file mode 100644 index 00000000..d688531b --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/praat.js @@ -0,0 +1,7 @@ +define("ace/snippets/praat",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "praat"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/prolog.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/prolog.js new file mode 100644 index 00000000..3330832b --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/prolog.js @@ -0,0 +1,7 @@ +define("ace/snippets/prolog",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "prolog"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/properties.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/properties.js new file mode 100644 index 00000000..13627095 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/properties.js @@ -0,0 +1,7 @@ +define("ace/snippets/properties",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "properties"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/protobuf.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/protobuf.js new file mode 100644 index 00000000..ca88cb0d --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/protobuf.js @@ -0,0 +1,7 @@ +define("ace/snippets/protobuf",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = ""; +exports.scope = "protobuf"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/python.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/python.js new file mode 100644 index 00000000..8bc443a6 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/python.js @@ -0,0 +1,165 @@ +define("ace/snippets/python",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet #!\n\ + #!/usr/bin/env python\n\ +snippet imp\n\ + import ${1:module}\n\ +snippet from\n\ + from ${1:package} import ${2:module}\n\ +# Module Docstring\n\ +snippet docs\n\ + '''\n\ + File: ${1:FILENAME:file_name}\n\ + Author: ${2:author}\n\ + Description: ${3}\n\ + '''\n\ +snippet wh\n\ + while ${1:condition}:\n\ + ${2:# TODO: write code...}\n\ +# dowh - does the same as do...while in other languages\n\ +snippet dowh\n\ + while True:\n\ + ${1:# TODO: write code...}\n\ + if ${2:condition}:\n\ + break\n\ +snippet with\n\ + with ${1:expr} as ${2:var}:\n\ + ${3:# TODO: write code...}\n\ +# New Class\n\ +snippet cl\n\ + class ${1:ClassName}(${2:object}):\n\ + \"\"\"${3:docstring for $1}\"\"\"\n\ + def __init__(self, ${4:arg}):\n\ + ${5:super($1, self).__init__()}\n\ + self.$4 = $4\n\ + ${6}\n\ +# New Function\n\ +snippet def\n\ + def ${1:fname}(${2:`indent('.') ? 'self' : ''`}):\n\ + \"\"\"${3:docstring for $1}\"\"\"\n\ + ${4:# TODO: write code...}\n\ +snippet deff\n\ + def ${1:fname}(${2:`indent('.') ? 'self' : ''`}):\n\ + ${3:# TODO: write code...}\n\ +# New Method\n\ +snippet defs\n\ + def ${1:mname}(self, ${2:arg}):\n\ + ${3:# TODO: write code...}\n\ +# New Property\n\ +snippet property\n\ + def ${1:foo}():\n\ + doc = \"${2:The $1 property.}\"\n\ + def fget(self):\n\ + ${3:return self._$1}\n\ + def fset(self, value):\n\ + ${4:self._$1 = value}\n\ +# Ifs\n\ +snippet if\n\ + if ${1:condition}:\n\ + ${2:# TODO: write code...}\n\ +snippet el\n\ + else:\n\ + ${1:# TODO: write code...}\n\ +snippet ei\n\ + elif ${1:condition}:\n\ + ${2:# TODO: write code...}\n\ +# For\n\ +snippet for\n\ + for ${1:item} in ${2:items}:\n\ + ${3:# TODO: write code...}\n\ +# Encodes\n\ +snippet cutf8\n\ + # -*- coding: utf-8 -*-\n\ +snippet clatin1\n\ + # -*- coding: latin-1 -*-\n\ +snippet cascii\n\ + # -*- coding: ascii -*-\n\ +# Lambda\n\ +snippet ld\n\ + ${1:var} = lambda ${2:vars} : ${3:action}\n\ +snippet .\n\ + self.\n\ +snippet try Try/Except\n\ + try:\n\ + ${1:# TODO: write code...}\n\ + except ${2:Exception}, ${3:e}:\n\ + ${4:raise $3}\n\ +snippet try Try/Except/Else\n\ + try:\n\ + ${1:# TODO: write code...}\n\ + except ${2:Exception}, ${3:e}:\n\ + ${4:raise $3}\n\ + else:\n\ + ${5:# TODO: write code...}\n\ +snippet try Try/Except/Finally\n\ + try:\n\ + ${1:# TODO: write code...}\n\ + except ${2:Exception}, ${3:e}:\n\ + ${4:raise $3}\n\ + finally:\n\ + ${5:# TODO: write code...}\n\ +snippet try Try/Except/Else/Finally\n\ + try:\n\ + ${1:# TODO: write code...}\n\ + except ${2:Exception}, ${3:e}:\n\ + ${4:raise $3}\n\ + else:\n\ + ${5:# TODO: write code...}\n\ + finally:\n\ + ${6:# TODO: write code...}\n\ +# if __name__ == '__main__':\n\ +snippet ifmain\n\ + if __name__ == '__main__':\n\ + ${1:main()}\n\ +# __magic__\n\ +snippet _\n\ + __${1:init}__${2}\n\ +# python debugger (pdb)\n\ +snippet pdb\n\ + import pdb; pdb.set_trace()\n\ +# ipython debugger (ipdb)\n\ +snippet ipdb\n\ + import ipdb; ipdb.set_trace()\n\ +# ipython debugger (pdbbb)\n\ +snippet pdbbb\n\ + import pdbpp; pdbpp.set_trace()\n\ +snippet pprint\n\ + import pprint; pprint.pprint(${1})${2}\n\ +snippet \"\n\ + \"\"\"\n\ + ${1:doc}\n\ + \"\"\"\n\ +# test function/method\n\ +snippet test\n\ + def test_${1:description}(${2:self}):\n\ + ${3:# TODO: write code...}\n\ +# test case\n\ +snippet testcase\n\ + class ${1:ExampleCase}(unittest.TestCase):\n\ + \n\ + def test_${2:description}(self):\n\ + ${3:# TODO: write code...}\n\ +snippet fut\n\ + from __future__ import ${1}\n\ +#getopt\n\ +snippet getopt\n\ + try:\n\ + # Short option syntax: \"hv:\"\n\ + # Long option syntax: \"help\" or \"verbose=\"\n\ + opts, args = getopt.getopt(sys.argv[1:], \"${1:short_options}\", [${2:long_options}])\n\ + \n\ + except getopt.GetoptError, err:\n\ + # Print debug info\n\ + print str(err)\n\ + ${3:error_action}\n\ +\n\ + for option, argument in opts:\n\ + if option in (\"-h\", \"--help\"):\n\ + ${4}\n\ + elif option in (\"-v\", \"--verbose\"):\n\ + verbose = argument\n\ +"; +exports.scope = "python"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/r.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/r.js new file mode 100644 index 00000000..5ab99ed6 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/r.js @@ -0,0 +1,128 @@ +define("ace/snippets/r",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet #!\n\ + #!/usr/bin/env Rscript\n\ +\n\ +# includes\n\ +snippet lib\n\ + library(${1:package})\n\ +snippet req\n\ + require(${1:package})\n\ +snippet source\n\ + source('${1:file}')\n\ +\n\ +# conditionals\n\ +snippet if\n\ + if (${1:condition}) {\n\ + ${2:code}\n\ + }\n\ +snippet el\n\ + else {\n\ + ${1:code}\n\ + }\n\ +snippet ei\n\ + else if (${1:condition}) {\n\ + ${2:code}\n\ + }\n\ +\n\ +# functions\n\ +snippet fun\n\ + ${1:name} = function (${2:variables}) {\n\ + ${3:code}\n\ + }\n\ +snippet ret\n\ + return(${1:code})\n\ +\n\ +# dataframes, lists, etc\n\ +snippet df\n\ + ${1:name}[${2:rows}, ${3:cols}]\n\ +snippet c\n\ + c(${1:items})\n\ +snippet li\n\ + list(${1:items})\n\ +snippet mat\n\ + matrix(${1:data}, nrow=${2:rows}, ncol=${3:cols})\n\ +\n\ +# apply functions\n\ +snippet apply\n\ + apply(${1:array}, ${2:margin}, ${3:function})\n\ +snippet lapply\n\ + lapply(${1:list}, ${2:function})\n\ +snippet sapply\n\ + lapply(${1:list}, ${2:function})\n\ +snippet vapply\n\ + vapply(${1:list}, ${2:function}, ${3:type})\n\ +snippet mapply\n\ + mapply(${1:function}, ${2:...})\n\ +snippet tapply\n\ + tapply(${1:vector}, ${2:index}, ${3:function})\n\ +snippet rapply\n\ + rapply(${1:list}, ${2:function})\n\ +\n\ +# plyr functions\n\ +snippet dd\n\ + ddply(${1:frame}, ${2:variables}, ${3:function})\n\ +snippet dl\n\ + dlply(${1:frame}, ${2:variables}, ${3:function})\n\ +snippet da\n\ + daply(${1:frame}, ${2:variables}, ${3:function})\n\ +snippet d_\n\ + d_ply(${1:frame}, ${2:variables}, ${3:function})\n\ +\n\ +snippet ad\n\ + adply(${1:array}, ${2:margin}, ${3:function})\n\ +snippet al\n\ + alply(${1:array}, ${2:margin}, ${3:function})\n\ +snippet aa\n\ + aaply(${1:array}, ${2:margin}, ${3:function})\n\ +snippet a_\n\ + a_ply(${1:array}, ${2:margin}, ${3:function})\n\ +\n\ +snippet ld\n\ + ldply(${1:list}, ${2:function})\n\ +snippet ll\n\ + llply(${1:list}, ${2:function})\n\ +snippet la\n\ + laply(${1:list}, ${2:function})\n\ +snippet l_\n\ + l_ply(${1:list}, ${2:function})\n\ +\n\ +snippet md\n\ + mdply(${1:matrix}, ${2:function})\n\ +snippet ml\n\ + mlply(${1:matrix}, ${2:function})\n\ +snippet ma\n\ + maply(${1:matrix}, ${2:function})\n\ +snippet m_\n\ + m_ply(${1:matrix}, ${2:function})\n\ +\n\ +# plot functions\n\ +snippet pl\n\ + plot(${1:x}, ${2:y})\n\ +snippet ggp\n\ + ggplot(${1:data}, aes(${2:aesthetics}))\n\ +snippet img\n\ + ${1:(jpeg,bmp,png,tiff)}(filename=\"${2:filename}\", width=${3}, height=${4}, unit=\"${5}\")\n\ + ${6:plot}\n\ + dev.off()\n\ +\n\ +# statistical test functions\n\ +snippet fis\n\ + fisher.test(${1:x}, ${2:y})\n\ +snippet chi\n\ + chisq.test(${1:x}, ${2:y})\n\ +snippet tt\n\ + t.test(${1:x}, ${2:y})\n\ +snippet wil\n\ + wilcox.test(${1:x}, ${2:y})\n\ +snippet cor\n\ + cor.test(${1:x}, ${2:y})\n\ +snippet fte\n\ + var.test(${1:x}, ${2:y})\n\ +snippet kvt \n\ + kv.test(${1:x}, ${2:y})\n\ +"; +exports.scope = "r"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/rdoc.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/rdoc.js new file mode 100644 index 00000000..ba41d285 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/rdoc.js @@ -0,0 +1,7 @@ +define("ace/snippets/rdoc",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "rdoc"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/rhtml.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/rhtml.js new file mode 100644 index 00000000..3b8e6866 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/rhtml.js @@ -0,0 +1,7 @@ +define("ace/snippets/rhtml",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "rhtml"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ruby.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ruby.js new file mode 100644 index 00000000..d6e21c32 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/ruby.js @@ -0,0 +1,935 @@ +define("ace/snippets/ruby",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "########################################\n\ +# Ruby snippets - for Rails, see below #\n\ +########################################\n\ +\n\ +# encoding for Ruby 1.9\n\ +snippet enc\n\ + # encoding: utf-8\n\ +\n\ +# #!/usr/bin/env ruby\n\ +snippet #!\n\ + #!/usr/bin/env ruby\n\ + # encoding: utf-8\n\ +\n\ +# New Block\n\ +snippet =b\n\ + =begin rdoc\n\ + ${1}\n\ + =end\n\ +snippet y\n\ + :yields: ${1:arguments}\n\ +snippet rb\n\ + #!/usr/bin/env ruby -wKU\n\ +snippet beg\n\ + begin\n\ + ${3}\n\ + rescue ${1:Exception} => ${2:e}\n\ + end\n\ +\n\ +snippet req require\n\ + require \"${1}\"${2}\n\ +snippet #\n\ + # =>\n\ +snippet end\n\ + __END__\n\ +snippet case\n\ + case ${1:object}\n\ + when ${2:condition}\n\ + ${3}\n\ + end\n\ +snippet when\n\ + when ${1:condition}\n\ + ${2}\n\ +snippet def\n\ + def ${1:method_name}\n\ + ${2}\n\ + end\n\ +snippet deft\n\ + def test_${1:case_name}\n\ + ${2}\n\ + end\n\ +snippet if\n\ + if ${1:condition}\n\ + ${2}\n\ + end\n\ +snippet ife\n\ + if ${1:condition}\n\ + ${2}\n\ + else\n\ + ${3}\n\ + end\n\ +snippet elsif\n\ + elsif ${1:condition}\n\ + ${2}\n\ +snippet unless\n\ + unless ${1:condition}\n\ + ${2}\n\ + end\n\ +snippet while\n\ + while ${1:condition}\n\ + ${2}\n\ + end\n\ +snippet for\n\ + for ${1:e} in ${2:c}\n\ + ${3}\n\ + end\n\ +snippet until\n\ + until ${1:condition}\n\ + ${2}\n\ + end\n\ +snippet cla class .. end\n\ + class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`}\n\ + ${2}\n\ + end\n\ +snippet cla class .. initialize .. end\n\ + class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`}\n\ + def initialize(${2:args})\n\ + ${3}\n\ + end\n\ + end\n\ +snippet cla class .. < ParentClass .. initialize .. end\n\ + class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`} < ${2:ParentClass}\n\ + def initialize(${3:args})\n\ + ${4}\n\ + end\n\ + end\n\ +snippet cla ClassName = Struct .. do .. end\n\ + ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`} = Struct.new(:${2:attr_names}) do\n\ + def ${3:method_name}\n\ + ${4}\n\ + end\n\ + end\n\ +snippet cla class BlankSlate .. initialize .. end\n\ + class ${1:BlankSlate}\n\ + instance_methods.each { |meth| undef_method(meth) unless meth =~ /\\A__/ }\n\ + end\n\ +snippet cla class << self .. end\n\ + class << ${1:self}\n\ + ${2}\n\ + end\n\ +# class .. < DelegateClass .. initialize .. end\n\ +snippet cla-\n\ + class ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`} < DelegateClass(${2:ParentClass})\n\ + def initialize(${3:args})\n\ + super(${4:del_obj})\n\ +\n\ + ${5}\n\ + end\n\ + end\n\ +snippet mod module .. end\n\ + module ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`}\n\ + ${2}\n\ + end\n\ +snippet mod module .. module_function .. end\n\ + module ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`}\n\ + module_function\n\ +\n\ + ${2}\n\ + end\n\ +snippet mod module .. ClassMethods .. end\n\ + module ${1:`substitute(Filename(), '\\(_\\|^\\)\\(.\\)', '\\u\\2', 'g')`}\n\ + module ClassMethods\n\ + ${2}\n\ + end\n\ +\n\ + module InstanceMethods\n\ +\n\ + end\n\ +\n\ + def self.included(receiver)\n\ + receiver.extend ClassMethods\n\ + receiver.send :include, InstanceMethods\n\ + end\n\ + end\n\ +# attr_reader\n\ +snippet r\n\ + attr_reader :${1:attr_names}\n\ +# attr_writer\n\ +snippet w\n\ + attr_writer :${1:attr_names}\n\ +# attr_accessor\n\ +snippet rw\n\ + attr_accessor :${1:attr_names}\n\ +snippet atp\n\ + attr_protected :${1:attr_names}\n\ +snippet ata\n\ + attr_accessible :${1:attr_names}\n\ +# include Enumerable\n\ +snippet Enum\n\ + include Enumerable\n\ +\n\ + def each(&block)\n\ + ${1}\n\ + end\n\ +# include Comparable\n\ +snippet Comp\n\ + include Comparable\n\ +\n\ + def <=>(other)\n\ + ${1}\n\ + end\n\ +# extend Forwardable\n\ +snippet Forw-\n\ + extend Forwardable\n\ +# def self\n\ +snippet defs\n\ + def self.${1:class_method_name}\n\ + ${2}\n\ + end\n\ +# def method_missing\n\ +snippet defmm\n\ + def method_missing(meth, *args, &blk)\n\ + ${1}\n\ + end\n\ +snippet defd\n\ + def_delegator :${1:@del_obj}, :${2:del_meth}, :${3:new_name}\n\ +snippet defds\n\ + def_delegators :${1:@del_obj}, :${2:del_methods}\n\ +snippet am\n\ + alias_method :${1:new_name}, :${2:old_name}\n\ +snippet app\n\ + if __FILE__ == $PROGRAM_NAME\n\ + ${1}\n\ + end\n\ +# usage_if()\n\ +snippet usai\n\ + if ARGV.${1}\n\ + abort \"Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}\"${3}\n\ + end\n\ +# usage_unless()\n\ +snippet usau\n\ + unless ARGV.${1}\n\ + abort \"Usage: #{$PROGRAM_NAME} ${2:ARGS_GO_HERE}\"${3}\n\ + end\n\ +snippet array\n\ + Array.new(${1:10}) { |${2:i}| ${3} }\n\ +snippet hash\n\ + Hash.new { |${1:hash}, ${2:key}| $1[$2] = ${3} }\n\ +snippet file File.foreach() { |line| .. }\n\ + File.foreach(${1:\"path/to/file\"}) { |${2:line}| ${3} }\n\ +snippet file File.read()\n\ + File.read(${1:\"path/to/file\"})${2}\n\ +snippet Dir Dir.global() { |file| .. }\n\ + Dir.glob(${1:\"dir/glob/*\"}) { |${2:file}| ${3} }\n\ +snippet Dir Dir[\"..\"]\n\ + Dir[${1:\"glob/**/*.rb\"}]${2}\n\ +snippet dir\n\ + Filename.dirname(__FILE__)\n\ +snippet deli\n\ + delete_if { |${1:e}| ${2} }\n\ +snippet fil\n\ + fill(${1:range}) { |${2:i}| ${3} }\n\ +# flatten_once()\n\ +snippet flao\n\ + inject(Array.new) { |${1:arr}, ${2:a}| $1.push(*$2)}${3}\n\ +snippet zip\n\ + zip(${1:enums}) { |${2:row}| ${3} }\n\ +# downto(0) { |n| .. }\n\ +snippet dow\n\ + downto(${1:0}) { |${2:n}| ${3} }\n\ +snippet ste\n\ + step(${1:2}) { |${2:n}| ${3} }\n\ +snippet tim\n\ + times { |${1:n}| ${2} }\n\ +snippet upt\n\ + upto(${1:1.0/0.0}) { |${2:n}| ${3} }\n\ +snippet loo\n\ + loop { ${1} }\n\ +snippet ea\n\ + each { |${1:e}| ${2} }\n\ +snippet ead\n\ + each do |${1:e}|\n\ + ${2}\n\ + end\n\ +snippet eab\n\ + each_byte { |${1:byte}| ${2} }\n\ +snippet eac- each_char { |chr| .. }\n\ + each_char { |${1:chr}| ${2} }\n\ +snippet eac- each_cons(..) { |group| .. }\n\ + each_cons(${1:2}) { |${2:group}| ${3} }\n\ +snippet eai\n\ + each_index { |${1:i}| ${2} }\n\ +snippet eaid\n\ + each_index do |${1:i}|\n\ + ${2}\n\ + end\n\ +snippet eak\n\ + each_key { |${1:key}| ${2} }\n\ +snippet eakd\n\ + each_key do |${1:key}|\n\ + ${2}\n\ + end\n\ +snippet eal\n\ + each_line { |${1:line}| ${2} }\n\ +snippet eald\n\ + each_line do |${1:line}|\n\ + ${2}\n\ + end\n\ +snippet eap\n\ + each_pair { |${1:name}, ${2:val}| ${3} }\n\ +snippet eapd\n\ + each_pair do |${1:name}, ${2:val}|\n\ + ${3}\n\ + end\n\ +snippet eas-\n\ + each_slice(${1:2}) { |${2:group}| ${3} }\n\ +snippet easd-\n\ + each_slice(${1:2}) do |${2:group}|\n\ + ${3}\n\ + end\n\ +snippet eav\n\ + each_value { |${1:val}| ${2} }\n\ +snippet eavd\n\ + each_value do |${1:val}|\n\ + ${2}\n\ + end\n\ +snippet eawi\n\ + each_with_index { |${1:e}, ${2:i}| ${3} }\n\ +snippet eawid\n\ + each_with_index do |${1:e},${2:i}|\n\ + ${3}\n\ + end\n\ +snippet reve\n\ + reverse_each { |${1:e}| ${2} }\n\ +snippet reved\n\ + reverse_each do |${1:e}|\n\ + ${2}\n\ + end\n\ +snippet inj\n\ + inject(${1:init}) { |${2:mem}, ${3:var}| ${4} }\n\ +snippet injd\n\ + inject(${1:init}) do |${2:mem}, ${3:var}|\n\ + ${4}\n\ + end\n\ +snippet map\n\ + map { |${1:e}| ${2} }\n\ +snippet mapd\n\ + map do |${1:e}|\n\ + ${2}\n\ + end\n\ +snippet mapwi-\n\ + enum_with_index.map { |${1:e}, ${2:i}| ${3} }\n\ +snippet sor\n\ + sort { |a, b| ${1} }\n\ +snippet sorb\n\ + sort_by { |${1:e}| ${2} }\n\ +snippet ran\n\ + sort_by { rand }\n\ +snippet all\n\ + all? { |${1:e}| ${2} }\n\ +snippet any\n\ + any? { |${1:e}| ${2} }\n\ +snippet cl\n\ + classify { |${1:e}| ${2} }\n\ +snippet col\n\ + collect { |${1:e}| ${2} }\n\ +snippet cold\n\ + collect do |${1:e}|\n\ + ${2}\n\ + end\n\ +snippet det\n\ + detect { |${1:e}| ${2} }\n\ +snippet detd\n\ + detect do |${1:e}|\n\ + ${2}\n\ + end\n\ +snippet fet\n\ + fetch(${1:name}) { |${2:key}| ${3} }\n\ +snippet fin\n\ + find { |${1:e}| ${2} }\n\ +snippet find\n\ + find do |${1:e}|\n\ + ${2}\n\ + end\n\ +snippet fina\n\ + find_all { |${1:e}| ${2} }\n\ +snippet finad\n\ + find_all do |${1:e}|\n\ + ${2}\n\ + end\n\ +snippet gre\n\ + grep(${1:/pattern/}) { |${2:match}| ${3} }\n\ +snippet sub\n\ + ${1:g}sub(${2:/pattern/}) { |${3:match}| ${4} }\n\ +snippet sca\n\ + scan(${1:/pattern/}) { |${2:match}| ${3} }\n\ +snippet scad\n\ + scan(${1:/pattern/}) do |${2:match}|\n\ + ${3}\n\ + end\n\ +snippet max\n\ + max { |a, b| ${1} }\n\ +snippet min\n\ + min { |a, b| ${1} }\n\ +snippet par\n\ + partition { |${1:e}| ${2} }\n\ +snippet pard\n\ + partition do |${1:e}|\n\ + ${2}\n\ + end\n\ +snippet rej\n\ + reject { |${1:e}| ${2} }\n\ +snippet rejd\n\ + reject do |${1:e}|\n\ + ${2}\n\ + end\n\ +snippet sel\n\ + select { |${1:e}| ${2} }\n\ +snippet seld\n\ + select do |${1:e}|\n\ + ${2}\n\ + end\n\ +snippet lam\n\ + lambda { |${1:args}| ${2} }\n\ +snippet doo\n\ + do\n\ + ${1}\n\ + end\n\ +snippet dov\n\ + do |${1:variable}|\n\ + ${2}\n\ + end\n\ +snippet :\n\ + :${1:key} => ${2:\"value\"}${3}\n\ +snippet ope\n\ + open(${1:\"path/or/url/or/pipe\"}, \"${2:w}\") { |${3:io}| ${4} }\n\ +# path_from_here()\n\ +snippet fpath\n\ + File.join(File.dirname(__FILE__), *%2[${1:rel path here}])${2}\n\ +# unix_filter {}\n\ +snippet unif\n\ + ARGF.each_line${1} do |${2:line}|\n\ + ${3}\n\ + end\n\ +# option_parse {}\n\ +snippet optp\n\ + require \"optparse\"\n\ +\n\ + options = {${1:default => \"args\"}}\n\ +\n\ + ARGV.options do |opts|\n\ + opts.banner = \"Usage: #{File.basename($PROGRAM_NAME)}\n\ +snippet opt\n\ + opts.on( \"-${1:o}\", \"--${2:long-option-name}\", ${3:String},\n\ + \"${4:Option description.}\") do |${5:opt}|\n\ + ${6}\n\ + end\n\ +snippet tc\n\ + require \"test/unit\"\n\ +\n\ + require \"${1:library_file_name}\"\n\ +\n\ + class Test${2:$1} < Test::Unit::TestCase\n\ + def test_${3:case_name}\n\ + ${4}\n\ + end\n\ + end\n\ +snippet ts\n\ + require \"test/unit\"\n\ +\n\ + require \"tc_${1:test_case_file}\"\n\ + require \"tc_${2:test_case_file}\"${3}\n\ +snippet as\n\ + assert ${1:test}, \"${2:Failure message.}\"${3}\n\ +snippet ase\n\ + assert_equal ${1:expected}, ${2:actual}${3}\n\ +snippet asne\n\ + assert_not_equal ${1:unexpected}, ${2:actual}${3}\n\ +snippet asid\n\ + assert_in_delta ${1:expected_float}, ${2:actual_float}, ${3:2 ** -20}${4}\n\ +snippet asio\n\ + assert_instance_of ${1:ExpectedClass}, ${2:actual_instance}${3}\n\ +snippet asko\n\ + assert_kind_of ${1:ExpectedKind}, ${2:actual_instance}${3}\n\ +snippet asn\n\ + assert_nil ${1:instance}${2}\n\ +snippet asnn\n\ + assert_not_nil ${1:instance}${2}\n\ +snippet asm\n\ + assert_match /${1:expected_pattern}/, ${2:actual_string}${3}\n\ +snippet asnm\n\ + assert_no_match /${1:unexpected_pattern}/, ${2:actual_string}${3}\n\ +snippet aso\n\ + assert_operator ${1:left}, :${2:operator}, ${3:right}${4}\n\ +snippet asr\n\ + assert_raise ${1:Exception} { ${2} }\n\ +snippet asrd\n\ + assert_raise ${1:Exception} do\n\ + ${2}\n\ + end\n\ +snippet asnr\n\ + assert_nothing_raised ${1:Exception} { ${2} }\n\ +snippet asnrd\n\ + assert_nothing_raised ${1:Exception} do\n\ + ${2}\n\ + end\n\ +snippet asrt\n\ + assert_respond_to ${1:object}, :${2:method}${3}\n\ +snippet ass assert_same(..)\n\ + assert_same ${1:expected}, ${2:actual}${3}\n\ +snippet ass assert_send(..)\n\ + assert_send [${1:object}, :${2:message}, ${3:args}]${4}\n\ +snippet asns\n\ + assert_not_same ${1:unexpected}, ${2:actual}${3}\n\ +snippet ast\n\ + assert_throws :${1:expected} { ${2} }\n\ +snippet astd\n\ + assert_throws :${1:expected} do\n\ + ${2}\n\ + end\n\ +snippet asnt\n\ + assert_nothing_thrown { ${1} }\n\ +snippet asntd\n\ + assert_nothing_thrown do\n\ + ${1}\n\ + end\n\ +snippet fl\n\ + flunk \"${1:Failure message.}\"${2}\n\ +# Benchmark.bmbm do .. end\n\ +snippet bm-\n\ + TESTS = ${1:10_000}\n\ + Benchmark.bmbm do |results|\n\ + ${2}\n\ + end\n\ +snippet rep\n\ + results.report(\"${1:name}:\") { TESTS.times { ${2} }}\n\ +# Marshal.dump(.., file)\n\ +snippet Md\n\ + File.open(${1:\"path/to/file.dump\"}, \"wb\") { |${2:file}| Marshal.dump(${3:obj}, $2) }${4}\n\ +# Mashal.load(obj)\n\ +snippet Ml\n\ + File.open(${1:\"path/to/file.dump\"}, \"rb\") { |${2:file}| Marshal.load($2) }${3}\n\ +# deep_copy(..)\n\ +snippet deec\n\ + Marshal.load(Marshal.dump(${1:obj_to_copy}))${2}\n\ +snippet Pn-\n\ + PStore.new(${1:\"file_name.pstore\"})${2}\n\ +snippet tra\n\ + transaction(${1:true}) { ${2} }\n\ +# xmlread(..)\n\ +snippet xml-\n\ + REXML::Document.new(File.read(${1:\"path/to/file\"}))${2}\n\ +# xpath(..) { .. }\n\ +snippet xpa\n\ + elements.each(${1:\"//Xpath\"}) do |${2:node}|\n\ + ${3}\n\ + end\n\ +# class_from_name()\n\ +snippet clafn\n\ + split(\"::\").inject(Object) { |par, const| par.const_get(const) }\n\ +# singleton_class()\n\ +snippet sinc\n\ + class << self; self end\n\ +snippet nam\n\ + namespace :${1:`Filename()`} do\n\ + ${2}\n\ + end\n\ +snippet tas\n\ + desc \"${1:Task description}\"\n\ + task :${2:task_name => [:dependent, :tasks]} do\n\ + ${3}\n\ + end\n\ +# block\n\ +snippet b\n\ + { |${1:var}| ${2} }\n\ +snippet begin\n\ + begin\n\ + raise 'A test exception.'\n\ + rescue Exception => e\n\ + puts e.message\n\ + puts e.backtrace.inspect\n\ + else\n\ + # other exception\n\ + ensure\n\ + # always executed\n\ + end\n\ +\n\ +#debugging\n\ +snippet debug\n\ + require 'ruby-debug'; debugger; true;\n\ +snippet pry\n\ + require 'pry'; binding.pry\n\ +\n\ +#############################################\n\ +# Rails snippets - for pure Ruby, see above #\n\ +#############################################\n\ +snippet art\n\ + assert_redirected_to ${1::action => \"${2:index}\"}\n\ +snippet artnp\n\ + assert_redirected_to ${1:parent}_${2:child}_path(${3:@$1}, ${4:@$2})\n\ +snippet artnpp\n\ + assert_redirected_to ${1:parent}_${2:child}_path(${3:@$1})\n\ +snippet artp\n\ + assert_redirected_to ${1:model}_path(${2:@$1})\n\ +snippet artpp\n\ + assert_redirected_to ${1:model}s_path\n\ +snippet asd\n\ + assert_difference \"${1:Model}.${2:count}\", $1 do\n\ + ${3}\n\ + end\n\ +snippet asnd\n\ + assert_no_difference \"${1:Model}.${2:count}\" do\n\ + ${3}\n\ + end\n\ +snippet asre\n\ + assert_response :${1:success}, @response.body${2}\n\ +snippet asrj\n\ + assert_rjs :${1:replace}, \"${2:dom id}\"\n\ +snippet ass assert_select(..)\n\ + assert_select '${1:path}', :${2:text} => '${3:inner_html' ${4:do}\n\ +snippet bf\n\ + before_filter :${1:method}\n\ +snippet bt\n\ + belongs_to :${1:association}\n\ +snippet crw\n\ + cattr_accessor :${1:attr_names}\n\ +snippet defcreate\n\ + def create\n\ + @${1:model_class_name} = ${2:ModelClassName}.new(params[:$1])\n\ +\n\ + respond_to do |wants|\n\ + if @$1.save\n\ + flash[:notice] = '$2 was successfully created.'\n\ + wants.html { redirect_to(@$1) }\n\ + wants.xml { render :xml => @$1, :status => :created, :location => @$1 }\n\ + else\n\ + wants.html { render :action => \"new\" }\n\ + wants.xml { render :xml => @$1.errors, :status => :unprocessable_entity }\n\ + end\n\ + end\n\ + end${3}\n\ +snippet defdestroy\n\ + def destroy\n\ + @${1:model_class_name} = ${2:ModelClassName}.find(params[:id])\n\ + @$1.destroy\n\ +\n\ + respond_to do |wants|\n\ + wants.html { redirect_to($1s_url) }\n\ + wants.xml { head :ok }\n\ + end\n\ + end${3}\n\ +snippet defedit\n\ + def edit\n\ + @${1:model_class_name} = ${2:ModelClassName}.find(params[:id])\n\ + end\n\ +snippet defindex\n\ + def index\n\ + @${1:model_class_name} = ${2:ModelClassName}.all\n\ +\n\ + respond_to do |wants|\n\ + wants.html # index.html.erb\n\ + wants.xml { render :xml => @$1s }\n\ + end\n\ + end${3}\n\ +snippet defnew\n\ + def new\n\ + @${1:model_class_name} = ${2:ModelClassName}.new\n\ +\n\ + respond_to do |wants|\n\ + wants.html # new.html.erb\n\ + wants.xml { render :xml => @$1 }\n\ + end\n\ + end${3}\n\ +snippet defshow\n\ + def show\n\ + @${1:model_class_name} = ${2:ModelClassName}.find(params[:id])\n\ +\n\ + respond_to do |wants|\n\ + wants.html # show.html.erb\n\ + wants.xml { render :xml => @$1 }\n\ + end\n\ + end${3}\n\ +snippet defupdate\n\ + def update\n\ + @${1:model_class_name} = ${2:ModelClassName}.find(params[:id])\n\ +\n\ + respond_to do |wants|\n\ + if @$1.update_attributes(params[:$1])\n\ + flash[:notice] = '$2 was successfully updated.'\n\ + wants.html { redirect_to(@$1) }\n\ + wants.xml { head :ok }\n\ + else\n\ + wants.html { render :action => \"edit\" }\n\ + wants.xml { render :xml => @$1.errors, :status => :unprocessable_entity }\n\ + end\n\ + end\n\ + end${3}\n\ +snippet flash\n\ + flash[:${1:notice}] = \"${2}\"\n\ +snippet habtm\n\ + has_and_belongs_to_many :${1:object}, :join_table => \"${2:table_name}\", :foreign_key => \"${3}_id\"${4}\n\ +snippet hm\n\ + has_many :${1:object}\n\ +snippet hmd\n\ + has_many :${1:other}s, :class_name => \"${2:$1}\", :foreign_key => \"${3:$1}_id\", :dependent => :destroy${4}\n\ +snippet hmt\n\ + has_many :${1:object}, :through => :${2:object}\n\ +snippet ho\n\ + has_one :${1:object}\n\ +snippet i18\n\ + I18n.t('${1:type.key}')${2}\n\ +snippet ist\n\ + <%= image_submit_tag(\"${1:agree.png}\", :id => \"${2:id}\"${3} %>\n\ +snippet log\n\ + Rails.logger.${1:debug} ${2}\n\ +snippet log2\n\ + RAILS_DEFAULT_LOGGER.${1:debug} ${2}\n\ +snippet logd\n\ + logger.debug { \"${1:message}\" }${2}\n\ +snippet loge\n\ + logger.error { \"${1:message}\" }${2}\n\ +snippet logf\n\ + logger.fatal { \"${1:message}\" }${2}\n\ +snippet logi\n\ + logger.info { \"${1:message}\" }${2}\n\ +snippet logw\n\ + logger.warn { \"${1:message}\" }${2}\n\ +snippet mapc\n\ + ${1:map}.${2:connect} '${3:controller/:action/:id}'\n\ +snippet mapca\n\ + ${1:map}.catch_all \"*${2:anything}\", :controller => \"${3:default}\", :action => \"${4:error}\"${5}\n\ +snippet mapr\n\ + ${1:map}.resource :${2:resource}\n\ +snippet maprs\n\ + ${1:map}.resources :${2:resource}\n\ +snippet mapwo\n\ + ${1:map}.with_options :${2:controller} => '${3:thing}' do |$3|\n\ + ${4}\n\ + end\n\ +snippet mbs\n\ + before_save :${1:method}\n\ +snippet mcht\n\ + change_table :${1:table_name} do |t|\n\ + ${2}\n\ + end\n\ +snippet mp\n\ + map(&:${1:id})\n\ +snippet mrw\n\ + mattr_accessor :${1:attr_names}\n\ +snippet oa\n\ + order(\"${1:field}\")\n\ +snippet od\n\ + order(\"${1:field} DESC\")\n\ +snippet pa\n\ + params[:${1:id}]${2}\n\ +snippet ra\n\ + render :action => \"${1:action}\"\n\ +snippet ral\n\ + render :action => \"${1:action}\", :layout => \"${2:layoutname}\"\n\ +snippet rest\n\ + respond_to do |wants|\n\ + wants.${1:html} { ${2} }\n\ + end\n\ +snippet rf\n\ + render :file => \"${1:filepath}\"\n\ +snippet rfu\n\ + render :file => \"${1:filepath}\", :use_full_path => ${2:false}\n\ +snippet ri\n\ + render :inline => \"${1:<%= 'hello' %>}\"\n\ +snippet ril\n\ + render :inline => \"${1:<%= 'hello' %>}\", :locals => { ${2::name} => \"${3:value}\"${4} }\n\ +snippet rit\n\ + render :inline => \"${1:<%= 'hello' %>}\", :type => ${2::rxml}\n\ +snippet rjson\n\ + render :json => ${1:text to render}\n\ +snippet rl\n\ + render :layout => \"${1:layoutname}\"\n\ +snippet rn\n\ + render :nothing => ${1:true}\n\ +snippet rns\n\ + render :nothing => ${1:true}, :status => ${2:401}\n\ +snippet rp\n\ + render :partial => \"${1:item}\"\n\ +snippet rpc\n\ + render :partial => \"${1:item}\", :collection => ${2:@$1s}\n\ +snippet rpl\n\ + render :partial => \"${1:item}\", :locals => { :${2:$1} => ${3:@$1}\n\ +snippet rpo\n\ + render :partial => \"${1:item}\", :object => ${2:@$1}\n\ +snippet rps\n\ + render :partial => \"${1:item}\", :status => ${2:500}\n\ +snippet rt\n\ + render :text => \"${1:text to render}\"\n\ +snippet rtl\n\ + render :text => \"${1:text to render}\", :layout => \"${2:layoutname}\"\n\ +snippet rtlt\n\ + render :text => \"${1:text to render}\", :layout => ${2:true}\n\ +snippet rts\n\ + render :text => \"${1:text to render}\", :status => ${2:401}\n\ +snippet ru\n\ + render :update do |${1:page}|\n\ + $1.${2}\n\ + end\n\ +snippet rxml\n\ + render :xml => ${1:text to render}\n\ +snippet sc\n\ + scope :${1:name}, :where(:@${2:field} => ${3:value})\n\ +snippet sl\n\ + scope :${1:name}, lambda do |${2:value}|\n\ + where(\"${3:field = ?}\", ${4:bind var})\n\ + end\n\ +snippet sha1\n\ + Digest::SHA1.hexdigest(${1:string})\n\ +snippet sweeper\n\ + class ${1:ModelClassName}Sweeper < ActionController::Caching::Sweeper\n\ + observe $1\n\ +\n\ + def after_save(${2:model_class_name})\n\ + expire_cache($2)\n\ + end\n\ +\n\ + def after_destroy($2)\n\ + expire_cache($2)\n\ + end\n\ +\n\ + def expire_cache($2)\n\ + expire_page\n\ + end\n\ + end\n\ +snippet tcb\n\ + t.boolean :${1:title}\n\ + ${2}\n\ +snippet tcbi\n\ + t.binary :${1:title}, :limit => ${2:2}.megabytes\n\ + ${3}\n\ +snippet tcd\n\ + t.decimal :${1:title}, :precision => ${2:10}, :scale => ${3:2}\n\ + ${4}\n\ +snippet tcda\n\ + t.date :${1:title}\n\ + ${2}\n\ +snippet tcdt\n\ + t.datetime :${1:title}\n\ + ${2}\n\ +snippet tcf\n\ + t.float :${1:title}\n\ + ${2}\n\ +snippet tch\n\ + t.change :${1:name}, :${2:string}, :${3:limit} => ${4:80}\n\ + ${5}\n\ +snippet tci\n\ + t.integer :${1:title}\n\ + ${2}\n\ +snippet tcl\n\ + t.integer :lock_version, :null => false, :default => 0\n\ + ${1}\n\ +snippet tcr\n\ + t.references :${1:taggable}, :polymorphic => { :default => '${2:Photo}' }\n\ + ${3}\n\ +snippet tcs\n\ + t.string :${1:title}\n\ + ${2}\n\ +snippet tct\n\ + t.text :${1:title}\n\ + ${2}\n\ +snippet tcti\n\ + t.time :${1:title}\n\ + ${2}\n\ +snippet tcts\n\ + t.timestamp :${1:title}\n\ + ${2}\n\ +snippet tctss\n\ + t.timestamps\n\ + ${1}\n\ +snippet va\n\ + validates_associated :${1:attribute}\n\ +snippet vao\n\ + validates_acceptance_of :${1:terms}\n\ +snippet vc\n\ + validates_confirmation_of :${1:attribute}\n\ +snippet ve\n\ + validates_exclusion_of :${1:attribute}, :in => ${2:%w( mov avi )}\n\ +snippet vf\n\ + validates_format_of :${1:attribute}, :with => /${2:regex}/\n\ +snippet vi\n\ + validates_inclusion_of :${1:attribute}, :in => %w(${2: mov avi })\n\ +snippet vl\n\ + validates_length_of :${1:attribute}, :within => ${2:3}..${3:20}\n\ +snippet vn\n\ + validates_numericality_of :${1:attribute}\n\ +snippet vpo\n\ + validates_presence_of :${1:attribute}\n\ +snippet vu\n\ + validates_uniqueness_of :${1:attribute}\n\ +snippet wants\n\ + wants.${1:js|xml|html} { ${2} }\n\ +snippet wc\n\ + where(${1:\"conditions\"}${2:, bind_var})\n\ +snippet wh\n\ + where(${1:field} => ${2:value})\n\ +snippet xdelete\n\ + xhr :delete, :${1:destroy}, :id => ${2:1}${3}\n\ +snippet xget\n\ + xhr :get, :${1:show}, :id => ${2:1}${3}\n\ +snippet xpost\n\ + xhr :post, :${1:create}, :${2:object} => { ${3} }\n\ +snippet xput\n\ + xhr :put, :${1:update}, :id => ${2:1}, :${3:object} => { ${4} }${5}\n\ +snippet test\n\ + test \"should ${1:do something}\" do\n\ + ${2}\n\ + end\n\ +#migrations\n\ +snippet mac\n\ + add_column :${1:table_name}, :${2:column_name}, :${3:data_type}\n\ +snippet mrc\n\ + remove_column :${1:table_name}, :${2:column_name}\n\ +snippet mrnc\n\ + rename_column :${1:table_name}, :${2:old_column_name}, :${3:new_column_name}\n\ +snippet mcc\n\ + change_column :${1:table}, :${2:column}, :${3:type}\n\ +snippet mccc\n\ + t.column :${1:title}, :${2:string}\n\ +snippet mct\n\ + create_table :${1:table_name} do |t|\n\ + t.column :${2:name}, :${3:type}\n\ + end\n\ +snippet migration\n\ + class ${1:class_name} < ActiveRecord::Migration\n\ + def self.up\n\ + ${2}\n\ + end\n\ +\n\ + def self.down\n\ + end\n\ + end\n\ +\n\ +snippet trc\n\ + t.remove :${1:column}\n\ +snippet tre\n\ + t.rename :${1:old_column_name}, :${2:new_column_name}\n\ + ${3}\n\ +snippet tref\n\ + t.references :${1:model}\n\ +\n\ +#rspec\n\ +snippet it\n\ + it \"${1:spec_name}\" do\n\ + ${2}\n\ + end\n\ +snippet itp\n\ + it \"${1:spec_name}\"\n\ + ${2}\n\ +snippet desc\n\ + describe ${1:class_name} do\n\ + ${2}\n\ + end\n\ +snippet cont\n\ + context \"${1:message}\" do\n\ + ${2}\n\ + end\n\ +snippet bef\n\ + before :${1:each} do\n\ + ${2}\n\ + end\n\ +snippet aft\n\ + after :${1:each} do\n\ + ${2}\n\ + end\n\ +"; +exports.scope = "ruby"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/rust.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/rust.js new file mode 100644 index 00000000..4d14a2d3 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/rust.js @@ -0,0 +1,7 @@ +define("ace/snippets/rust",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "rust"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sass.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sass.js new file mode 100644 index 00000000..336c9b93 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sass.js @@ -0,0 +1,7 @@ +define("ace/snippets/sass",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "sass"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scad.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scad.js new file mode 100644 index 00000000..40449e8c --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scad.js @@ -0,0 +1,7 @@ +define("ace/snippets/scad",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "scad"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scala.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scala.js new file mode 100644 index 00000000..99c40576 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scala.js @@ -0,0 +1,7 @@ +define("ace/snippets/scala",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "scala"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scheme.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scheme.js new file mode 100644 index 00000000..6d3dab8f --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scheme.js @@ -0,0 +1,7 @@ +define("ace/snippets/scheme",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "scheme"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scss.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scss.js new file mode 100644 index 00000000..3dc9a063 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/scss.js @@ -0,0 +1,7 @@ +define("ace/snippets/scss",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "scss"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sh.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sh.js new file mode 100644 index 00000000..db7e2567 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sh.js @@ -0,0 +1,90 @@ +define("ace/snippets/sh",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# Shebang. Executing bash via /usr/bin/env makes scripts more portable.\n\ +snippet #!\n\ + #!/usr/bin/env bash\n\ + \n\ +snippet if\n\ + if [[ ${1:condition} ]]; then\n\ + ${2:#statements}\n\ + fi\n\ +snippet elif\n\ + elif [[ ${1:condition} ]]; then\n\ + ${2:#statements}\n\ +snippet for\n\ + for (( ${2:i} = 0; $2 < ${1:count}; $2++ )); do\n\ + ${3:#statements}\n\ + done\n\ +snippet fori\n\ + for ${1:needle} in ${2:haystack} ; do\n\ + ${3:#statements}\n\ + done\n\ +snippet wh\n\ + while [[ ${1:condition} ]]; do\n\ + ${2:#statements}\n\ + done\n\ +snippet until\n\ + until [[ ${1:condition} ]]; do\n\ + ${2:#statements}\n\ + done\n\ +snippet case\n\ + case ${1:word} in\n\ + ${2:pattern})\n\ + ${3};;\n\ + esac\n\ +snippet go \n\ + while getopts '${1:o}' ${2:opts} \n\ + do \n\ + case $$2 in\n\ + ${3:o0})\n\ + ${4:#staments};;\n\ + esac\n\ + done\n\ +# Set SCRIPT_DIR variable to directory script is located.\n\ +snippet sdir\n\ + SCRIPT_DIR=\"$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\"\n\ +# getopt\n\ +snippet getopt\n\ + __ScriptVersion=\"${1:version}\"\n\ +\n\ + #=== FUNCTION ================================================================\n\ + # NAME: usage\n\ + # DESCRIPTION: Display usage information.\n\ + #===============================================================================\n\ + function usage ()\n\ + {\n\ + cat <<- EOT\n\ +\n\ + Usage : $${0:0} [options] [--] \n\ +\n\ + Options: \n\ + -h|help Display this message\n\ + -v|version Display script version\n\ +\n\ + EOT\n\ + } # ---------- end of function usage ----------\n\ +\n\ + #-----------------------------------------------------------------------\n\ + # Handle command line arguments\n\ + #-----------------------------------------------------------------------\n\ +\n\ + while getopts \":hv\" opt\n\ + do\n\ + case $opt in\n\ +\n\ + h|help ) usage; exit 0 ;;\n\ +\n\ + v|version ) echo \"$${0:0} -- Version $__ScriptVersion\"; exit 0 ;;\n\ +\n\ + \\? ) echo -e \"\\n Option does not exist : $OPTARG\\n\"\n\ + usage; exit 1 ;;\n\ +\n\ + esac # --- end of case ---\n\ + done\n\ + shift $(($OPTIND-1))\n\ +\n\ +"; +exports.scope = "sh"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sjs.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sjs.js new file mode 100644 index 00000000..e81ff84d --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sjs.js @@ -0,0 +1,7 @@ +define("ace/snippets/sjs",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "sjs"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/smarty.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/smarty.js new file mode 100644 index 00000000..9f43a82b --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/smarty.js @@ -0,0 +1,7 @@ +define("ace/snippets/smarty",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "smarty"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/snippets.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/snippets.js new file mode 100644 index 00000000..2d5917e8 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/snippets.js @@ -0,0 +1,16 @@ +define("ace/snippets/snippets",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# snippets for making snippets :)\n\ +snippet snip\n\ + snippet ${1:trigger}\n\ + ${2}\n\ +snippet msnip\n\ + snippet ${1:trigger} ${2:description}\n\ + ${3}\n\ +snippet v\n\ + {VISUAL}\n\ +"; +exports.scope = "snippets"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/soy_template.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/soy_template.js new file mode 100644 index 00000000..487f2408 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/soy_template.js @@ -0,0 +1,7 @@ +define("ace/snippets/soy_template",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "soy_template"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/space.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/space.js new file mode 100644 index 00000000..c97ec607 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/space.js @@ -0,0 +1,7 @@ +define("ace/snippets/space",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "space"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sql.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sql.js new file mode 100644 index 00000000..7440ce44 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/sql.js @@ -0,0 +1,33 @@ +define("ace/snippets/sql",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet tbl\n\ + create table ${1:table} (\n\ + ${2:columns}\n\ + );\n\ +snippet col\n\ + ${1:name} ${2:type} ${3:default ''} ${4:not null}\n\ +snippet ccol\n\ + ${1:name} varchar2(${2:size}) ${3:default ''} ${4:not null}\n\ +snippet ncol\n\ + ${1:name} number ${3:default 0} ${4:not null}\n\ +snippet dcol\n\ + ${1:name} date ${3:default sysdate} ${4:not null}\n\ +snippet ind\n\ + create index ${3:$1_$2} on ${1:table}(${2:column});\n\ +snippet uind\n\ + create unique index ${1:name} on ${2:table}(${3:column});\n\ +snippet tblcom\n\ + comment on table ${1:table} is '${2:comment}';\n\ +snippet colcom\n\ + comment on column ${1:table}.${2:column} is '${3:comment}';\n\ +snippet addcol\n\ + alter table ${1:table} add (${2:column} ${3:type});\n\ +snippet seq\n\ + create sequence ${1:name} start with ${2:1} increment by ${3:1} minvalue ${4:1};\n\ +snippet s*\n\ + select * from ${1:table}\n\ +"; +exports.scope = "sql"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/stylus.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/stylus.js new file mode 100644 index 00000000..1a67e556 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/stylus.js @@ -0,0 +1,7 @@ +define("ace/snippets/stylus",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "stylus"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/svg.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/svg.js new file mode 100644 index 00000000..a1636910 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/svg.js @@ -0,0 +1,7 @@ +define("ace/snippets/svg",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "svg"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/tcl.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/tcl.js new file mode 100644 index 00000000..9a266ad1 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/tcl.js @@ -0,0 +1,99 @@ +define("ace/snippets/tcl",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# #!/usr/bin/env tclsh\n\ +snippet #!\n\ + #!/usr/bin/env tclsh\n\ + \n\ +# Process\n\ +snippet pro\n\ + proc ${1:function_name} {${2:args}} {\n\ + ${3:#body ...}\n\ + }\n\ +#xif\n\ +snippet xif\n\ + ${1:expr}? ${2:true} : ${3:false}\n\ +# Conditional\n\ +snippet if\n\ + if {${1}} {\n\ + ${2:# body...}\n\ + }\n\ +# Conditional if..else\n\ +snippet ife\n\ + if {${1}} {\n\ + ${2:# body...}\n\ + } else {\n\ + ${3:# else...}\n\ + }\n\ +# Conditional if..elsif..else\n\ +snippet ifee\n\ + if {${1}} {\n\ + ${2:# body...}\n\ + } elseif {${3}} {\n\ + ${4:# elsif...}\n\ + } else {\n\ + ${5:# else...}\n\ + }\n\ +# If catch then\n\ +snippet ifc\n\ + if { [catch {${1:#do something...}} ${2:err}] } {\n\ + ${3:# handle failure...}\n\ + }\n\ +# Catch\n\ +snippet catch\n\ + catch {${1}} ${2:err} ${3:options}\n\ +# While Loop\n\ +snippet wh\n\ + while {${1}} {\n\ + ${2:# body...}\n\ + }\n\ +# For Loop\n\ +snippet for\n\ + for {set ${2:var} 0} {$$2 < ${1:count}} {${3:incr} $2} {\n\ + ${4:# body...}\n\ + }\n\ +# Foreach Loop\n\ +snippet fore\n\ + foreach ${1:x} {${2:#list}} {\n\ + ${3:# body...}\n\ + }\n\ +# after ms script...\n\ +snippet af\n\ + after ${1:ms} ${2:#do something}\n\ +# after cancel id\n\ +snippet afc\n\ + after cancel ${1:id or script}\n\ +# after idle\n\ +snippet afi\n\ + after idle ${1:script}\n\ +# after info id\n\ +snippet afin\n\ + after info ${1:id}\n\ +# Expr\n\ +snippet exp\n\ + expr {${1:#expression here}}\n\ +# Switch\n\ +snippet sw\n\ + switch ${1:var} {\n\ + ${3:pattern 1} {\n\ + ${4:#do something}\n\ + }\n\ + default {\n\ + ${2:#do something}\n\ + }\n\ + }\n\ +# Case\n\ +snippet ca\n\ + ${1:pattern} {\n\ + ${2:#do something}\n\ + }${3}\n\ +# Namespace eval\n\ +snippet ns\n\ + namespace eval ${1:path} {${2:#script...}}\n\ +# Namespace current\n\ +snippet nsc\n\ + namespace current\n\ +"; +exports.scope = "tcl"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/tex.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/tex.js new file mode 100644 index 00000000..7ee645a3 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/tex.js @@ -0,0 +1,197 @@ +define("ace/snippets/tex",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "#PREAMBLE\n\ +#newcommand\n\ +snippet nc\n\ + \\newcommand{\\${1:cmd}}[${2:opt}]{${3:realcmd}}${4}\n\ +#usepackage\n\ +snippet up\n\ + \\usepackage[${1:[options}]{${2:package}}\n\ +#newunicodechar\n\ +snippet nuc\n\ + \\newunicodechar{${1}}{${2:\\ensuremath}${3:tex-substitute}}}\n\ +#DeclareMathOperator\n\ +snippet dmo\n\ + \\DeclareMathOperator{${1}}{${2}}\n\ +\n\ +#DOCUMENT\n\ +# \\begin{}...\\end{}\n\ +snippet begin\n\ + \\begin{${1:env}}\n\ + ${2}\n\ + \\end{$1}\n\ +# Tabular\n\ +snippet tab\n\ + \\begin{${1:tabular}}{${2:c}}\n\ + ${3}\n\ + \\end{$1}\n\ +snippet thm\n\ + \\begin[${1:author}]{${2:thm}}\n\ + ${3}\n\ + \\end{$1}\n\ +snippet center\n\ + \\begin{center}\n\ + ${1}\n\ + \\end{center}\n\ +# Align(ed)\n\ +snippet ali\n\ + \\begin{align${1:ed}}\n\ + ${2}\n\ + \\end{align$1}\n\ +# Gather(ed)\n\ +snippet gat\n\ + \\begin{gather${1:ed}}\n\ + ${2}\n\ + \\end{gather$1}\n\ +# Equation\n\ +snippet eq\n\ + \\begin{equation}\n\ + ${1}\n\ + \\end{equation}\n\ +# Equation\n\ +snippet eq*\n\ + \\begin{equation*}\n\ + ${1}\n\ + \\end{equation*}\n\ +# Unnumbered Equation\n\ +snippet \\\n\ + \\[\n\ + ${1}\n\ + \\]\n\ +# Enumerate\n\ +snippet enum\n\ + \\begin{enumerate}\n\ + \\item ${1}\n\ + \\end{enumerate}\n\ +# Itemize\n\ +snippet itemize\n\ + \\begin{itemize}\n\ + \\item ${1}\n\ + \\end{itemize}\n\ +# Description\n\ +snippet desc\n\ + \\begin{description}\n\ + \\item[${1}] ${2}\n\ + \\end{description}\n\ +# Matrix\n\ +snippet mat\n\ + \\begin{${1:p/b/v/V/B/small}matrix}\n\ + ${2}\n\ + \\end{$1matrix}\n\ +# Cases\n\ +snippet cas\n\ + \\begin{cases}\n\ + ${1:equation}, &\\text{ if }${2:case}\\\\\n\ + ${3}\n\ + \\end{cases}\n\ +# Split\n\ +snippet spl\n\ + \\begin{split}\n\ + ${1}\n\ + \\end{split}\n\ +# Part\n\ +snippet part\n\ + \\part{${1:part name}} % (fold)\n\ + \\label{prt:${2:$1}}\n\ + ${3}\n\ + % part $2 (end)\n\ +# Chapter\n\ +snippet cha\n\ + \\chapter{${1:chapter name}}\n\ + \\label{cha:${2:$1}}\n\ + ${3}\n\ +# Section\n\ +snippet sec\n\ + \\section{${1:section name}}\n\ + \\label{sec:${2:$1}}\n\ + ${3}\n\ +# Sub Section\n\ +snippet sub\n\ + \\subsection{${1:subsection name}}\n\ + \\label{sub:${2:$1}}\n\ + ${3}\n\ +# Sub Sub Section\n\ +snippet subs\n\ + \\subsubsection{${1:subsubsection name}}\n\ + \\label{ssub:${2:$1}}\n\ + ${3}\n\ +# Paragraph\n\ +snippet par\n\ + \\paragraph{${1:paragraph name}}\n\ + \\label{par:${2:$1}}\n\ + ${3}\n\ +# Sub Paragraph\n\ +snippet subp\n\ + \\subparagraph{${1:subparagraph name}}\n\ + \\label{subp:${2:$1}}\n\ + ${3}\n\ +#References\n\ +snippet itd\n\ + \\item[${1:description}] ${2:item}\n\ +snippet figure\n\ + ${1:Figure}~\\ref{${2:fig:}}${3}\n\ +snippet table\n\ + ${1:Table}~\\ref{${2:tab:}}${3}\n\ +snippet listing\n\ + ${1:Listing}~\\ref{${2:list}}${3}\n\ +snippet section\n\ + ${1:Section}~\\ref{${2:sec:}}${3}\n\ +snippet page\n\ + ${1:page}~\\pageref{${2}}${3}\n\ +snippet index\n\ + \\index{${1:index}}${2}\n\ +#Citations\n\ +snippet cite\n\ + \\cite[${1}]{${2}}${3}\n\ +snippet fcite\n\ + \\footcite[${1}]{${2}}${3}\n\ +#Formating text: italic, bold, underline, small capital, emphase ..\n\ +snippet it\n\ + \\textit{${1:text}}\n\ +snippet bf\n\ + \\textbf{${1:text}}\n\ +snippet under\n\ + \\underline{${1:text}}\n\ +snippet emp\n\ + \\emph{${1:text}}\n\ +snippet sc\n\ + \\textsc{${1:text}}\n\ +#Choosing font\n\ +snippet sf\n\ + \\textsf{${1:text}}\n\ +snippet rm\n\ + \\textrm{${1:text}}\n\ +snippet tt\n\ + \\texttt{${1:text}}\n\ +#misc\n\ +snippet ft\n\ + \\footnote{${1:text}}\n\ +snippet fig\n\ + \\begin{figure}\n\ + \\begin{center}\n\ + \\includegraphics[scale=${1}]{Figures/${2}}\n\ + \\end{center}\n\ + \\caption{${3}}\n\ + \\label{fig:${4}}\n\ + \\end{figure}\n\ +snippet tikz\n\ + \\begin{figure}\n\ + \\begin{center}\n\ + \\begin{tikzpicture}[scale=${1:1}]\n\ + ${2}\n\ + \\end{tikzpicture}\n\ + \\end{center}\n\ + \\caption{${3}}\n\ + \\label{fig:${4}}\n\ + \\end{figure}\n\ +#math\n\ +snippet stackrel\n\ + \\stackrel{${1:above}}{${2:below}} ${3}\n\ +snippet frac\n\ + \\frac{${1:num}}{${2:denom}}\n\ +snippet sum\n\ + \\sum^{${1:n}}_{${2:i=1}}{${3}}"; +exports.scope = "tex"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/text.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/text.js new file mode 100644 index 00000000..42530302 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/text.js @@ -0,0 +1,7 @@ +define("ace/snippets/text",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "text"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/textile.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/textile.js new file mode 100644 index 00000000..5fb5306a --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/textile.js @@ -0,0 +1,37 @@ +define("ace/snippets/textile",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# Jekyll post header\n\ +snippet header\n\ + ---\n\ + title: ${1:title}\n\ + layout: post\n\ + date: ${2:date} ${3:hour:minute:second} -05:00\n\ + ---\n\ +\n\ +# Image\n\ +snippet img\n\ + !${1:url}(${2:title}):${3:link}!\n\ +\n\ +# Table\n\ +snippet |\n\ + |${1}|${2}\n\ +\n\ +# Link\n\ +snippet link\n\ + \"${1:link text}\":${2:url}\n\ +\n\ +# Acronym\n\ +snippet (\n\ + (${1:Expand acronym})${2}\n\ +\n\ +# Footnote\n\ +snippet fn\n\ + [${1:ref number}] ${3}\n\ +\n\ + fn$1. ${2:footnote}\n\ + \n\ +"; +exports.scope = "textile"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/toml.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/toml.js new file mode 100644 index 00000000..dfe8f6bd --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/toml.js @@ -0,0 +1,7 @@ +define("ace/snippets/toml",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "toml"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/twig.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/twig.js new file mode 100644 index 00000000..ec656eaf --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/twig.js @@ -0,0 +1,7 @@ +define("ace/snippets/twig",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "twig"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/typescript.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/typescript.js new file mode 100644 index 00000000..144d3be7 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/typescript.js @@ -0,0 +1,7 @@ +define("ace/snippets/typescript",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "typescript"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/vala.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/vala.js new file mode 100644 index 00000000..57f6627c --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/vala.js @@ -0,0 +1,193 @@ +define("ace/snippets/vala",["require","exports","module"], function(require, exports, module) { +"use strict"; +exports.snippets = [ + { + "content": "case ${1:condition}:\n\t$0\n\tbreak;\n", + "name": "case", + "scope": "vala", + "tabTrigger": "case" + }, + { + "content": "/**\n * ${6}\n */\n${1:public} class ${2:MethodName}${3: : GLib.Object} {\n\n\t/**\n\t * ${7}\n\t */\n\tpublic ${2}(${4}) {\n\t\t${5}\n\t}\n\n\t$0\n}", + "name": "class", + "scope": "vala", + "tabTrigger": "class" + }, + { + "content": "(${1}) => {\n\t${0}\n}\n", + "name": "closure", + "scope": "vala", + "tabTrigger": "=>" + }, + { + "content": "/*\n * $0\n */", + "name": "Comment (multiline)", + "scope": "vala", + "tabTrigger": "/*" + }, + { + "content": "Console.WriteLine($1);\n$0", + "name": "Console.WriteLine (writeline)", + "scope": "vala", + "tabTrigger": "writeline" + }, + { + "content": "[DBus(name = \"$0\")]", + "name": "DBus annotation", + "scope": "vala", + "tabTrigger": "[DBus" + }, + { + "content": "delegate ${1:void} ${2:DelegateName}($0);", + "name": "delegate", + "scope": "vala", + "tabTrigger": "delegate" + }, + { + "content": "do {\n\t$0\n} while ($1);\n", + "name": "do while", + "scope": "vala", + "tabTrigger": "dowhile" + }, + { + "content": "/**\n * $0\n */", + "name": "DocBlock", + "scope": "vala", + "tabTrigger": "/**" + }, + { + "content": "else if ($1) {\n\t$0\n}\n", + "name": "else if (elseif)", + "scope": "vala", + "tabTrigger": "elseif" + }, + { + "content": "else {\n\t$0\n}", + "name": "else", + "scope": "vala", + "tabTrigger": "else" + }, + { + "content": "enum {$1:EnumName} {\n\t$0\n}", + "name": "enum", + "scope": "vala", + "tabTrigger": "enum" + }, + { + "content": "public errordomain ${1:Error} {\n\t$0\n}", + "name": "error domain", + "scope": "vala", + "tabTrigger": "errordomain" + }, + { + "content": "for ($1;$2;$3) {\n\t$0\n}", + "name": "for", + "scope": "vala", + "tabTrigger": "for" + }, + { + "content": "foreach ($1 in $2) {\n\t$0\n}", + "name": "foreach", + "scope": "vala", + "tabTrigger": "foreach" + }, + { + "content": "Gee.ArrayList<${1:G}>($0);", + "name": "Gee.ArrayList", + "scope": "vala", + "tabTrigger": "ArrayList" + }, + { + "content": "Gee.HashMap<${1:K},${2:V}>($0);", + "name": "Gee.HashMap", + "scope": "vala", + "tabTrigger": "HashMap" + }, + { + "content": "Gee.HashSet<${1:G}>($0);", + "name": "Gee.HashSet", + "scope": "vala", + "tabTrigger": "HashSet" + }, + { + "content": "if ($1) {\n\t$0\n}", + "name": "if", + "scope": "vala", + "tabTrigger": "if" + }, + { + "content": "interface ${1:InterfaceName}{$2: : SuperInterface} {\n\t$0\n}", + "name": "interface", + "scope": "vala", + "tabTrigger": "interface" + }, + { + "content": "public static int main(string [] argv) {\n\t${0}\n\treturn 0;\n}", + "name": "Main function", + "scope": "vala", + "tabTrigger": "main" + }, + { + "content": "namespace $1 {\n\t$0\n}\n", + "name": "namespace (ns)", + "scope": "vala", + "tabTrigger": "ns" + }, + { + "content": "stdout.printf($0);", + "name": "printf", + "scope": "vala", + "tabTrigger": "printf" + }, + { + "content": "${1:public} ${2:Type} ${3:Name} {\n\tset {\n\t\t$0\n\t}\n\tget {\n\n\t}\n}", + "name": "property (prop)", + "scope": "vala", + "tabTrigger": "prop" + }, + { + "content": "${1:public} ${2:Type} ${3:Name} {\n\tget {\n\t\t$0\n\t}\n}", + "name": "read-only property (roprop)", + "scope": "vala", + "tabTrigger": "roprop" + }, + { + "content": "@\"${1:\\$var}\"", + "name": "String template (@)", + "scope": "vala", + "tabTrigger": "@" + }, + { + "content": "struct ${1:StructName} {\n\t$0\n}", + "name": "struct", + "scope": "vala", + "tabTrigger": "struct" + }, + { + "content": "switch ($1) {\n\t$0\n}", + "name": "switch", + "scope": "vala", + "tabTrigger": "switch" + }, + { + "content": "try {\n\t$2\n} catch (${1:Error} e) {\n\t$0\n}", + "name": "try/catch", + "scope": "vala", + "tabTrigger": "try" + }, + { + "content": "\"\"\"$0\"\"\";", + "name": "Verbatim string (\"\"\")", + "scope": "vala", + "tabTrigger": "verbatim" + }, + { + "content": "while ($1) {\n\t$0\n}", + "name": "while", + "scope": "vala", + "tabTrigger": "while" + } +]; +exports.scope = ""; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/vbscript.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/vbscript.js new file mode 100644 index 00000000..02b94ce5 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/vbscript.js @@ -0,0 +1,7 @@ +define("ace/snippets/vbscript",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "vbscript"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/velocity.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/velocity.js new file mode 100644 index 00000000..ad945bd4 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/velocity.js @@ -0,0 +1,36 @@ +define("ace/snippets/velocity",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# macro\n\ +snippet #macro\n\ + #macro ( ${1:macroName} ${2:\\$var1, [\\$var2, ...]} )\n\ + ${3:## macro code}\n\ + #end\n\ +# foreach\n\ +snippet #foreach\n\ + #foreach ( ${1:\\$item} in ${2:\\$collection} )\n\ + ${3:## foreach code}\n\ + #end\n\ +# if\n\ +snippet #if\n\ + #if ( ${1:true} )\n\ + ${0}\n\ + #end\n\ +# if ... else\n\ +snippet #ife\n\ + #if ( ${1:true} )\n\ + ${2}\n\ + #else\n\ + ${0}\n\ + #end\n\ +#import\n\ +snippet #import\n\ + #import ( \"${1:path/to/velocity/format}\" )\n\ +# set\n\ +snippet #set\n\ + #set ( $${1:var} = ${0} )\n\ +"; +exports.scope = "velocity"; +exports.includeScopes = ["html", "javascript", "css"]; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/verilog.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/verilog.js new file mode 100644 index 00000000..fa3db8ed --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/verilog.js @@ -0,0 +1,7 @@ +define("ace/snippets/verilog",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "verilog"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/vhdl.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/vhdl.js new file mode 100644 index 00000000..e06d2cff --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/vhdl.js @@ -0,0 +1,7 @@ +define("ace/snippets/vhdl",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "vhdl"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/xml.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/xml.js new file mode 100644 index 00000000..de14ce01 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/xml.js @@ -0,0 +1,7 @@ +define("ace/snippets/xml",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "xml"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/xquery.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/xquery.js new file mode 100644 index 00000000..c45681fd --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/xquery.js @@ -0,0 +1,68 @@ +define("ace/snippets/xquery",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet for\n\ + for $${1:item} in ${2:expr}\n\ +snippet return\n\ + return ${1:expr}\n\ +snippet import\n\ + import module namespace ${1:ns} = \"${2:http://www.example.com/}\";\n\ +snippet some\n\ + some $${1:varname} in ${2:expr} satisfies ${3:expr}\n\ +snippet every\n\ + every $${1:varname} in ${2:expr} satisfies ${3:expr}\n\ +snippet if\n\ + if(${1:true}) then ${2:expr} else ${3:true}\n\ +snippet switch\n\ + switch(${1:\"foo\"})\n\ + case ${2:\"foo\"}\n\ + return ${3:true}\n\ + default return ${4:false}\n\ +snippet try\n\ + try { ${1:expr} } catch ${2:*} { ${3:expr} }\n\ +snippet tumbling\n\ + for tumbling window $${1:varname} in ${2:expr}\n\ + start at $${3:start} when ${4:expr}\n\ + end at $${5:end} when ${6:expr}\n\ + return ${7:expr}\n\ +snippet sliding\n\ + for sliding window $${1:varname} in ${2:expr}\n\ + start at $${3:start} when ${4:expr}\n\ + end at $${5:end} when ${6:expr}\n\ + return ${7:expr}\n\ +snippet let\n\ + let $${1:varname} := ${2:expr}\n\ +snippet group\n\ + group by $${1:varname} := ${2:expr}\n\ +snippet order\n\ + order by ${1:expr} ${2:descending}\n\ +snippet stable\n\ + stable order by ${1:expr}\n\ +snippet count\n\ + count $${1:varname}\n\ +snippet ordered\n\ + ordered { ${1:expr} }\n\ +snippet unordered\n\ + unordered { ${1:expr} }\n\ +snippet treat \n\ + treat as ${1:expr}\n\ +snippet castable\n\ + castable as ${1:atomicType}\n\ +snippet cast\n\ + cast as ${1:atomicType}\n\ +snippet typeswitch\n\ + typeswitch(${1:expr})\n\ + case ${2:type} return ${3:expr}\n\ + default return ${4:expr}\n\ +snippet var\n\ + declare variable $${1:varname} := ${2:expr};\n\ +snippet fn\n\ + declare function ${1:ns}:${2:name}(){\n\ + ${3:expr}\n\ + };\n\ +snippet module\n\ + module namespace ${1:ns} = \"${2:http://www.example.com}\";\n\ +"; +exports.scope = "xquery"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/snippets/yaml.js b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/yaml.js new file mode 100644 index 00000000..f3f31fee --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/snippets/yaml.js @@ -0,0 +1,7 @@ +define("ace/snippets/yaml",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "yaml"; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/theme-chrome.js b/Patent2Net/media/graph-recipes/app/assets/ace/theme-chrome.js new file mode 100644 index 00000000..3b3b6cf7 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/theme-chrome.js @@ -0,0 +1,128 @@ +define("ace/theme/chrome",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-chrome"; +exports.cssText = ".ace-chrome .ace_gutter {\ +background: #ebebeb;\ +color: #333;\ +overflow : hidden;\ +}\ +.ace-chrome .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8;\ +}\ +.ace-chrome {\ +background-color: #FFFFFF;\ +color: black;\ +}\ +.ace-chrome .ace_cursor {\ +color: black;\ +}\ +.ace-chrome .ace_invisible {\ +color: rgb(191, 191, 191);\ +}\ +.ace-chrome .ace_constant.ace_buildin {\ +color: rgb(88, 72, 246);\ +}\ +.ace-chrome .ace_constant.ace_language {\ +color: rgb(88, 92, 246);\ +}\ +.ace-chrome .ace_constant.ace_library {\ +color: rgb(6, 150, 14);\ +}\ +.ace-chrome .ace_invalid {\ +background-color: rgb(153, 0, 0);\ +color: white;\ +}\ +.ace-chrome .ace_fold {\ +}\ +.ace-chrome .ace_support.ace_function {\ +color: rgb(60, 76, 114);\ +}\ +.ace-chrome .ace_support.ace_constant {\ +color: rgb(6, 150, 14);\ +}\ +.ace-chrome .ace_support.ace_type,\ +.ace-chrome .ace_support.ace_class\ +.ace-chrome .ace_support.ace_other {\ +color: rgb(109, 121, 222);\ +}\ +.ace-chrome .ace_variable.ace_parameter {\ +font-style:italic;\ +color:#FD971F;\ +}\ +.ace-chrome .ace_keyword.ace_operator {\ +color: rgb(104, 118, 135);\ +}\ +.ace-chrome .ace_comment {\ +color: #236e24;\ +}\ +.ace-chrome .ace_comment.ace_doc {\ +color: #236e24;\ +}\ +.ace-chrome .ace_comment.ace_doc.ace_tag {\ +color: #236e24;\ +}\ +.ace-chrome .ace_constant.ace_numeric {\ +color: rgb(0, 0, 205);\ +}\ +.ace-chrome .ace_variable {\ +color: rgb(49, 132, 149);\ +}\ +.ace-chrome .ace_xml-pe {\ +color: rgb(104, 104, 91);\ +}\ +.ace-chrome .ace_entity.ace_name.ace_function {\ +color: #0000A2;\ +}\ +.ace-chrome .ace_heading {\ +color: rgb(12, 7, 255);\ +}\ +.ace-chrome .ace_list {\ +color:rgb(185, 6, 144);\ +}\ +.ace-chrome .ace_marker-layer .ace_selection {\ +background: rgb(181, 213, 255);\ +}\ +.ace-chrome .ace_marker-layer .ace_step {\ +background: rgb(252, 255, 0);\ +}\ +.ace-chrome .ace_marker-layer .ace_stack {\ +background: rgb(164, 229, 101);\ +}\ +.ace-chrome .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgb(192, 192, 192);\ +}\ +.ace-chrome .ace_marker-layer .ace_active-line {\ +background: rgba(0, 0, 0, 0.07);\ +}\ +.ace-chrome .ace_gutter-active-line {\ +background-color : #dcdcdc;\ +}\ +.ace-chrome .ace_marker-layer .ace_selected-word {\ +background: rgb(250, 250, 255);\ +border: 1px solid rgb(200, 200, 250);\ +}\ +.ace-chrome .ace_storage,\ +.ace-chrome .ace_keyword,\ +.ace-chrome .ace_meta.ace_tag {\ +color: rgb(147, 15, 128);\ +}\ +.ace-chrome .ace_string.ace_regex {\ +color: rgb(255, 0, 0)\ +}\ +.ace-chrome .ace_string {\ +color: #1A1AA6;\ +}\ +.ace-chrome .ace_entity.ace_other.ace_attribute-name {\ +color: #994409;\ +}\ +.ace-chrome .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ +}\ +"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/theme-clouds.js b/Patent2Net/media/graph-recipes/app/assets/ace/theme-clouds.js new file mode 100644 index 00000000..e029da32 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/theme-clouds.js @@ -0,0 +1,96 @@ +define("ace/theme/clouds",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-clouds"; +exports.cssText = ".ace-clouds .ace_gutter {\ +background: #ebebeb;\ +color: #333\ +}\ +.ace-clouds .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8\ +}\ +.ace-clouds {\ +background-color: #FFFFFF;\ +color: #000000\ +}\ +.ace-clouds .ace_cursor {\ +color: #000000\ +}\ +.ace-clouds .ace_marker-layer .ace_selection {\ +background: #BDD5FC\ +}\ +.ace-clouds.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #FFFFFF;\ +border-radius: 2px\ +}\ +.ace-clouds .ace_marker-layer .ace_step {\ +background: rgb(255, 255, 0)\ +}\ +.ace-clouds .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #BFBFBF\ +}\ +.ace-clouds .ace_marker-layer .ace_active-line {\ +background: #FFFBD1\ +}\ +.ace-clouds .ace_gutter-active-line {\ +background-color : #dcdcdc\ +}\ +.ace-clouds .ace_marker-layer .ace_selected-word {\ +border: 1px solid #BDD5FC\ +}\ +.ace-clouds .ace_invisible {\ +color: #BFBFBF\ +}\ +.ace-clouds .ace_keyword,\ +.ace-clouds .ace_meta,\ +.ace-clouds .ace_support.ace_constant.ace_property-value {\ +color: #AF956F\ +}\ +.ace-clouds .ace_keyword.ace_operator {\ +color: #484848\ +}\ +.ace-clouds .ace_keyword.ace_other.ace_unit {\ +color: #96DC5F\ +}\ +.ace-clouds .ace_constant.ace_language {\ +color: #39946A\ +}\ +.ace-clouds .ace_constant.ace_numeric {\ +color: #46A609\ +}\ +.ace-clouds .ace_constant.ace_character.ace_entity {\ +color: #BF78CC\ +}\ +.ace-clouds .ace_invalid {\ +background-color: #FF002A\ +}\ +.ace-clouds .ace_fold {\ +background-color: #AF956F;\ +border-color: #000000\ +}\ +.ace-clouds .ace_storage,\ +.ace-clouds .ace_support.ace_class,\ +.ace-clouds .ace_support.ace_function,\ +.ace-clouds .ace_support.ace_other,\ +.ace-clouds .ace_support.ace_type {\ +color: #C52727\ +}\ +.ace-clouds .ace_string {\ +color: #5D90CD\ +}\ +.ace-clouds .ace_comment {\ +color: #BCC8BA\ +}\ +.ace-clouds .ace_entity.ace_name.ace_tag,\ +.ace-clouds .ace_entity.ace_other.ace_attribute-name {\ +color: #606060\ +}\ +.ace-clouds .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/theme-clouds_midnight.js b/Patent2Net/media/graph-recipes/app/assets/ace/theme-clouds_midnight.js new file mode 100644 index 00000000..4160e5ea --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/theme-clouds_midnight.js @@ -0,0 +1,97 @@ +define("ace/theme/clouds_midnight",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-clouds-midnight"; +exports.cssText = ".ace-clouds-midnight .ace_gutter {\ +background: #232323;\ +color: #929292\ +}\ +.ace-clouds-midnight .ace_print-margin {\ +width: 1px;\ +background: #232323\ +}\ +.ace-clouds-midnight {\ +background-color: #191919;\ +color: #929292\ +}\ +.ace-clouds-midnight .ace_cursor {\ +color: #7DA5DC\ +}\ +.ace-clouds-midnight .ace_marker-layer .ace_selection {\ +background: #000000\ +}\ +.ace-clouds-midnight.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #191919;\ +border-radius: 2px\ +}\ +.ace-clouds-midnight .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-clouds-midnight .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #BFBFBF\ +}\ +.ace-clouds-midnight .ace_marker-layer .ace_active-line {\ +background: rgba(215, 215, 215, 0.031)\ +}\ +.ace-clouds-midnight .ace_gutter-active-line {\ +background-color: rgba(215, 215, 215, 0.031)\ +}\ +.ace-clouds-midnight .ace_marker-layer .ace_selected-word {\ +border: 1px solid #000000\ +}\ +.ace-clouds-midnight .ace_invisible {\ +color: #BFBFBF\ +}\ +.ace-clouds-midnight .ace_keyword,\ +.ace-clouds-midnight .ace_meta,\ +.ace-clouds-midnight .ace_support.ace_constant.ace_property-value {\ +color: #927C5D\ +}\ +.ace-clouds-midnight .ace_keyword.ace_operator {\ +color: #4B4B4B\ +}\ +.ace-clouds-midnight .ace_keyword.ace_other.ace_unit {\ +color: #366F1A\ +}\ +.ace-clouds-midnight .ace_constant.ace_language {\ +color: #39946A\ +}\ +.ace-clouds-midnight .ace_constant.ace_numeric {\ +color: #46A609\ +}\ +.ace-clouds-midnight .ace_constant.ace_character.ace_entity {\ +color: #A165AC\ +}\ +.ace-clouds-midnight .ace_invalid {\ +color: #FFFFFF;\ +background-color: #E92E2E\ +}\ +.ace-clouds-midnight .ace_fold {\ +background-color: #927C5D;\ +border-color: #929292\ +}\ +.ace-clouds-midnight .ace_storage,\ +.ace-clouds-midnight .ace_support.ace_class,\ +.ace-clouds-midnight .ace_support.ace_function,\ +.ace-clouds-midnight .ace_support.ace_other,\ +.ace-clouds-midnight .ace_support.ace_type {\ +color: #E92E2E\ +}\ +.ace-clouds-midnight .ace_string {\ +color: #5D90CD\ +}\ +.ace-clouds-midnight .ace_comment {\ +color: #3C403B\ +}\ +.ace-clouds-midnight .ace_entity.ace_name.ace_tag,\ +.ace-clouds-midnight .ace_entity.ace_other.ace_attribute-name {\ +color: #606060\ +}\ +.ace-clouds-midnight .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHB3d/8PAAOIAdULw8qMAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/theme-twilight.js b/Patent2Net/media/graph-recipes/app/assets/ace/theme-twilight.js new file mode 100644 index 00000000..3c619de4 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/theme-twilight.js @@ -0,0 +1,110 @@ +define("ace/theme/twilight",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-twilight"; +exports.cssText = ".ace-twilight .ace_gutter {\ +background: #232323;\ +color: #E2E2E2\ +}\ +.ace-twilight .ace_print-margin {\ +width: 1px;\ +background: #232323\ +}\ +.ace-twilight {\ +background-color: #141414;\ +color: #F8F8F8\ +}\ +.ace-twilight .ace_cursor {\ +color: #A7A7A7\ +}\ +.ace-twilight .ace_marker-layer .ace_selection {\ +background: rgba(221, 240, 255, 0.20)\ +}\ +.ace-twilight.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #141414;\ +border-radius: 2px\ +}\ +.ace-twilight .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-twilight .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(255, 255, 255, 0.25)\ +}\ +.ace-twilight .ace_marker-layer .ace_active-line {\ +background: rgba(255, 255, 255, 0.031)\ +}\ +.ace-twilight .ace_gutter-active-line {\ +background-color: rgba(255, 255, 255, 0.031)\ +}\ +.ace-twilight .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgba(221, 240, 255, 0.20)\ +}\ +.ace-twilight .ace_invisible {\ +color: rgba(255, 255, 255, 0.25)\ +}\ +.ace-twilight .ace_keyword,\ +.ace-twilight .ace_meta {\ +color: #CDA869\ +}\ +.ace-twilight .ace_constant,\ +.ace-twilight .ace_constant.ace_character,\ +.ace-twilight .ace_constant.ace_character.ace_escape,\ +.ace-twilight .ace_constant.ace_other,\ +.ace-twilight .ace_heading,\ +.ace-twilight .ace_markup.ace_heading,\ +.ace-twilight .ace_support.ace_constant {\ +color: #CF6A4C\ +}\ +.ace-twilight .ace_invalid.ace_illegal {\ +color: #F8F8F8;\ +background-color: rgba(86, 45, 86, 0.75)\ +}\ +.ace-twilight .ace_invalid.ace_deprecated {\ +text-decoration: underline;\ +font-style: italic;\ +color: #D2A8A1\ +}\ +.ace-twilight .ace_support {\ +color: #9B859D\ +}\ +.ace-twilight .ace_fold {\ +background-color: #AC885B;\ +border-color: #F8F8F8\ +}\ +.ace-twilight .ace_support.ace_function {\ +color: #DAD085\ +}\ +.ace-twilight .ace_list,\ +.ace-twilight .ace_markup.ace_list,\ +.ace-twilight .ace_storage {\ +color: #F9EE98\ +}\ +.ace-twilight .ace_entity.ace_name.ace_function,\ +.ace-twilight .ace_meta.ace_tag,\ +.ace-twilight .ace_variable {\ +color: #AC885B\ +}\ +.ace-twilight .ace_string {\ +color: #8F9D6A\ +}\ +.ace-twilight .ace_string.ace_regexp {\ +color: #E9C062\ +}\ +.ace-twilight .ace_comment {\ +font-style: italic;\ +color: #5F5A60\ +}\ +.ace-twilight .ace_variable {\ +color: #7587A6\ +}\ +.ace-twilight .ace_xml-pe {\ +color: #494949\ +}\ +.ace-twilight .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMQERFpYLC1tf0PAAgOAnPnhxyiAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/worker-javascript.js b/Patent2Net/media/graph-recipes/app/assets/ace/worker-javascript.js new file mode 100644 index 00000000..ea4c959e --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/worker-javascript.js @@ -0,0 +1,11019 @@ +"no use strict"; +;(function(window) { +if (typeof window.window != "undefined" && window.document) { + return; +} + +window.console = function() { + var msgs = Array.prototype.slice.call(arguments, 0); + postMessage({type: "log", data: msgs}); +}; +window.console.error = +window.console.warn = +window.console.log = +window.console.trace = window.console; + +window.window = window; +window.ace = window; + +window.onerror = function(message, file, line, col, err) { + postMessage({type: "error", data: { + message: message, + file: file, + line: line, + col: col, + stack: err.stack + }}); +}; + +window.normalizeModule = function(parentId, moduleName) { + // normalize plugin requires + if (moduleName.indexOf("!") !== -1) { + var chunks = moduleName.split("!"); + return window.normalizeModule(parentId, chunks[0]) + "!" + window.normalizeModule(parentId, chunks[1]); + } + // normalize relative requires + if (moduleName.charAt(0) == ".") { + var base = parentId.split("/").slice(0, -1).join("/"); + moduleName = (base ? base + "/" : "") + moduleName; + + while(moduleName.indexOf(".") !== -1 && previous != moduleName) { + var previous = moduleName; + moduleName = moduleName.replace(/^\.\//, "").replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); + } + } + + return moduleName; +}; + +window.require = function(parentId, id) { + if (!id) { + id = parentId; + parentId = null; + } + if (!id.charAt) + throw new Error("worker.js require() accepts only (parentId, id) as arguments"); + + id = window.normalizeModule(parentId, id); + + var module = window.require.modules[id]; + if (module) { + if (!module.initialized) { + module.initialized = true; + module.exports = module.factory().exports; + } + return module.exports; + } + + var chunks = id.split("/"); + if (!window.require.tlns) + return console.log("unable to load " + id); + chunks[0] = window.require.tlns[chunks[0]] || chunks[0]; + var path = chunks.join("/") + ".js"; + + window.require.id = id; + importScripts(path); + return window.require(parentId, id); +}; +window.require.modules = {}; +window.require.tlns = {}; + +window.define = function(id, deps, factory) { + if (arguments.length == 2) { + factory = deps; + if (typeof id != "string") { + deps = id; + id = window.require.id; + } + } else if (arguments.length == 1) { + factory = id; + deps = []; + id = window.require.id; + } + + if (typeof factory != "function") { + window.require.modules[id] = { + exports: factory, + initialized: true + }; + return; + } + + if (!deps.length) + // If there is no dependencies, we inject 'require', 'exports' and + // 'module' as dependencies, to provide CommonJS compatibility. + deps = ['require', 'exports', 'module']; + + var req = function(childId) { + return window.require(id, childId); + }; + + window.require.modules[id] = { + exports: {}, + factory: function() { + var module = this; + var returnExports = factory.apply(this, deps.map(function(dep) { + switch(dep) { + // Because 'require', 'exports' and 'module' aren't actual + // dependencies, we must handle them seperately. + case 'require': return req; + case 'exports': return module.exports; + case 'module': return module; + // But for all other dependencies, we can just go ahead and + // require them. + default: return req(dep); + } + })); + if (returnExports) + module.exports = returnExports; + return module; + } + }; +}; +window.define.amd = {}; + +window.initBaseUrls = function initBaseUrls(topLevelNamespaces) { + require.tlns = topLevelNamespaces; +}; + +window.initSender = function initSender() { + + var EventEmitter = window.require("ace/lib/event_emitter").EventEmitter; + var oop = window.require("ace/lib/oop"); + + var Sender = function() {}; + + (function() { + + oop.implement(this, EventEmitter); + + this.callback = function(data, callbackId) { + postMessage({ + type: "call", + id: callbackId, + data: data + }); + }; + + this.emit = function(name, data) { + postMessage({ + type: "event", + name: name, + data: data + }); + }; + + }).call(Sender.prototype); + + return new Sender(); +}; + +var main = window.main = null; +var sender = window.sender = null; + +window.onmessage = function(e) { + var msg = e.data; + if (msg.command) { + if (main[msg.command]) + main[msg.command].apply(main, msg.args); + else + throw new Error("Unknown command:" + msg.command); + } + else if (msg.init) { + initBaseUrls(msg.tlns); + require("ace/lib/es5-shim"); + sender = window.sender = initSender(); + var clazz = require(msg.module)[msg.classname]; + main = window.main = new clazz(sender); + } + else if (msg.event && sender) { + sender._signal(msg.event, msg.data); + } +}; +})(this); + +define("ace/lib/oop",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.inherits = function(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); +}; + +exports.mixin = function(obj, mixin) { + for (var key in mixin) { + obj[key] = mixin[key]; + } + return obj; +}; + +exports.implement = function(proto, mixin) { + exports.mixin(proto, mixin); +}; + +}); + +define("ace/lib/event_emitter",["require","exports","module"], function(require, exports, module) { +"use strict"; + +var EventEmitter = {}; +var stopPropagation = function() { this.propagationStopped = true; }; +var preventDefault = function() { this.defaultPrevented = true; }; + +EventEmitter._emit = +EventEmitter._dispatchEvent = function(eventName, e) { + this._eventRegistry || (this._eventRegistry = {}); + this._defaultHandlers || (this._defaultHandlers = {}); + + var listeners = this._eventRegistry[eventName] || []; + var defaultHandler = this._defaultHandlers[eventName]; + if (!listeners.length && !defaultHandler) + return; + + if (typeof e != "object" || !e) + e = {}; + + if (!e.type) + e.type = eventName; + if (!e.stopPropagation) + e.stopPropagation = stopPropagation; + if (!e.preventDefault) + e.preventDefault = preventDefault; + + listeners = listeners.slice(); + for (var i=0; i [" + this.end.row + "/" + this.end.column + "]"); + }; + + this.contains = function(row, column) { + return this.compare(row, column) == 0; + }; + this.compareRange = function(range) { + var cmp, + end = range.end, + start = range.start; + + cmp = this.compare(end.row, end.column); + if (cmp == 1) { + cmp = this.compare(start.row, start.column); + if (cmp == 1) { + return 2; + } else if (cmp == 0) { + return 1; + } else { + return 0; + } + } else if (cmp == -1) { + return -2; + } else { + cmp = this.compare(start.row, start.column); + if (cmp == -1) { + return -1; + } else if (cmp == 1) { + return 42; + } else { + return 0; + } + } + }; + this.comparePoint = function(p) { + return this.compare(p.row, p.column); + }; + this.containsRange = function(range) { + return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; + }; + this.intersects = function(range) { + var cmp = this.compareRange(range); + return (cmp == -1 || cmp == 0 || cmp == 1); + }; + this.isEnd = function(row, column) { + return this.end.row == row && this.end.column == column; + }; + this.isStart = function(row, column) { + return this.start.row == row && this.start.column == column; + }; + this.setStart = function(row, column) { + if (typeof row == "object") { + this.start.column = row.column; + this.start.row = row.row; + } else { + this.start.row = row; + this.start.column = column; + } + }; + this.setEnd = function(row, column) { + if (typeof row == "object") { + this.end.column = row.column; + this.end.row = row.row; + } else { + this.end.row = row; + this.end.column = column; + } + }; + this.inside = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column) || this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideStart = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideEnd = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.compare = function(row, column) { + if (!this.isMultiLine()) { + if (row === this.start.row) { + return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); + }; + } + + if (row < this.start.row) + return -1; + + if (row > this.end.row) + return 1; + + if (this.start.row === row) + return column >= this.start.column ? 0 : -1; + + if (this.end.row === row) + return column <= this.end.column ? 0 : 1; + + return 0; + }; + this.compareStart = function(row, column) { + if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.compareEnd = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else { + return this.compare(row, column); + } + }; + this.compareInside = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.clipRows = function(firstRow, lastRow) { + if (this.end.row > lastRow) + var end = {row: lastRow + 1, column: 0}; + else if (this.end.row < firstRow) + var end = {row: firstRow, column: 0}; + + if (this.start.row > lastRow) + var start = {row: lastRow + 1, column: 0}; + else if (this.start.row < firstRow) + var start = {row: firstRow, column: 0}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + this.extend = function(row, column) { + var cmp = this.compare(row, column); + + if (cmp == 0) + return this; + else if (cmp == -1) + var start = {row: row, column: column}; + else + var end = {row: row, column: column}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + + this.isEmpty = function() { + return (this.start.row === this.end.row && this.start.column === this.end.column); + }; + this.isMultiLine = function() { + return (this.start.row !== this.end.row); + }; + this.clone = function() { + return Range.fromPoints(this.start, this.end); + }; + this.collapseRows = function() { + if (this.end.column == 0) + return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) + else + return new Range(this.start.row, 0, this.end.row, 0) + }; + this.toScreenRange = function(session) { + var screenPosStart = session.documentToScreenPosition(this.start); + var screenPosEnd = session.documentToScreenPosition(this.end); + + return new Range( + screenPosStart.row, screenPosStart.column, + screenPosEnd.row, screenPosEnd.column + ); + }; + this.moveBy = function(row, column) { + this.start.row += row; + this.start.column += column; + this.end.row += row; + this.end.column += column; + }; + +}).call(Range.prototype); +Range.fromPoints = function(start, end) { + return new Range(start.row, start.column, end.row, end.column); +}; +Range.comparePoints = comparePoints; + +Range.comparePoints = function(p1, p2) { + return p1.row - p2.row || p1.column - p2.column; +}; + + +exports.Range = Range; +}); + +define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; + +var Anchor = exports.Anchor = function(doc, row, column) { + this.$onChange = this.onChange.bind(this); + this.attach(doc); + + if (typeof column == "undefined") + this.setPosition(row.row, row.column); + else + this.setPosition(row, column); +}; + +(function() { + + oop.implement(this, EventEmitter); + this.getPosition = function() { + return this.$clipPositionToDocument(this.row, this.column); + }; + this.getDocument = function() { + return this.document; + }; + this.$insertRight = false; + this.onChange = function(e) { + var delta = e.data; + var range = delta.range; + + if (range.start.row == range.end.row && range.start.row != this.row) + return; + + if (range.start.row > this.row) + return; + + if (range.start.row == this.row && range.start.column > this.column) + return; + + var row = this.row; + var column = this.column; + var start = range.start; + var end = range.end; + + if (delta.action === "insertText") { + if (start.row === row && start.column <= column) { + if (start.column === column && this.$insertRight) { + } else if (start.row === end.row) { + column += end.column - start.column; + } else { + column -= start.column; + row += end.row - start.row; + } + } else if (start.row !== end.row && start.row < row) { + row += end.row - start.row; + } + } else if (delta.action === "insertLines") { + if (start.row === row && column === 0 && this.$insertRight) { + } + else if (start.row <= row) { + row += end.row - start.row; + } + } else if (delta.action === "removeText") { + if (start.row === row && start.column < column) { + if (end.column >= column) + column = start.column; + else + column = Math.max(0, column - (end.column - start.column)); + + } else if (start.row !== end.row && start.row < row) { + if (end.row === row) + column = Math.max(0, column - end.column) + start.column; + row -= (end.row - start.row); + } else if (end.row === row) { + row -= end.row - start.row; + column = Math.max(0, column - end.column) + start.column; + } + } else if (delta.action == "removeLines") { + if (start.row <= row) { + if (end.row <= row) + row -= end.row - start.row; + else { + row = start.row; + column = 0; + } + } + } + + this.setPosition(row, column, true); + }; + this.setPosition = function(row, column, noClip) { + var pos; + if (noClip) { + pos = { + row: row, + column: column + }; + } else { + pos = this.$clipPositionToDocument(row, column); + } + + if (this.row == pos.row && this.column == pos.column) + return; + + var old = { + row: this.row, + column: this.column + }; + + this.row = pos.row; + this.column = pos.column; + this._signal("change", { + old: old, + value: pos + }); + }; + this.detach = function() { + this.document.removeEventListener("change", this.$onChange); + }; + this.attach = function(doc) { + this.document = doc || this.document; + this.document.on("change", this.$onChange); + }; + this.$clipPositionToDocument = function(row, column) { + var pos = {}; + + if (row >= this.document.getLength()) { + pos.row = Math.max(0, this.document.getLength() - 1); + pos.column = this.document.getLine(pos.row).length; + } + else if (row < 0) { + pos.row = 0; + pos.column = 0; + } + else { + pos.row = row; + pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); + } + + if (column < 0) + pos.column = 0; + + return pos; + }; + +}).call(Anchor.prototype); + +}); + +define("ace/document",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/range","ace/anchor"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var Range = require("./range").Range; +var Anchor = require("./anchor").Anchor; + +var Document = function(text) { + this.$lines = []; + if (text.length === 0) { + this.$lines = [""]; + } else if (Array.isArray(text)) { + this._insertLines(0, text); + } else { + this.insert({row: 0, column:0}, text); + } +}; + +(function() { + + oop.implement(this, EventEmitter); + this.setValue = function(text) { + var len = this.getLength(); + this.remove(new Range(0, 0, len, this.getLine(len-1).length)); + this.insert({row: 0, column:0}, text); + }; + this.getValue = function() { + return this.getAllLines().join(this.getNewLineCharacter()); + }; + this.createAnchor = function(row, column) { + return new Anchor(this, row, column); + }; + if ("aaa".split(/a/).length === 0) + this.$split = function(text) { + return text.replace(/\r\n|\r/g, "\n").split("\n"); + }; + else + this.$split = function(text) { + return text.split(/\r\n|\r|\n/); + }; + + + this.$detectNewLine = function(text) { + var match = text.match(/^.*?(\r\n|\r|\n)/m); + this.$autoNewLine = match ? match[1] : "\n"; + this._signal("changeNewLineMode"); + }; + this.getNewLineCharacter = function() { + switch (this.$newLineMode) { + case "windows": + return "\r\n"; + case "unix": + return "\n"; + default: + return this.$autoNewLine || "\n"; + } + }; + + this.$autoNewLine = ""; + this.$newLineMode = "auto"; + this.setNewLineMode = function(newLineMode) { + if (this.$newLineMode === newLineMode) + return; + + this.$newLineMode = newLineMode; + this._signal("changeNewLineMode"); + }; + this.getNewLineMode = function() { + return this.$newLineMode; + }; + this.isNewLine = function(text) { + return (text == "\r\n" || text == "\r" || text == "\n"); + }; + this.getLine = function(row) { + return this.$lines[row] || ""; + }; + this.getLines = function(firstRow, lastRow) { + return this.$lines.slice(firstRow, lastRow + 1); + }; + this.getAllLines = function() { + return this.getLines(0, this.getLength()); + }; + this.getLength = function() { + return this.$lines.length; + }; + this.getTextRange = function(range) { + if (range.start.row == range.end.row) { + return this.getLine(range.start.row) + .substring(range.start.column, range.end.column); + } + var lines = this.getLines(range.start.row, range.end.row); + lines[0] = (lines[0] || "").substring(range.start.column); + var l = lines.length - 1; + if (range.end.row - range.start.row == l) + lines[l] = lines[l].substring(0, range.end.column); + return lines.join(this.getNewLineCharacter()); + }; + + this.$clipPosition = function(position) { + var length = this.getLength(); + if (position.row >= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length-1).length; + } else if (position.row < 0) + position.row = 0; + return position; + }; + this.insert = function(position, text) { + if (!text || text.length === 0) + return position; + + position = this.$clipPosition(position); + if (this.getLength() <= 1) + this.$detectNewLine(text); + + var lines = this.$split(text); + var firstLine = lines.splice(0, 1)[0]; + var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0]; + + position = this.insertInLine(position, firstLine); + if (lastLine !== null) { + position = this.insertNewLine(position); // terminate first line + position = this._insertLines(position.row, lines); + position = this.insertInLine(position, lastLine || ""); + } + return position; + }; + this.insertLines = function(row, lines) { + if (row >= this.getLength()) + return this.insert({row: row, column: 0}, "\n" + lines.join("\n")); + return this._insertLines(Math.max(row, 0), lines); + }; + this._insertLines = function(row, lines) { + if (lines.length == 0) + return {row: row, column: 0}; + while (lines.length > 20000) { + var end = this._insertLines(row, lines.slice(0, 20000)); + lines = lines.slice(20000); + row = end.row; + } + + var args = [row, 0]; + args.push.apply(args, lines); + this.$lines.splice.apply(this.$lines, args); + + var range = new Range(row, 0, row + lines.length, 0); + var delta = { + action: "insertLines", + range: range, + lines: lines + }; + this._signal("change", { data: delta }); + return range.end; + }; + this.insertNewLine = function(position) { + position = this.$clipPosition(position); + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column); + this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length)); + + var end = { + row : position.row + 1, + column : 0 + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: this.getNewLineCharacter() + }; + this._signal("change", { data: delta }); + + return end; + }; + this.insertInLine = function(position, text) { + if (text.length == 0) + return position; + + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column) + text + + line.substring(position.column); + + var end = { + row : position.row, + column : position.column + text.length + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: text + }; + this._signal("change", { data: delta }); + + return end; + }; + this.remove = function(range) { + if (!(range instanceof Range)) + range = Range.fromPoints(range.start, range.end); + range.start = this.$clipPosition(range.start); + range.end = this.$clipPosition(range.end); + + if (range.isEmpty()) + return range.start; + + var firstRow = range.start.row; + var lastRow = range.end.row; + + if (range.isMultiLine()) { + var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1; + var lastFullRow = lastRow - 1; + + if (range.end.column > 0) + this.removeInLine(lastRow, 0, range.end.column); + + if (lastFullRow >= firstFullRow) + this._removeLines(firstFullRow, lastFullRow); + + if (firstFullRow != firstRow) { + this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length); + this.removeNewLine(range.start.row); + } + } + else { + this.removeInLine(firstRow, range.start.column, range.end.column); + } + return range.start; + }; + this.removeInLine = function(row, startColumn, endColumn) { + if (startColumn == endColumn) + return; + + var range = new Range(row, startColumn, row, endColumn); + var line = this.getLine(row); + var removed = line.substring(startColumn, endColumn); + var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length); + this.$lines.splice(row, 1, newLine); + + var delta = { + action: "removeText", + range: range, + text: removed + }; + this._signal("change", { data: delta }); + return range.start; + }; + this.removeLines = function(firstRow, lastRow) { + if (firstRow < 0 || lastRow >= this.getLength()) + return this.remove(new Range(firstRow, 0, lastRow + 1, 0)); + return this._removeLines(firstRow, lastRow); + }; + + this._removeLines = function(firstRow, lastRow) { + var range = new Range(firstRow, 0, lastRow + 1, 0); + var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1); + + var delta = { + action: "removeLines", + range: range, + nl: this.getNewLineCharacter(), + lines: removed + }; + this._signal("change", { data: delta }); + return removed; + }; + this.removeNewLine = function(row) { + var firstLine = this.getLine(row); + var secondLine = this.getLine(row+1); + + var range = new Range(row, firstLine.length, row+1, 0); + var line = firstLine + secondLine; + + this.$lines.splice(row, 2, line); + + var delta = { + action: "removeText", + range: range, + text: this.getNewLineCharacter() + }; + this._signal("change", { data: delta }); + }; + this.replace = function(range, text) { + if (!(range instanceof Range)) + range = Range.fromPoints(range.start, range.end); + if (text.length == 0 && range.isEmpty()) + return range.start; + if (text == this.getTextRange(range)) + return range.end; + + this.remove(range); + if (text) { + var end = this.insert(range.start, text); + } + else { + end = range.start; + } + + return end; + }; + this.applyDeltas = function(deltas) { + for (var i=0; i=0; i--) { + var delta = deltas[i]; + + var range = Range.fromPoints(delta.range.start, delta.range.end); + + if (delta.action == "insertLines") + this._removeLines(range.start.row, range.end.row - 1); + else if (delta.action == "insertText") + this.remove(range); + else if (delta.action == "removeLines") + this._insertLines(range.start.row, delta.lines); + else if (delta.action == "removeText") + this.insert(range.start, delta.text); + } + }; + this.indexToPosition = function(index, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + for (var i = startRow || 0, l = lines.length; i < l; i++) { + index -= lines[i].length + newlineLength; + if (index < 0) + return {row: i, column: index + lines[i].length + newlineLength}; + } + return {row: l-1, column: lines[l-1].length}; + }; + this.positionToIndex = function(pos, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + var index = 0; + var row = Math.min(pos.row, lines.length); + for (var i = startRow || 0; i < row; ++i) + index += lines[i].length + newlineLength; + + return index + pos.column; + }; + +}).call(Document.prototype); + +exports.Document = Document; +}); + +define("ace/lib/lang",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.last = function(a) { + return a[a.length - 1]; +}; + +exports.stringReverse = function(string) { + return string.split("").reverse().join(""); +}; + +exports.stringRepeat = function (string, count) { + var result = ''; + while (count > 0) { + if (count & 1) + result += string; + + if (count >>= 1) + string += string; + } + return result; +}; + +var trimBeginRegexp = /^\s\s*/; +var trimEndRegexp = /\s\s*$/; + +exports.stringTrimLeft = function (string) { + return string.replace(trimBeginRegexp, ''); +}; + +exports.stringTrimRight = function (string) { + return string.replace(trimEndRegexp, ''); +}; + +exports.copyObject = function(obj) { + var copy = {}; + for (var key in obj) { + copy[key] = obj[key]; + } + return copy; +}; + +exports.copyArray = function(array){ + var copy = []; + for (var i=0, l=array.length; i= 65 && i <= 90 || // A-Z + i === 95 || // _ + i >= 97 && i <= 122; // a-z +} + +var identifierPartTable = []; + +for (var i = 0; i < 128; i++) { + identifierPartTable[i] = + identifierStartTable[i] || // $, _, A-Z, a-z + i >= 48 && i <= 57; // 0-9 +} + +module.exports = { + asciiIdentifierStartTable: identifierStartTable, + asciiIdentifierPartTable: identifierPartTable +}; + +}, +{}], +2:[function(_dereq_,module,exports){ + +(function() { + var root = this; + var previousUnderscore = root._; + var breaker = {}; + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + var + push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + _.VERSION = '1.6.0'; + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return obj; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, length = obj.length; i < length; i++) { + if (iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; + } + } + return obj; + }; + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results.push(iterator.call(context, value, index, list)); + }); + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + _.find = _.detect = function(obj, predicate, context) { + var result; + any(obj, function(value, index, list) { + if (predicate.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + _.filter = _.select = function(obj, predicate, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); + each(obj, function(value, index, list) { + if (predicate.call(context, value, index, list)) results.push(value); + }); + return results; + }; + _.reject = function(obj, predicate, context) { + return _.filter(obj, function(value, index, list) { + return !predicate.call(context, value, index, list); + }, context); + }; + _.every = _.all = function(obj, predicate, context) { + predicate || (predicate = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context); + each(obj, function(value, index, list) { + if (!(result = result && predicate.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + var any = _.some = _.any = function(obj, predicate, context) { + predicate || (predicate = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); + each(obj, function(value, index, list) { + if (result || (result = predicate.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + _.pluck = function(obj, key) { + return _.map(obj, _.property(key)); + }; + _.where = function(obj, attrs) { + return _.filter(obj, _.matches(attrs)); + }; + _.findWhere = function(obj, attrs) { + return _.find(obj, _.matches(attrs)); + }; + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + var result = -Infinity, lastComputed = -Infinity; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + if (computed > lastComputed) { + result = value; + lastComputed = computed; + } + }); + return result; + }; + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + var result = Infinity, lastComputed = Infinity; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + if (computed < lastComputed) { + result = value; + lastComputed = computed; + } + }); + return result; + }; + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + _.sample = function(obj, n, guard) { + if (n == null || guard) { + if (obj.length !== +obj.length) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; + var lookupIterator = function(value) { + if (value == null) return _.identity; + if (_.isFunction(value)) return value; + return _.property(value); + }; + _.sortBy = function(obj, iterator, context) { + iterator = lookupIterator(iterator); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value: value, + index: index, + criteria: iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + var group = function(behavior) { + return function(obj, iterator, context) { + var result = {}; + iterator = lookupIterator(iterator); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + }; + _.groupBy = group(function(result, key, value) { + _.has(result, key) ? result[key].push(value) : result[key] = [value]; + }); + _.indexBy = group(function(result, key, value) { + result[key] = value; + }); + _.countBy = group(function(result, key) { + _.has(result, key) ? result[key]++ : result[key] = 1; + }); + _.sortedIndex = function(array, obj, iterator, context) { + iterator = lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + if ((n == null) || guard) return array[0]; + if (n < 0) return []; + return slice.call(array, 0, n); + }; + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n == null) || guard) return array[array.length - 1]; + return slice.call(array, Math.max(array.length - n, 0)); + }; + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + _.compact = function(array) { + return _.filter(array, _.identity); + }; + var flatten = function(input, shallow, output) { + if (shallow && _.every(input, _.isArray)) { + return concat.apply(output, input); + } + each(input, function(value) { + if (_.isArray(value) || _.isArguments(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + _.partition = function(array, predicate) { + var pass = [], fail = []; + each(array, function(elem) { + (predicate(elem) ? pass : fail).push(elem); + }); + return [pass, fail]; + }; + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + _.union = function() { + return _.uniq(_.flatten(arguments, true)); + }; + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.contains(other, item); + }); + }); + }; + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + _.zip = function() { + var length = _.max(_.pluck(arguments, 'length').concat(0)); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(arguments, '' + i); + } + return results; + }; + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, length = list.length; i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, length = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < length; i++) if (array[i] === item) return i; + return -1; + }; + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(length); + + while(idx < length) { + range[idx++] = start; + start += step; + } + + return range; + }; + var ctor = function(){}; + _.bind = function(func, context) { + var args, bound; + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + ctor.prototype = null; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + _.partial = function(func) { + var boundArgs = slice.call(arguments, 1); + return function() { + var position = 0; + var args = boundArgs.slice(); + for (var i = 0, length = args.length; i < length; i++) { + if (args[i] === _) args[i] = arguments[position++]; + } + while (position < arguments.length) args.push(arguments[position++]); + return func.apply(this, args); + }; + }; + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length === 0) throw new Error('bindAll must be passed function names'); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + options || (options = {}); + var later = function() { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + context = args = null; + }; + return function() { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + _.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; + + var later = function() { + var last = _.now() - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + context = args = null; + } + } + }; + + return function() { + context = this; + args = arguments; + timestamp = _.now(); + var callNow = immediate && !timeout; + if (!timeout) { + timeout = setTimeout(later, wait); + } + if (callNow) { + result = func.apply(context, args); + context = args = null; + } + + return result; + }; + }; + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + _.wrap = function(func, wrapper) { + return _.partial(wrapper, func); + }; + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + _.keys = function(obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + return keys; + }; + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = new Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = new Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] === void 0) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + var eq = function(a, b, aStack, bStack) { + if (a === b) return a !== 0 || 1 / a == 1 / b; + if (a == null || b == null) return a === b; + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + case '[object String]': + return a == String(b); + case '[object Number]': + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + return +a == +b; + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + var length = aStack.length; + while (length--) { + if (aStack[length] == a) return bStack[length] == b; + } + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor)) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + if (className == '[object Array]') { + size = a.length; + result = size == b.length; + if (result) { + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + for (var key in a) { + if (_.has(a, key)) { + size++; + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + aStack.pop(); + bStack.pop(); + return result; + }; + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + _.isObject = function(obj) { + return obj === Object(obj); + }; + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + _.isNull = function(obj) { + return obj === null; + }; + _.isUndefined = function(obj) { + return obj === void 0; + }; + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + _.identity = function(value) { + return value; + }; + + _.constant = function(value) { + return function () { + return value; + }; + }; + + _.property = function(key) { + return function(obj) { + return obj[key]; + }; + }; + _.matches = function(attrs) { + return function(obj) { + if (obj === attrs) return true; //avoid comparing an object to itself. + for (var key in attrs) { + if (attrs[key] !== obj[key]) + return false; + } + return true; + } + }; + _.times = function(n, iterator, context) { + var accum = Array(Math.max(0, n)); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + _.now = Date.now || function() { return new Date().getTime(); }; + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + _.result = function(object, property) { + if (object == null) return void 0; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + _.mixin = function(obj) { + each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + var noMatch = /(.)^/; + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + _.template = function(text, data, settings) { + var render; + settings = _.defaults({}, settings, _.templateSettings); + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + _.chain = function(obj) { + return _(obj).chain(); + }; + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + _.mixin(_); + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + chain: function() { + this._chain = true; + return this; + }, + value: function() { + return this._wrapped; + } + + }); + if (typeof define === 'function' && define.amd) { + define('underscore', [], function() { + return _; + }); + } +}).call(this); + +}, +{}], +3:[function(_dereq_,module,exports){ + +var _ = _dereq_("underscore"); +var events = _dereq_("events"); +var vars = _dereq_("./vars.js"); +var messages = _dereq_("./messages.js"); +var Lexer = _dereq_("./lex.js").Lexer; +var reg = _dereq_("./reg.js"); +var state = _dereq_("./state.js").state; +var style = _dereq_("./style.js"); +var options = _dereq_("./options.js"); + +var JSHINT = (function () { + "use strict"; + + var api, // Extension API + bang = { + "<" : true, + "<=" : true, + "==" : true, + "===": true, + "!==": true, + "!=" : true, + ">" : true, + ">=" : true, + "+" : true, + "-" : true, + "*" : true, + "/" : true, + "%" : true + }, + + declared, // Globals that were declared using /*global ... */ syntax. + exported, // Variables that are used outside of the current file. + + functionicity = [ + "closure", "exception", "global", "label", + "outer", "unused", "var" + ], + + funct, // The current function + functions, // All of the functions + + global, // The global scope + implied, // Implied globals + inblock, + indent, + lookahead, + lex, + member, + membersOnly, + predefined, // Global variables defined by option + + scope, // The current scope + stack, + unuseds, + urls, + + extraModules = [], + emitter = new events.EventEmitter(); + + function checkOption(name, t) { + name = name.trim(); + + if (/^[+-]W\d{3}$/g.test(name)) { + return true; + } + + if (options.validNames.indexOf(name) === -1) { + if (t.type !== "jslint" && !_.has(options.removed, name)) { + error("E001", t, name); + return false; + } + } + + return true; + } + + function isString(obj) { + return Object.prototype.toString.call(obj) === "[object String]"; + } + + function isIdentifier(tkn, value) { + if (!tkn) + return false; + + if (!tkn.identifier || tkn.value !== value) + return false; + + return true; + } + + function isReserved(token) { + if (!token.reserved) { + return false; + } + var meta = token.meta; + + if (meta && meta.isFutureReservedWord && state.option.inES5()) { + if (!meta.es5) { + return false; + } + if (meta.strictOnly) { + if (!state.option.strict && !state.directive["use strict"]) { + return false; + } + } + + if (token.isProperty) { + return false; + } + } + + return true; + } + + function supplant(str, data) { + return str.replace(/\{([^{}]*)\}/g, function (a, b) { + var r = data[b]; + return typeof r === "string" || typeof r === "number" ? r : a; + }); + } + + function combine(dest, src) { + Object.keys(src).forEach(function (name) { + if (_.has(JSHINT.blacklist, name)) return; + dest[name] = src[name]; + }); + } + + function processenforceall() { + if (state.option.enforceall) { + for (var enforceopt in options.bool.enforcing) { + if (state.option[enforceopt] === undefined) { + state.option[enforceopt] = true; + } + } + for (var relaxopt in options.bool.relaxing) { + if (state.option[relaxopt] === undefined) { + state.option[relaxopt] = false; + } + } + } + } + + function assume() { + processenforceall(); + + if (state.option.esnext) { + combine(predefined, vars.newEcmaIdentifiers); + } + + if (state.option.couch) { + combine(predefined, vars.couch); + } + + if (state.option.qunit) { + combine(predefined, vars.qunit); + } + + if (state.option.rhino) { + combine(predefined, vars.rhino); + } + + if (state.option.shelljs) { + combine(predefined, vars.shelljs); + combine(predefined, vars.node); + } + if (state.option.typed) { + combine(predefined, vars.typed); + } + + if (state.option.phantom) { + combine(predefined, vars.phantom); + } + + if (state.option.prototypejs) { + combine(predefined, vars.prototypejs); + } + + if (state.option.node) { + combine(predefined, vars.node); + combine(predefined, vars.typed); + } + + if (state.option.devel) { + combine(predefined, vars.devel); + } + + if (state.option.dojo) { + combine(predefined, vars.dojo); + } + + if (state.option.browser) { + combine(predefined, vars.browser); + combine(predefined, vars.typed); + } + + if (state.option.browserify) { + combine(predefined, vars.browser); + combine(predefined, vars.typed); + combine(predefined, vars.browserify); + } + + if (state.option.nonstandard) { + combine(predefined, vars.nonstandard); + } + + if (state.option.jasmine) { + combine(predefined, vars.jasmine); + } + + if (state.option.jquery) { + combine(predefined, vars.jquery); + } + + if (state.option.mootools) { + combine(predefined, vars.mootools); + } + + if (state.option.worker) { + combine(predefined, vars.worker); + } + + if (state.option.wsh) { + combine(predefined, vars.wsh); + } + + if (state.option.globalstrict && state.option.strict !== false) { + state.option.strict = true; + } + + if (state.option.yui) { + combine(predefined, vars.yui); + } + + if (state.option.mocha) { + combine(predefined, vars.mocha); + } + + state.option.inMoz = function (strict) { + return state.option.moz; + }; + + state.option.inESNext = function (strict) { + return state.option.moz || state.option.esnext; + }; + + state.option.inES5 = function (/* strict */) { + return !state.option.es3; + }; + + state.option.inES3 = function (strict) { + if (strict) { + return !state.option.moz && !state.option.esnext && state.option.es3; + } + return state.option.es3; + }; + } + function quit(code, line, chr) { + var percentage = Math.floor((line / state.lines.length) * 100); + var message = messages.errors[code].desc; + + throw { + name: "JSHintError", + line: line, + character: chr, + message: message + " (" + percentage + "% scanned).", + raw: message, + code: code + }; + } + + function isundef(scope, code, token, a) { + return JSHINT.undefs.push([scope, code, token, a]); + } + + function removeIgnoredMessages() { + var ignored = state.ignoredLines; + + if (_.isEmpty(ignored)) return; + JSHINT.errors = _.reject(JSHINT.errors, function (err) { return ignored[err.line] }); + } + + function warning(code, t, a, b, c, d) { + var ch, l, w, msg; + + if (/^W\d{3}$/.test(code)) { + if (state.ignored[code]) + return; + + msg = messages.warnings[code]; + } else if (/E\d{3}/.test(code)) { + msg = messages.errors[code]; + } else if (/I\d{3}/.test(code)) { + msg = messages.info[code]; + } + + t = t || state.tokens.next; + if (t.id === "(end)") { // `~ + t = state.tokens.curr; + } + + l = t.line || 0; + ch = t.from || 0; + + w = { + id: "(error)", + raw: msg.desc, + code: msg.code, + evidence: state.lines[l - 1] || "", + line: l, + character: ch, + scope: JSHINT.scope, + a: a, + b: b, + c: c, + d: d + }; + + w.reason = supplant(msg.desc, w); + JSHINT.errors.push(w); + + removeIgnoredMessages(); + + if (JSHINT.errors.length >= state.option.maxerr) + quit("E043", l, ch); + + return w; + } + + function warningAt(m, l, ch, a, b, c, d) { + return warning(m, { + line: l, + from: ch + }, a, b, c, d); + } + + function error(m, t, a, b, c, d) { + warning(m, t, a, b, c, d); + } + + function errorAt(m, l, ch, a, b, c, d) { + return error(m, { + line: l, + from: ch + }, a, b, c, d); + } + function addInternalSrc(elem, src) { + var i; + i = { + id: "(internal)", + elem: elem, + value: src + }; + JSHINT.internals.push(i); + return i; + } + function addlabel(name, opts) { + opts = opts || {}; + + var type = opts.type; + var token = opts.token; + var islet = opts.islet; + if (type === "exception") { + if (_.has(funct["(context)"], name)) { + if (funct[name] !== true && !state.option.node) { + warning("W002", state.tokens.next, name); + } + } + } + + if (_.has(funct, name) && !funct["(global)"]) { + if (funct[name] === true) { + if (state.option.latedef) { + if ((state.option.latedef === true && _.contains([funct[name], type], "unction")) || + !_.contains([funct[name], type], "unction")) { + warning("W003", state.tokens.next, name); + } + } + } else { + if ((!state.option.shadow || _.contains([ "inner", "outer" ], state.option.shadow)) && + type !== "exception" || funct["(blockscope)"].getlabel(name)) { + warning("W004", state.tokens.next, name); + } + } + } + + if (funct["(context)"] && _.has(funct["(context)"], name) && type !== "function") { + if (state.option.shadow === "outer") { + warning("W123", state.tokens.next, name); + } + } + if (islet) { + funct["(blockscope)"].current.add(name, type, state.tokens.curr); + if (funct["(blockscope)"].atTop() && exported[name]) { + state.tokens.curr.exported = true; + } + } else { + funct["(blockscope)"].shadow(name); + funct[name] = type; + + if (token) { + funct["(tokens)"][name] = token; + } + + setprop(funct, name, { unused: opts.unused || false }); + + if (funct["(global)"]) { + global[name] = funct; + if (_.has(implied, name)) { + if (state.option.latedef) { + if ((state.option.latedef === true && _.contains([funct[name], type], "unction")) || + !_.contains([funct[name], type], "unction")) { + warning("W003", state.tokens.next, name); + } + } + + delete implied[name]; + } + } else { + scope[name] = funct; + } + } + } + + function doOption() { + var nt = state.tokens.next; + var body = nt.body.match(/(-\s+)?[^\s,:]+(?:\s*:\s*(-\s+)?[^\s,]+)?/g) || []; + var predef = {}; + + if (nt.type === "globals") { + body.forEach(function (g) { + g = g.split(":"); + var key = (g[0] || "").trim(); + var val = (g[1] || "").trim(); + + if (key.charAt(0) === "-") { + key = key.slice(1); + val = false; + + JSHINT.blacklist[key] = key; + delete predefined[key]; + } else { + predef[key] = (val === "true"); + } + }); + + combine(predefined, predef); + + for (var key in predef) { + if (_.has(predef, key)) { + declared[key] = nt; + } + } + } + + if (nt.type === "exported") { + body.forEach(function (e) { + exported[e] = true; + }); + } + + if (nt.type === "members") { + membersOnly = membersOnly || {}; + + body.forEach(function (m) { + var ch1 = m.charAt(0); + var ch2 = m.charAt(m.length - 1); + + if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) { + m = m + .substr(1, m.length - 2) + .replace("\\\"", "\""); + } + + membersOnly[m] = false; + }); + } + + var numvals = [ + "maxstatements", + "maxparams", + "maxdepth", + "maxcomplexity", + "maxerr", + "maxlen", + "indent" + ]; + + if (nt.type === "jshint" || nt.type === "jslint") { + body.forEach(function (g) { + g = g.split(":"); + var key = (g[0] || "").trim(); + var val = (g[1] || "").trim(); + + if (!checkOption(key, nt)) { + return; + } + + if (numvals.indexOf(key) >= 0) { + if (val !== "false") { + val = +val; + + if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) { + error("E032", nt, g[1].trim()); + return; + } + + state.option[key] = val; + } else { + state.option[key] = key === "indent" ? 4 : false; + } + + return; + } + + if (key === "validthis") { + + if (funct["(global)"]) + return void error("E009"); + + if (val !== "true" && val !== "false") + return void error("E002", nt); + + state.option.validthis = (val === "true"); + return; + } + + if (key === "quotmark") { + switch (val) { + case "true": + case "false": + state.option.quotmark = (val === "true"); + break; + case "double": + case "single": + state.option.quotmark = val; + break; + default: + error("E002", nt); + } + return; + } + + if (key === "shadow") { + switch (val) { + case "true": + state.option.shadow = true; + break; + case "outer": + state.option.shadow = "outer"; + break; + case "false": + case "inner": + state.option.shadow = "inner"; + break; + default: + error("E002", nt); + } + return; + } + + if (key === "unused") { + switch (val) { + case "true": + state.option.unused = true; + break; + case "false": + state.option.unused = false; + break; + case "vars": + case "strict": + state.option.unused = val; + break; + default: + error("E002", nt); + } + return; + } + + if (key === "latedef") { + switch (val) { + case "true": + state.option.latedef = true; + break; + case "false": + state.option.latedef = false; + break; + case "nofunc": + state.option.latedef = "nofunc"; + break; + default: + error("E002", nt); + } + return; + } + + if (key === "ignore") { + switch (val) { + case "start": + state.ignoreLinterErrors = true; + break; + case "end": + state.ignoreLinterErrors = false; + break; + case "line": + state.ignoredLines[nt.line] = true; + removeIgnoredMessages(); + break; + default: + error("E002", nt); + } + return; + } + + var match = /^([+-])(W\d{3})$/g.exec(key); + if (match) { + state.ignored[match[2]] = (match[1] === "-"); + return; + } + + var tn; + if (val === "true" || val === "false") { + if (nt.type === "jslint") { + tn = options.renamed[key] || key; + state.option[tn] = (val === "true"); + + if (options.inverted[tn] !== undefined) { + state.option[tn] = !state.option[tn]; + } + } else { + state.option[key] = (val === "true"); + } + + if (key === "newcap") { + state.option["(explicitNewcap)"] = true; + } + return; + } + + error("E002", nt); + }); + + assume(); + } + } + + function peek(p) { + var i = p || 0, j = 0, t; + + while (j <= i) { + t = lookahead[j]; + if (!t) { + t = lookahead[j] = lex.token(); + } + j += 1; + } + return t; + } + + function peekIgnoreEOL() { + var i = 0; + var t; + do { + t = peek(i++); + } while (t.id === "(endline)"); + return t; + } + + function advance(id, t) { + + switch (state.tokens.curr.id) { + case "(number)": + if (state.tokens.next.id === ".") { + warning("W005", state.tokens.curr); + } + break; + case "-": + if (state.tokens.next.id === "-" || state.tokens.next.id === "--") { + warning("W006"); + } + break; + case "+": + if (state.tokens.next.id === "+" || state.tokens.next.id === "++") { + warning("W007"); + } + break; + } + + if (id && state.tokens.next.id !== id) { + if (t) { + if (state.tokens.next.id === "(end)") { + error("E019", t, t.id); + } else { + error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value); + } + } else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) { + if (state.tokens.next.value === "...") { + if (!state.option.esnext) { + warning("W119", state.tokens.next, "spread/rest operator"); + } + } else { + warning("W116", state.tokens.next, id, state.tokens.next.value); + } + } + } + + state.tokens.prev = state.tokens.curr; + state.tokens.curr = state.tokens.next; + for (;;) { + state.tokens.next = lookahead.shift() || lex.token(); + + if (!state.tokens.next) { // No more tokens left, give up + quit("E041", state.tokens.curr.line); + } + + if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") { + return; + } + + if (state.tokens.next.check) { + state.tokens.next.check(); + } + + if (state.tokens.next.isSpecial) { + doOption(); + } else { + if (state.tokens.next.id !== "(endline)") { + break; + } + } + } + } + + function isInfix(token) { + return token.infix || (!token.identifier && !!token.led); + } + + function isEndOfExpr() { + var curr = state.tokens.curr; + var next = state.tokens.next; + if (next.id === ";" || next.id === "}" || next.id === ":") { + return true; + } + if (isInfix(next) === isInfix(curr) || (curr.id === "yield" && state.option.inMoz(true))) { + return curr.line !== next.line; + } + return false; + } + + function expression(rbp, initial) { + var left, isArray = false, isObject = false, isLetExpr = false, + isFatArrowBody = state.tokens.curr.value === "=>"; + + state.nameStack.push(); + if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") { + if (!state.option.inMoz(true)) { + warning("W118", state.tokens.next, "let expressions"); + } + isLetExpr = true; + funct["(blockscope)"].stack(); + advance("let"); + advance("("); + state.syntax["let"].fud.call(state.syntax["let"].fud, false); + advance(")"); + } + + if (state.tokens.next.id === "(end)") + error("E006", state.tokens.curr); + + if (state.tokens.next.type === "(template)") { + doTemplateLiteral(); + } + + var isDangerous = + state.option.asi && + state.tokens.prev.line < state.tokens.curr.line && + _.contains(["]", ")"], state.tokens.prev.id) && + _.contains(["[", "("], state.tokens.curr.id); + + if (isDangerous) + warning("W014", state.tokens.curr, state.tokens.curr.id); + + advance(); + + if (initial) { + funct["(verb)"] = state.tokens.curr.value; + } + + if (initial === true && state.tokens.curr.fud) { + left = state.tokens.curr.fud(); + } else { + if (state.tokens.curr.nud) { + left = state.tokens.curr.nud(); + } else { + error("E030", state.tokens.curr, state.tokens.curr.id); + } + + while (rbp < state.tokens.next.lbp && !isEndOfExpr()) { + isArray = state.tokens.curr.value === "Array"; + isObject = state.tokens.curr.value === "Object"; + if (left && (left.value || (left.first && left.first.value))) { + if (left.value !== "new" || + (left.first && left.first.value && left.first.value === ".")) { + isArray = false; + if (left.value !== state.tokens.curr.value) { + isObject = false; + } + } + } + + advance(); + + if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") { + warning("W009", state.tokens.curr); + } + + if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") { + warning("W010", state.tokens.curr); + } + + if (left && state.tokens.curr.led) { + left = state.tokens.curr.led(left); + } else { + error("E033", state.tokens.curr, state.tokens.curr.id); + } + } + } + if (isLetExpr) { + funct["(blockscope)"].unstack(); + } + + if (state.option.singleGroups && left && left.paren && !left.exprs && + !isFatArrowBody && !left.triggerFnExpr) { + warning("W126"); + } + + state.nameStack.pop(); + + return left; + } + + function nobreaknonadjacent(left, right) { + left = left || state.tokens.curr; + right = right || state.tokens.next; + if (!state.option.laxbreak && left.line !== right.line) { + warning("W014", right, right.value); + } + } + + function nolinebreak(t) { + t = t || state.tokens.curr; + if (t.line !== state.tokens.next.line) { + warning("E022", t, t.value); + } + } + + function nobreakcomma(left, right) { + if (left.line !== right.line) { + if (!state.option.laxcomma) { + if (comma.first) { + warning("I001"); + comma.first = false; + } + warning("W014", left, right.value); + } + } + } + + function comma(opts) { + opts = opts || {}; + + if (state.option.nocomma) { + warning("W127"); + } + + if (!opts.peek) { + nobreakcomma(state.tokens.curr, state.tokens.next); + advance(","); + } else { + nobreakcomma(state.tokens.prev, state.tokens.curr); + } + + if (state.tokens.next.identifier && !(opts.property && state.option.inES5())) { + switch (state.tokens.next.value) { + case "break": + case "case": + case "catch": + case "continue": + case "default": + case "do": + case "else": + case "finally": + case "for": + case "if": + case "in": + case "instanceof": + case "return": + case "switch": + case "throw": + case "try": + case "var": + case "let": + case "while": + case "with": + error("E024", state.tokens.next, state.tokens.next.value); + return false; + } + } + + if (state.tokens.next.type === "(punctuator)") { + switch (state.tokens.next.value) { + case "}": + case "]": + case ",": + if (opts.allowTrailing) { + return true; + } + case ")": + error("E024", state.tokens.next, state.tokens.next.value); + return false; + } + } + return true; + } + + function symbol(s, p) { + var x = state.syntax[s]; + if (!x || typeof x !== "object") { + state.syntax[s] = x = { + id: s, + lbp: p, + value: s + }; + } + return x; + } + + function delim(s) { + return symbol(s, 0); + } + + function stmt(s, f) { + var x = delim(s); + x.identifier = x.reserved = true; + x.fud = f; + return x; + } + + function blockstmt(s, f) { + var x = stmt(s, f); + x.block = true; + return x; + } + + function reserveName(x) { + var c = x.id.charAt(0); + if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) { + x.identifier = x.reserved = true; + } + return x; + } + + function prefix(s, f) { + var x = symbol(s, 150); + reserveName(x); + + x.nud = (typeof f === "function") ? f : function () { + this.right = expression(150); + this.arity = "unary"; + + if (this.id === "++" || this.id === "--") { + if (state.option.plusplus) { + warning("W016", this, this.id); + } else if (this.right && (!this.right.identifier || isReserved(this.right)) && + this.right.id !== "." && this.right.id !== "[") { + warning("W017", this); + } + } + + return this; + }; + + return x; + } + + function type(s, f) { + var x = delim(s); + x.type = s; + x.nud = f; + return x; + } + + function reserve(name, func) { + var x = type(name, func); + x.identifier = true; + x.reserved = true; + return x; + } + + function FutureReservedWord(name, meta) { + var x = type(name, (meta && meta.nud) || function () { + return this; + }); + + meta = meta || {}; + meta.isFutureReservedWord = true; + + x.value = name; + x.identifier = true; + x.reserved = true; + x.meta = meta; + + return x; + } + + function reservevar(s, v) { + return reserve(s, function () { + if (typeof v === "function") { + v(this); + } + return this; + }); + } + + function infix(s, f, p, w) { + var x = symbol(s, p); + reserveName(x); + x.infix = true; + x.led = function (left) { + if (!w) { + nobreaknonadjacent(state.tokens.prev, state.tokens.curr); + } + if (s === "in" && left.id === "!") { + warning("W018", left, "!"); + } + if (typeof f === "function") { + return f(left, this); + } else { + this.left = left; + this.right = expression(p); + return this; + } + }; + return x; + } + + + function application(s) { + var x = symbol(s, 42); + + x.led = function (left) { + nobreaknonadjacent(state.tokens.prev, state.tokens.curr); + + this.left = left; + this.right = doFunction(undefined, undefined, false, { loneArg: left }); + return this; + }; + return x; + } + + function relation(s, f) { + var x = symbol(s, 100); + + x.led = function (left) { + nobreaknonadjacent(state.tokens.prev, state.tokens.curr); + var right = expression(100); + + if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) { + warning("W019", this); + } else if (f) { + f.apply(this, [left, right]); + } + + if (!left || !right) { + quit("E041", state.tokens.curr.line); + } + + if (left.id === "!") { + warning("W018", left, "!"); + } + + if (right.id === "!") { + warning("W018", right, "!"); + } + + this.left = left; + this.right = right; + return this; + }; + return x; + } + + function isPoorRelation(node) { + return node && + ((node.type === "(number)" && +node.value === 0) || + (node.type === "(string)" && node.value === "") || + (node.type === "null" && !state.option.eqnull) || + node.type === "true" || + node.type === "false" || + node.type === "undefined"); + } + + function isTypoTypeof(left, right) { + if (state.option.notypeof) + return false; + + if (!left || !right) + return false; + + var values = [ + "undefined", "object", "boolean", "number", + "string", "function", "xml", "object", "unknown" + ]; + + if (right.type === "(identifier)" && right.value === "typeof" && left.type === "(string)") + return !_.contains(values, left.value); + + return false; + } + + function findNativePrototype(left) { + var natives = [ + "Array", "ArrayBuffer", "Boolean", "Collator", "DataView", "Date", + "DateTimeFormat", "Error", "EvalError", "Float32Array", "Float64Array", + "Function", "Infinity", "Intl", "Int16Array", "Int32Array", "Int8Array", + "Iterator", "Number", "NumberFormat", "Object", "RangeError", + "ReferenceError", "RegExp", "StopIteration", "String", "SyntaxError", + "TypeError", "Uint16Array", "Uint32Array", "Uint8Array", "Uint8ClampedArray", + "URIError" + ]; + + function walkPrototype(obj) { + if (typeof obj !== "object") return; + return obj.right === "prototype" ? obj : walkPrototype(obj.left); + } + + function walkNative(obj) { + while (!obj.identifier && typeof obj.left === "object") + obj = obj.left; + + if (obj.identifier && natives.indexOf(obj.value) >= 0) + return obj.value; + } + + var prototype = walkPrototype(left); + if (prototype) return walkNative(prototype); + } + + function assignop(s, f, p) { + var x = infix(s, typeof f === "function" ? f : function (left, that) { + that.left = left; + + if (left) { + if (state.option.freeze) { + var nativeObject = findNativePrototype(left); + if (nativeObject) + warning("W121", left, nativeObject); + } + + if (predefined[left.value] === false && + scope[left.value]["(global)"] === true) { + warning("W020", left); + } else if (left["function"]) { + warning("W021", left, left.value); + } + + if (funct[left.value] === "const") { + error("E013", left, left.value); + } + + if (left.id === ".") { + if (!left.left) { + warning("E031", that); + } else if (left.left.value === "arguments" && !state.directive["use strict"]) { + warning("E031", that); + } + + state.nameStack.set(state.tokens.prev); + that.right = expression(10); + return that; + } else if (left.id === "[") { + if (state.tokens.curr.left.first) { + state.tokens.curr.left.first.forEach(function (t) { + if (t && funct[t.value] === "const") { + error("E013", t, t.value); + } + }); + } else if (!left.left) { + warning("E031", that); + } else if (left.left.value === "arguments" && !state.directive["use strict"]) { + warning("E031", that); + } + + state.nameStack.set(left.right); + + that.right = expression(10); + return that; + } else if (left.identifier && !isReserved(left)) { + if (funct[left.value] === "exception") { + warning("W022", left); + } + state.nameStack.set(left); + that.right = expression(10); + return that; + } + + if (left === state.syntax["function"]) { + warning("W023", state.tokens.curr); + } + } + + error("E031", that); + }, p); + + x.exps = true; + x.assign = true; + return x; + } + + + function bitwise(s, f, p) { + var x = symbol(s, p); + reserveName(x); + x.led = (typeof f === "function") ? f : function (left) { + if (state.option.bitwise) { + warning("W016", this, this.id); + } + this.left = left; + this.right = expression(p); + return this; + }; + return x; + } + + + function bitwiseassignop(s) { + return assignop(s, function (left, that) { + if (state.option.bitwise) { + warning("W016", that, that.id); + } + + if (left) { + if (left.id === "." || left.id === "[" || + (left.identifier && !isReserved(left))) { + expression(10); + return that; + } + if (left === state.syntax["function"]) { + warning("W023", state.tokens.curr); + } + return that; + } + error("E031", that); + }, 20); + } + + + function suffix(s) { + var x = symbol(s, 150); + + x.led = function (left) { + if (state.option.plusplus) { + warning("W016", this, this.id); + } else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") { + warning("W017", this); + } + + this.left = left; + return this; + }; + return x; + } + + function optionalidentifier(fnparam, prop, preserve, exported) { + if (!state.tokens.next.identifier) { + return; + } + + if (!preserve) { + advance(); + } + + var curr = state.tokens.curr; + var val = state.tokens.curr.value; + + if (exported) { + state.tokens.curr.exported = true; + } + + if (!isReserved(curr)) { + return val; + } + + if (prop) { + if (state.option.inES5()) { + return val; + } + } + + if (fnparam && val === "undefined") { + return val; + } + + warning("W024", state.tokens.curr, state.tokens.curr.id); + return val; + } + function identifier(fnparam, prop, exported) { + var i = optionalidentifier(fnparam, prop, false, exported); + if (i) { + return i; + } + if (state.tokens.next.value === "...") { + if (!state.option.esnext) { + warning("W119", state.tokens.next, "spread/rest operator"); + } + } else { + error("E030", state.tokens.next, state.tokens.next.value); + if (state.tokens.next.id !== ";") { + advance(); + } + } + } + + + function reachable(controlToken) { + var i = 0, t; + if (state.tokens.next.id !== ";" || controlToken.inBracelessBlock) { + return; + } + for (;;) { + do { + t = peek(i); + i += 1; + } while (t.id != "(end)" && t.id === "(comment)"); + + if (t.reach) { + return; + } + if (t.id !== "(endline)") { + if (t.id === "function") { + if (state.option.latedef === true) { + warning("W026", t); + } + break; + } + + warning("W027", t, t.value, controlToken.value); + break; + } + } + } + + function parseFinalSemicolon() { + if (state.tokens.next.id !== ";") { + if (!state.option.asi) { + if (!state.option.lastsemic || state.tokens.next.id !== "}" || + state.tokens.next.line !== state.tokens.curr.line) { + warningAt("W033", state.tokens.curr.line, state.tokens.curr.character); + } + } + } else { + advance(";"); + } + } + + function statement() { + var values; + var i = indent, r, s = scope, t = state.tokens.next; + + if (t.id === ";") { + advance(";"); + return; + } + var res = isReserved(t); + + if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") { + warning("W024", t, t.id); + res = false; + } + if (t.value === "module" && t.type === "(identifier)") { + if (peek().type === "(identifier)") { + if (!state.option.inESNext()) { + warning("W119", state.tokens.curr, "module"); + } + + advance("module"); + var name = identifier(); + addlabel(name, { type: "unused", token: state.tokens.curr }); + advance("from"); + advance("(string)"); + parseFinalSemicolon(); + return; + } + } + if (_.has(["[", "{"], t.value)) { + if (lookupBlockType().isDestAssign) { + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "destructuring expression"); + } + values = destructuringExpression(); + values.forEach(function (tok) { + isundef(funct, "W117", tok.token, tok.id); + }); + advance("="); + destructuringExpressionMatch(values, expression(10, true)); + advance(";"); + return; + } + } + if (t.identifier && !res && peek().id === ":") { + advance(); + advance(":"); + scope = Object.create(s); + addlabel(t.value, { type: "label" }); + + if (!state.tokens.next.labelled && state.tokens.next.value !== "{") { + warning("W028", state.tokens.next, t.value, state.tokens.next.value); + } + + state.tokens.next.label = t.value; + t = state.tokens.next; + } + + if (t.id === "{") { + var iscase = (funct["(verb)"] === "case" && state.tokens.curr.value === ":"); + block(true, true, false, false, iscase); + return; + } + + r = expression(0, true); + + if (r && (!r.identifier || r.value !== "function") && (r.type !== "(punctuator)")) { + if (!state.directive["use strict"] && + state.option.globalstrict && + state.option.strict) { + warning("E007"); + } + } + + if (!t.block) { + if (!state.option.expr && (!r || !r.exps)) { + warning("W030", state.tokens.curr); + } else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") { + warning("W031", t); + } + parseFinalSemicolon(); + } + + indent = i; + scope = s; + return r; + } + + + function statements() { + var a = [], p; + + while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") { + if (state.tokens.next.id === ";") { + p = peek(); + + if (!p || (p.id !== "(" && p.id !== "[")) { + warning("W032"); + } + + advance(";"); + } else { + a.push(statement()); + } + } + return a; + } + function directives() { + var i, p, pn; + + while (state.tokens.next.id === "(string)") { + p = peek(0); + if (p.id === "(endline)") { + i = 1; + do { + pn = peek(i++); + } while (pn.id === "(endline)"); + if (pn.id === ";") { + p = pn; + } else if (pn.value === "[" || pn.value === ".") { + return; + } else if (!state.option.asi || pn.value === "(") { + warning("W033", state.tokens.next); + } + } else if (p.id === "." || p.id === "[") { + return; + } else if (p.id !== ";") { + warning("W033", p); + } + + advance(); + if (state.directive[state.tokens.curr.value]) { + warning("W034", state.tokens.curr, state.tokens.curr.value); + } + + if (state.tokens.curr.value === "use strict") { + if (!state.option["(explicitNewcap)"]) { + state.option.newcap = true; + } + state.option.undef = true; + } + state.directive[state.tokens.curr.value] = true; + + if (p.id === ";") { + advance(";"); + } + } + } + function block(ordinary, stmt, isfunc, isfatarrow, iscase) { + var a, + b = inblock, + old_indent = indent, + m, + s = scope, + t, + line, + d; + + inblock = ordinary; + + if (!ordinary || !state.option.funcscope) + scope = Object.create(scope); + + t = state.tokens.next; + + var metrics = funct["(metrics)"]; + metrics.nestedBlockDepth += 1; + metrics.verifyMaxNestedBlockDepthPerFunction(); + + if (state.tokens.next.id === "{") { + advance("{"); + funct["(blockscope)"].stack(); + + line = state.tokens.curr.line; + if (state.tokens.next.id !== "}") { + indent += state.option.indent; + while (!ordinary && state.tokens.next.from > indent) { + indent += state.option.indent; + } + + if (isfunc) { + m = {}; + for (d in state.directive) { + if (_.has(state.directive, d)) { + m[d] = state.directive[d]; + } + } + directives(); + + if (state.option.strict && funct["(context)"]["(global)"]) { + if (!m["use strict"] && !state.directive["use strict"]) { + warning("E007"); + } + } + } + + a = statements(); + + metrics.statementCount += a.length; + + if (isfunc) { + state.directive = m; + } + + indent -= state.option.indent; + } + + advance("}", t); + + funct["(blockscope)"].unstack(); + + indent = old_indent; + } else if (!ordinary) { + if (isfunc) { + m = {}; + if (stmt && !isfatarrow && !state.option.inMoz(true)) { + error("W118", state.tokens.curr, "function closure expressions"); + } + + if (!stmt) { + for (d in state.directive) { + if (_.has(state.directive, d)) { + m[d] = state.directive[d]; + } + } + } + expression(10); + + if (state.option.strict && funct["(context)"]["(global)"]) { + if (!m["use strict"] && !state.directive["use strict"]) { + warning("E007"); + } + } + } else { + error("E021", state.tokens.next, "{", state.tokens.next.value); + } + } else { + funct["(nolet)"] = true; + + if (!stmt || state.option.curly) { + warning("W116", state.tokens.next, "{", state.tokens.next.value); + } + + state.tokens.next.inBracelessBlock = true; + indent += state.option.indent; + a = [statement()]; + indent -= state.option.indent; + + delete funct["(nolet)"]; + } + switch (funct["(verb)"]) { + case "break": + case "continue": + case "return": + case "throw": + if (iscase) { + break; + } + default: + funct["(verb)"] = null; + } + + if (!ordinary || !state.option.funcscope) scope = s; + inblock = b; + if (ordinary && state.option.noempty && (!a || a.length === 0)) { + warning("W035", state.tokens.prev); + } + metrics.nestedBlockDepth -= 1; + return a; + } + + + function countMember(m) { + if (membersOnly && typeof membersOnly[m] !== "boolean") { + warning("W036", state.tokens.curr, m); + } + if (typeof member[m] === "number") { + member[m] += 1; + } else { + member[m] = 1; + } + } + + + function note_implied(tkn) { + var name = tkn.value; + var desc = Object.getOwnPropertyDescriptor(implied, name); + + if (!desc) + implied[name] = [tkn.line]; + else + desc.value.push(tkn.line); + } + + type("(number)", function () { + return this; + }); + + type("(string)", function () { + return this; + }); + + state.syntax["(identifier)"] = { + type: "(identifier)", + lbp: 0, + identifier: true, + + nud: function () { + var v = this.value; + var s = scope[v]; + var f; + var block; + if (state.tokens.next.id === "=>") { + return this; + } + + if (typeof s === "function") { + s = undefined; + } else if (!funct["(blockscope)"].current.has(v) && typeof s === "boolean") { + f = funct; + funct = functions[0]; + addlabel(v, { type: "var" }); + s = funct; + funct = f; + } + + block = funct["(blockscope)"].getlabel(v); + if (funct === s || block) { + switch (block ? block[v]["(type)"] : funct[v]) { + case "unused": + if (block) block[v]["(type)"] = "var"; + else funct[v] = "var"; + break; + case "unction": + if (block) block[v]["(type)"] = "function"; + else funct[v] = "function"; + this["function"] = true; + break; + case "const": + setprop(funct, v, { unused: false }); + break; + case "function": + this["function"] = true; + break; + case "label": + warning("W037", state.tokens.curr, v); + break; + } + } else { + + switch (funct[v]) { + case "closure": + case "function": + case "var": + case "unused": + warning("W038", state.tokens.curr, v); + break; + case "label": + warning("W037", state.tokens.curr, v); + break; + case "outer": + case "global": + break; + default: + if (s === true) { + funct[v] = true; + } else if (s === null) { + warning("W039", state.tokens.curr, v); + note_implied(state.tokens.curr); + } else if (typeof s !== "object") { + + if (!funct["(comparray)"].check(v)) { + isundef(funct, "W117", state.tokens.curr, v); + } + if (!funct["(global)"]) { + funct[v] = true; + } + + note_implied(state.tokens.curr); + } else { + switch (s[v]) { + case "function": + case "unction": + this["function"] = true; + s[v] = "closure"; + funct[v] = s["(global)"] ? "global" : "outer"; + break; + case "var": + case "unused": + s[v] = "closure"; + funct[v] = s["(global)"] ? "global" : "outer"; + break; + case "const": + setprop(s, v, { unused: false }); + break; + case "closure": + funct[v] = s["(global)"] ? "global" : "outer"; + break; + case "label": + warning("W037", state.tokens.curr, v); + } + } + } + } + return this; + }, + + led: function () { + error("E033", state.tokens.next, state.tokens.next.value); + } + }; + + state.syntax["(template)"] = { + type: "(template)", + lbp: 0, + identifier: false, + fud: doTemplateLiteral + }; + + type("(template middle)", function () { + return this; + }); + + type("(template tail)", function () { + return this; + }); + + type("(regexp)", function () { + return this; + }); + + delim("(endline)"); + delim("(begin)"); + delim("(end)").reach = true; + delim("(error)").reach = true; + delim("}").reach = true; + delim(")"); + delim("]"); + delim("\"").reach = true; + delim("'").reach = true; + delim(";"); + delim(":").reach = true; + delim("#"); + + reserve("else"); + reserve("case").reach = true; + reserve("catch"); + reserve("default").reach = true; + reserve("finally"); + reservevar("arguments", function (x) { + if (state.directive["use strict"] && funct["(global)"]) { + warning("E008", x); + } + }); + reservevar("eval"); + reservevar("false"); + reservevar("Infinity"); + reservevar("null"); + reservevar("this", function (x) { + if (state.directive["use strict"] && !isMethod() && + !state.option.validthis && ((funct["(statement)"] && + funct["(name)"].charAt(0) > "Z") || funct["(global)"])) { + warning("W040", x); + } + }); + reservevar("true"); + reservevar("undefined"); + + assignop("=", "assign", 20); + assignop("+=", "assignadd", 20); + assignop("-=", "assignsub", 20); + assignop("*=", "assignmult", 20); + assignop("/=", "assigndiv", 20).nud = function () { + error("E014"); + }; + assignop("%=", "assignmod", 20); + + bitwiseassignop("&="); + bitwiseassignop("|="); + bitwiseassignop("^="); + bitwiseassignop("<<="); + bitwiseassignop(">>="); + bitwiseassignop(">>>="); + infix(",", function (left, that) { + var expr; + that.exprs = [left]; + if (!comma({peek: true})) { + return that; + } + while (true) { + if (!(expr = expression(10))) { + break; + } + that.exprs.push(expr); + if (state.tokens.next.value !== "," || !comma()) { + break; + } + } + return that; + }, 10, true); + + infix("?", function (left, that) { + increaseComplexityCount(); + that.left = left; + that.right = expression(10); + advance(":"); + that["else"] = expression(10); + return that; + }, 30); + + var orPrecendence = 40; + infix("||", function (left, that) { + increaseComplexityCount(); + that.left = left; + that.right = expression(orPrecendence); + return that; + }, orPrecendence); + infix("&&", "and", 50); + bitwise("|", "bitor", 70); + bitwise("^", "bitxor", 80); + bitwise("&", "bitand", 90); + relation("==", function (left, right) { + var eqnull = state.option.eqnull && (left.value === "null" || right.value === "null"); + + switch (true) { + case !eqnull && state.option.eqeqeq: + this.from = this.character; + warning("W116", this, "===", "=="); + break; + case isPoorRelation(left): + warning("W041", this, "===", left.value); + break; + case isPoorRelation(right): + warning("W041", this, "===", right.value); + break; + case isTypoTypeof(right, left): + warning("W122", this, right.value); + break; + case isTypoTypeof(left, right): + warning("W122", this, left.value); + break; + } + + return this; + }); + relation("===", function (left, right) { + if (isTypoTypeof(right, left)) { + warning("W122", this, right.value); + } else if (isTypoTypeof(left, right)) { + warning("W122", this, left.value); + } + return this; + }); + relation("!=", function (left, right) { + var eqnull = state.option.eqnull && + (left.value === "null" || right.value === "null"); + + if (!eqnull && state.option.eqeqeq) { + this.from = this.character; + warning("W116", this, "!==", "!="); + } else if (isPoorRelation(left)) { + warning("W041", this, "!==", left.value); + } else if (isPoorRelation(right)) { + warning("W041", this, "!==", right.value); + } else if (isTypoTypeof(right, left)) { + warning("W122", this, right.value); + } else if (isTypoTypeof(left, right)) { + warning("W122", this, left.value); + } + return this; + }); + relation("!==", function (left, right) { + if (isTypoTypeof(right, left)) { + warning("W122", this, right.value); + } else if (isTypoTypeof(left, right)) { + warning("W122", this, left.value); + } + return this; + }); + relation("<"); + relation(">"); + relation("<="); + relation(">="); + bitwise("<<", "shiftleft", 120); + bitwise(">>", "shiftright", 120); + bitwise(">>>", "shiftrightunsigned", 120); + infix("in", "in", 120); + infix("instanceof", "instanceof", 120); + infix("+", function (left, that) { + var right = expression(130); + if (left && right && left.id === "(string)" && right.id === "(string)") { + left.value += right.value; + left.character = right.character; + if (!state.option.scripturl && reg.javascriptURL.test(left.value)) { + warning("W050", left); + } + return left; + } + that.left = left; + that.right = right; + return that; + }, 130); + prefix("+", "num"); + prefix("+++", function () { + warning("W007"); + this.right = expression(150); + this.arity = "unary"; + return this; + }); + infix("+++", function (left) { + warning("W007"); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix("-", "sub", 130); + prefix("-", "neg"); + prefix("---", function () { + warning("W006"); + this.right = expression(150); + this.arity = "unary"; + return this; + }); + infix("---", function (left) { + warning("W006"); + this.left = left; + this.right = expression(130); + return this; + }, 130); + infix("*", "mult", 140); + infix("/", "div", 140); + infix("%", "mod", 140); + + suffix("++"); + prefix("++", "preinc"); + state.syntax["++"].exps = true; + + suffix("--"); + prefix("--", "predec"); + state.syntax["--"].exps = true; + prefix("delete", function () { + var p = expression(10); + if (!p || (p.id !== "." && p.id !== "[")) { + warning("W051"); + } + this.first = p; + if (p.identifier && !state.directive["use strict"]) { + p.forgiveUndef = true; + } + return this; + }).exps = true; + + prefix("~", function () { + if (state.option.bitwise) { + warning("W052", this, "~"); + } + expression(150); + return this; + }); + + prefix("...", function () { + if (!state.option.esnext) { + warning("W119", this, "spread/rest operator"); + } + if (!state.tokens.next.identifier) { + error("E030", state.tokens.next, state.tokens.next.value); + } + expression(150); + return this; + }); + + prefix("!", function () { + this.right = expression(150); + this.arity = "unary"; + + if (!this.right) { // '!' followed by nothing? Give up. + quit("E041", this.line || 0); + } + + if (bang[this.right.id] === true) { + warning("W018", this, "!"); + } + return this; + }); + + prefix("typeof", (function () { + var p = expression(150); + this.first = p; + if (p.identifier) { + p.forgiveUndef = true; + } + return this; + })); + prefix("new", function () { + var c = expression(155), i; + if (c && c.id !== "function") { + if (c.identifier) { + c["new"] = true; + switch (c.value) { + case "Number": + case "String": + case "Boolean": + case "Math": + case "JSON": + warning("W053", state.tokens.prev, c.value); + break; + case "Symbol": + if (state.option.esnext) { + warning("W053", state.tokens.prev, c.value); + } + break; + case "Function": + if (!state.option.evil) { + warning("W054"); + } + break; + case "Date": + case "RegExp": + case "this": + break; + default: + if (c.id !== "function") { + i = c.value.substr(0, 1); + if (state.option.newcap && (i < "A" || i > "Z") && !_.has(global, c.value)) { + warning("W055", state.tokens.curr); + } + } + } + } else { + if (c.id !== "." && c.id !== "[" && c.id !== "(") { + warning("W056", state.tokens.curr); + } + } + } else { + if (!state.option.supernew) + warning("W057", this); + } + if (state.tokens.next.id !== "(" && !state.option.supernew) { + warning("W058", state.tokens.curr, state.tokens.curr.value); + } + this.first = c; + return this; + }); + state.syntax["new"].exps = true; + + prefix("void").exps = true; + + infix(".", function (left, that) { + var m = identifier(false, true); + + if (typeof m === "string") { + countMember(m); + } + + that.left = left; + that.right = m; + + if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") { + warning("W001"); + } + + if (left && left.value === "arguments" && (m === "callee" || m === "caller")) { + if (state.option.noarg) + warning("W059", left, m); + else if (state.directive["use strict"]) + error("E008"); + } else if (!state.option.evil && left && left.value === "document" && + (m === "write" || m === "writeln")) { + warning("W060", left); + } + + if (!state.option.evil && (m === "eval" || m === "execScript")) { + warning("W061"); + } + + return that; + }, 160, true); + + infix("(", function (left, that) { + if (state.option.immed && left && !left.immed && left.id === "function") { + warning("W062"); + } + + var n = 0; + var p = []; + + if (left) { + if (left.type === "(identifier)") { + if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) { + if ("Number String Boolean Date Object Error Symbol".indexOf(left.value) === -1) { + if (left.value === "Math") { + warning("W063", left); + } else if (state.option.newcap) { + warning("W064", left); + } + } + } + } + } + + if (state.tokens.next.id !== ")") { + for (;;) { + p[p.length] = expression(10); + n += 1; + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + } + + advance(")"); + + if (typeof left === "object") { + if (state.option.inES3() && left.value === "parseInt" && n === 1) { + warning("W065", state.tokens.curr); + } + if (!state.option.evil) { + if (left.value === "eval" || left.value === "Function" || + left.value === "execScript") { + warning("W061", left); + + if (p[0] && [0].id === "(string)") { + addInternalSrc(left, p[0].value); + } + } else if (p[0] && p[0].id === "(string)" && + (left.value === "setTimeout" || + left.value === "setInterval")) { + warning("W066", left); + addInternalSrc(left, p[0].value); + } else if (p[0] && p[0].id === "(string)" && + left.value === "." && + left.left.value === "window" && + (left.right === "setTimeout" || + left.right === "setInterval")) { + warning("W066", left); + addInternalSrc(left, p[0].value); + } + } + if (!left.identifier && left.id !== "." && left.id !== "[" && + left.id !== "(" && left.id !== "&&" && left.id !== "||" && + left.id !== "?" && !(state.option.esnext && left["(name)"])) { + warning("W067", that); + } + } + + that.left = left; + return that; + }, 155, true).exps = true; + + prefix("(", function () { + var bracket, brackets = []; + var pn = state.tokens.next, pn1, i = -1; + var ret, triggerFnExpr; + var parens = 1; + + do { + if (pn.value === "(") { + parens += 1; + } else if (pn.value === ")") { + parens -= 1; + } + + i += 1; + pn1 = pn; + pn = peek(i); + } while (!(parens === 0 && pn1.value === ")") && + pn.value !== ";" && pn.type !== "(end)"); + + if (state.tokens.next.id === "function") { + triggerFnExpr = state.tokens.next.immed = true; + } + if (pn.value === "=>") { + return doFunction(null, null, null, { parsedParen: true }); + } + + var exprs = []; + + if (state.tokens.next.id !== ")") { + for (;;) { + if (pn.value === "=>" && _.contains(["{", "["], state.tokens.next.value)) { + bracket = state.tokens.next; + bracket.left = destructuringExpression(); + brackets.push(bracket); + for (var t in bracket.left) { + exprs.push(bracket.left[t].token); + } + } else { + exprs.push(expression(10)); + } + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + } + + advance(")", this); + if (state.option.immed && exprs[0] && exprs[0].id === "function") { + if (state.tokens.next.id !== "(" && + state.tokens.next.id !== "." && state.tokens.next.id !== "[") { + warning("W068", this); + } + } + + if (state.tokens.next.value === "=>") { + return exprs; + } + if (!exprs.length) { + return; + } + if (exprs.length > 1) { + ret = Object.create(state.syntax[","]); + ret.exprs = exprs; + } else { + ret = exprs[0]; + } + if (ret) { + ret.paren = true; + ret.triggerFnExpr = triggerFnExpr; + } + return ret; + }); + + application("=>"); + + infix("[", function (left, that) { + var e = expression(10), s; + if (e && e.type === "(string)") { + if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) { + warning("W061", that); + } + + countMember(e.value); + if (!state.option.sub && reg.identifier.test(e.value)) { + s = state.syntax[e.value]; + if (!s || !isReserved(s)) { + warning("W069", state.tokens.prev, e.value); + } + } + } + advance("]", that); + + if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") { + warning("W001"); + } + + that.left = left; + that.right = e; + return that; + }, 160, true); + + function comprehensiveArrayExpression() { + var res = {}; + res.exps = true; + funct["(comparray)"].stack(); + var reversed = false; + if (state.tokens.next.value !== "for") { + reversed = true; + if (!state.option.inMoz(true)) { + warning("W116", state.tokens.next, "for", state.tokens.next.value); + } + funct["(comparray)"].setState("use"); + res.right = expression(10); + } + + advance("for"); + if (state.tokens.next.value === "each") { + advance("each"); + if (!state.option.inMoz(true)) { + warning("W118", state.tokens.curr, "for each"); + } + } + advance("("); + funct["(comparray)"].setState("define"); + res.left = expression(130); + if (_.contains(["in", "of"], state.tokens.next.value)) { + advance(); + } else { + error("E045", state.tokens.curr); + } + funct["(comparray)"].setState("generate"); + expression(10); + + advance(")"); + if (state.tokens.next.value === "if") { + advance("if"); + advance("("); + funct["(comparray)"].setState("filter"); + res.filter = expression(10); + advance(")"); + } + + if (!reversed) { + funct["(comparray)"].setState("use"); + res.right = expression(10); + } + + advance("]"); + funct["(comparray)"].unstack(); + return res; + } + + prefix("[", function () { + var blocktype = lookupBlockType(); + if (blocktype.isCompArray) { + if (!state.option.inESNext()) { + warning("W119", state.tokens.curr, "array comprehension"); + } + return comprehensiveArrayExpression(); + } else if (blocktype.isDestAssign && !state.option.inESNext()) { + warning("W104", state.tokens.curr, "destructuring assignment"); + } + var b = state.tokens.curr.line !== state.tokens.next.line; + this.first = []; + if (b) { + indent += state.option.indent; + if (state.tokens.next.from === indent + state.option.indent) { + indent += state.option.indent; + } + } + while (state.tokens.next.id !== "(end)") { + while (state.tokens.next.id === ",") { + if (!state.option.elision) { + if (!state.option.inES5()) { + warning("W070"); + } else { + warning("W128"); + do { + advance(","); + } while(state.tokens.next.id === ","); + continue; + } + } + advance(","); + } + + if (state.tokens.next.id === "]") { + break; + } + + this.first.push(expression(10)); + if (state.tokens.next.id === ",") { + comma({ allowTrailing: true }); + if (state.tokens.next.id === "]" && !state.option.inES5(true)) { + warning("W070", state.tokens.curr); + break; + } + } else { + break; + } + } + if (b) { + indent -= state.option.indent; + } + advance("]", this); + return this; + }); + + + function isMethod() { + return funct["(statement)"] && funct["(statement)"].type === "class" || + funct["(context)"] && funct["(context)"]["(verb)"] === "class"; + } + + + function isPropertyName(token) { + return token.identifier || token.id === "(string)" || token.id === "(number)"; + } + + + function propertyName(preserveOrToken) { + var id; + var preserve = true; + if (typeof preserveOrToken === "object") { + id = preserveOrToken; + } else { + preserve = preserveOrToken; + id = optionalidentifier(false, true, preserve); + } + + if (!id) { + if (state.tokens.next.id === "(string)") { + id = state.tokens.next.value; + if (!preserve) { + advance(); + } + } else if (state.tokens.next.id === "(number)") { + id = state.tokens.next.value.toString(); + if (!preserve) { + advance(); + } + } + } else if (typeof id === "object") { + if (id.id === "(string)" || id.id === "(identifier)") id = id.value; + else if (id.id === "(number)") id = id.value.toString(); + } + + if (id === "hasOwnProperty") { + warning("W001"); + } + + return id; + } + + function functionparams(fatarrow) { + var next; + var params = []; + var ident; + var tokens = []; + var t; + var pastDefault = false; + var loneArg = fatarrow && fatarrow.loneArg; + + if (loneArg && loneArg.identifier === true) { + addlabel(loneArg.value, { type: "unused", token: loneArg }); + return [loneArg]; + } + + next = state.tokens.next; + + if (!fatarrow || !fatarrow.parsedParen) { + advance("("); + } + + if (state.tokens.next.id === ")") { + advance(")"); + return; + } + + for (;;) { + if (_.contains(["{", "["], state.tokens.next.id)) { + tokens = destructuringExpression(); + for (t in tokens) { + t = tokens[t]; + if (t.id) { + params.push(t.id); + addlabel(t.id, { type: "unused", token: t.token }); + } + } + } else if (state.tokens.next.value === "...") { + if (!state.option.esnext) { + warning("W119", state.tokens.next, "spread/rest operator"); + } + advance("..."); + ident = identifier(true); + params.push(ident); + addlabel(ident, { type: "unused", token: state.tokens.curr }); + } else { + ident = identifier(true); + params.push(ident); + addlabel(ident, { type: "unused", token: state.tokens.curr }); + } + if (pastDefault) { + if (state.tokens.next.id !== "=") { + error("E051", state.tokens.current); + } + } + if (state.tokens.next.id === "=") { + if (!state.option.inESNext()) { + warning("W119", state.tokens.next, "default parameters"); + } + advance("="); + pastDefault = true; + expression(10); + } + if (state.tokens.next.id === ",") { + comma(); + } else { + advance(")", next); + return params; + } + } + } + + function setprop(funct, name, values) { + if (!funct["(properties)"][name]) { + funct["(properties)"][name] = { unused: false }; + } + + _.extend(funct["(properties)"][name], values); + } + + function getprop(funct, name, prop) { + if (!funct["(properties)"][name]) + return null; + + return funct["(properties)"][name][prop] || null; + } + + function functor(name, token, scope, overwrites) { + var funct = { + "(name)" : name, + "(breakage)" : 0, + "(loopage)" : 0, + "(scope)" : scope, + "(tokens)" : {}, + "(properties)": {}, + + "(catch)" : false, + "(global)" : false, + + "(line)" : null, + "(character)" : null, + "(metrics)" : null, + "(statement)" : null, + "(context)" : null, + "(blockscope)": null, + "(comparray)" : null, + "(generator)" : null, + "(params)" : null + }; + + if (token) { + _.extend(funct, { + "(line)" : token.line, + "(character)": token.character, + "(metrics)" : createMetrics(token) + }); + } + + _.extend(funct, overwrites); + + if (funct["(context)"]) { + funct["(blockscope)"] = funct["(context)"]["(blockscope)"]; + funct["(comparray)"] = funct["(context)"]["(comparray)"]; + } + + return funct; + } + + function doTemplateLiteral() { + while (state.tokens.next.type !== "(template tail)" && state.tokens.next.id !== "(end)") { + advance(); + if (state.tokens.next.type === "(template tail)") { + break; + } else if (state.tokens.next.type !== "(template middle)" && + state.tokens.next.type !== "(end)") { + expression(10); // should probably have different rbp? + } + } + return { + id: "(template)", + type: "(template)" + }; + } + function doFunction(name, statement, generator, fatarrow) { + var f; + var oldOption = state.option; + var oldIgnored = state.ignored; + var oldScope = scope; + + state.option = Object.create(state.option); + state.ignored = Object.create(state.ignored); + scope = Object.create(scope); + + funct = functor(name || state.nameStack.infer(), state.tokens.next, scope, { + "(statement)": statement, + "(context)": funct, + "(generator)": generator ? true : null + }); + + f = funct; + state.tokens.curr.funct = funct; + + functions.push(funct); + + if (name) { + addlabel(name, { type: "function" }); + } + + funct["(params)"] = functionparams(fatarrow); + funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]); + + if (fatarrow) { + if (!state.option.esnext) { + warning("W119", state.tokens.curr, "arrow function syntax (=>)"); + } + + if (!fatarrow.loneArg) { + advance("=>"); + } + } + + block(false, true, true, !!fatarrow); + + if (!state.option.noyield && generator && + funct["(generator)"] !== "yielded") { + warning("W124", state.tokens.curr); + } + + funct["(metrics)"].verifyMaxStatementsPerFunction(); + funct["(metrics)"].verifyMaxComplexityPerFunction(); + funct["(unusedOption)"] = state.option.unused; + + scope = oldScope; + state.option = oldOption; + state.ignored = oldIgnored; + funct["(last)"] = state.tokens.curr.line; + funct["(lastcharacter)"] = state.tokens.curr.character; + + _.map(Object.keys(funct), function (key) { + if (key[0] === "(") return; + funct["(blockscope)"].unshadow(key); + }); + + funct = funct["(context)"]; + + return f; + } + + function createMetrics(functionStartToken) { + return { + statementCount: 0, + nestedBlockDepth: -1, + ComplexityCount: 1, + + verifyMaxStatementsPerFunction: function () { + if (state.option.maxstatements && + this.statementCount > state.option.maxstatements) { + warning("W071", functionStartToken, this.statementCount); + } + }, + + verifyMaxParametersPerFunction: function (params) { + params = params || []; + + if (state.option.maxparams && params.length > state.option.maxparams) { + warning("W072", functionStartToken, params.length); + } + }, + + verifyMaxNestedBlockDepthPerFunction: function () { + if (state.option.maxdepth && + this.nestedBlockDepth > 0 && + this.nestedBlockDepth === state.option.maxdepth + 1) { + warning("W073", null, this.nestedBlockDepth); + } + }, + + verifyMaxComplexityPerFunction: function () { + var max = state.option.maxcomplexity; + var cc = this.ComplexityCount; + if (max && cc > max) { + warning("W074", functionStartToken, cc); + } + } + }; + } + + function increaseComplexityCount() { + funct["(metrics)"].ComplexityCount += 1; + } + + function checkCondAssignment(expr) { + var id, paren; + if (expr) { + id = expr.id; + paren = expr.paren; + if (id === "," && (expr = expr.exprs[expr.exprs.length - 1])) { + id = expr.id; + paren = paren || expr.paren; + } + } + switch (id) { + case "=": + case "+=": + case "-=": + case "*=": + case "%=": + case "&=": + case "|=": + case "^=": + case "/=": + if (!paren && !state.option.boss) { + warning("W084"); + } + } + } + function checkProperties(props) { + if (state.option.inES5()) { + for (var name in props) { + if (_.has(props, name) && props[name].setterToken && !props[name].getterToken) { + warning("W078", props[name].setterToken); + } + } + } + } + + (function (x) { + x.nud = function () { + var b, f, i, p, t, g, nextVal; + var props = {}; // All properties, including accessors + + b = state.tokens.curr.line !== state.tokens.next.line; + if (b) { + indent += state.option.indent; + if (state.tokens.next.from === indent + state.option.indent) { + indent += state.option.indent; + } + } + + for (;;) { + if (state.tokens.next.id === "}") { + break; + } + + nextVal = state.tokens.next.value; + if (peek().id !== ":" && (nextVal === "get" || nextVal === "set")) { + advance(nextVal); + + if (!state.option.inES5()) { + error("E034"); + } + + i = propertyName(); + if (!i && !state.option.inESNext()) { + error("E035"); + } + if (i) { + saveAccessor(nextVal, props, i, state.tokens.curr); + } + + t = state.tokens.next; + f = doFunction(); + p = f["(params)"]; + if (nextVal === "get" && i && p) { + warning("W076", t, p[0], i); + } else if (nextVal === "set" && i && (!p || p.length !== 1)) { + warning("W077", t, i); + } + } else { + g = false; + if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") { + if (!state.option.inESNext()) { + warning("W104", state.tokens.next, "generator functions"); + } + advance("*"); + g = true; + } + if (state.tokens.next.identifier && + (peekIgnoreEOL().id === "," || peekIgnoreEOL().id === "}")) { + if (!state.option.inESNext()) { + warning("W104", state.tokens.next, "object short notation"); + } + i = propertyName(true); + saveProperty(props, i, state.tokens.next); + + expression(10); + } else { + if (state.tokens.next.id === "[") { + i = computedPropertyName(); + state.nameStack.set(i); + } else { + state.nameStack.set(state.tokens.next); + i = propertyName(); + saveProperty(props, i, state.tokens.next); + + if (typeof i !== "string") { + break; + } + } + + if (state.tokens.next.value === "(") { + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "concise methods"); + } + doFunction(null, undefined, g); + } else { + advance(":"); + expression(10); + } + } + } + + countMember(i); + + if (state.tokens.next.id === ",") { + comma({ allowTrailing: true, property: true }); + if (state.tokens.next.id === ",") { + warning("W070", state.tokens.curr); + } else if (state.tokens.next.id === "}" && !state.option.inES5(true)) { + warning("W070", state.tokens.curr); + } + } else { + break; + } + } + if (b) { + indent -= state.option.indent; + } + advance("}", this); + + checkProperties(props); + + return this; + }; + x.fud = function () { + error("E036", state.tokens.curr); + }; + }(delim("{"))); + + function destructuringExpression() { + var id, ids; + var identifiers = []; + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "destructuring expression"); + } + var nextInnerDE = function () { + var ident; + if (_.contains(["[", "{"], state.tokens.next.value)) { + ids = destructuringExpression(); + for (var id in ids) { + id = ids[id]; + identifiers.push({ id: id.id, token: id.token }); + } + } else if (state.tokens.next.value === ",") { + identifiers.push({ id: null, token: state.tokens.curr }); + } else if (state.tokens.next.value === "(") { + advance("("); + nextInnerDE(); + advance(")"); + } else { + ident = identifier(); + if (ident) + identifiers.push({ id: ident, token: state.tokens.curr }); + } + }; + if (state.tokens.next.value === "[") { + advance("["); + nextInnerDE(); + while (state.tokens.next.value !== "]") { + advance(","); + nextInnerDE(); + } + advance("]"); + } else if (state.tokens.next.value === "{") { + advance("{"); + id = identifier(); + if (state.tokens.next.value === ":") { + advance(":"); + nextInnerDE(); + } else { + identifiers.push({ id: id, token: state.tokens.curr }); + } + while (state.tokens.next.value !== "}") { + advance(","); + id = identifier(); + if (state.tokens.next.value === ":") { + advance(":"); + nextInnerDE(); + } else { + identifiers.push({ id: id, token: state.tokens.curr }); + } + } + advance("}"); + } + return identifiers; + } + + function destructuringExpressionMatch(tokens, value) { + var first = value.first; + + if (!first) + return; + + _.zip(tokens, Array.isArray(first) ? first : [ first ]).forEach(function (val) { + var token = val[0]; + var value = val[1]; + + if (token && value) + token.first = value; + else if (token && token.first && !value) + warning("W080", token.first, token.first.value); + }); + } + + var conststatement = stmt("const", function (prefix) { + var tokens; + var value; + var lone; // State variable to know if it is a lone identifier, or a destructuring statement. + + if (!state.option.inESNext()) + warning("W104", state.tokens.curr, "const"); + + this.first = []; + for (;;) { + var names = []; + if (_.contains(["{", "["], state.tokens.next.value)) { + tokens = destructuringExpression(); + lone = false; + } else { + tokens = [ { id: identifier(), token: state.tokens.curr } ]; + lone = true; + } + for (var t in tokens) { + if (tokens.hasOwnProperty(t)) { + t = tokens[t]; + if (funct[t.id] === "const") { + warning("E011", null, t.id); + } + if (funct["(global)"] && predefined[t.id] === false) { + warning("W079", t.token, t.id); + } + if (t.id) { + addlabel(t.id, { token: t.token, type: "const", unused: true }); + names.push(t.token); + } + } + } + if (prefix) { + break; + } + + this.first = this.first.concat(names); + + if (state.tokens.next.id !== "=") { + warning("E012", state.tokens.curr, state.tokens.curr.value); + } + + if (state.tokens.next.id === "=") { + advance("="); + if (state.tokens.next.id === "undefined") { + warning("W080", state.tokens.prev, state.tokens.prev.value); + } + if (peek(0).id === "=" && state.tokens.next.identifier) { + warning("W120", state.tokens.next, state.tokens.next.value); + } + value = expression(10); + if (lone) { + tokens[0].first = value; + } else { + destructuringExpressionMatch(names, value); + } + } + + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + return this; + }); + + conststatement.exps = true; + var varstatement = stmt("var", function (prefix) { + var tokens, lone, value; + + this.first = []; + for (;;) { + var names = []; + if (_.contains(["{", "["], state.tokens.next.value)) { + tokens = destructuringExpression(); + lone = false; + } else { + tokens = [ { id: identifier(), token: state.tokens.curr } ]; + lone = true; + } + for (var t in tokens) { + if (tokens.hasOwnProperty(t)) { + t = tokens[t]; + if (state.option.inESNext() && funct[t.id] === "const") { + warning("E011", null, t.id); + } + if (funct["(global)"] && predefined[t.id] === false) { + warning("W079", t.token, t.id); + } + if (t.id) { + addlabel(t.id, { type: "unused", token: t.token }); + names.push(t.token); + } + } + } + if (prefix) { + break; + } + + this.first = this.first.concat(names); + + if (state.tokens.next.id === "=") { + state.nameStack.set(state.tokens.curr); + advance("="); + if (state.tokens.next.id === "undefined") { + warning("W080", state.tokens.prev, state.tokens.prev.value); + } + if (peek(0).id === "=" && state.tokens.next.identifier) { + if (!funct["(params)"] || funct["(params)"].indexOf(state.tokens.next.value) === -1) { + warning("W120", state.tokens.next, state.tokens.next.value); + } + } + value = expression(10); + if (lone) { + tokens[0].first = value; + } else { + destructuringExpressionMatch(names, value); + } + } + + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + return this; + }); + varstatement.exps = true; + + var letstatement = stmt("let", function (prefix) { + var tokens, lone, value, letblock; + + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "let"); + } + + if (state.tokens.next.value === "(") { + if (!state.option.inMoz(true)) { + warning("W118", state.tokens.next, "let block"); + } + advance("("); + funct["(blockscope)"].stack(); + letblock = true; + } else if (funct["(nolet)"]) { + error("E048", state.tokens.curr); + } + + this.first = []; + for (;;) { + var names = []; + if (_.contains(["{", "["], state.tokens.next.value)) { + tokens = destructuringExpression(); + lone = false; + } else { + tokens = [ { id: identifier(), token: state.tokens.curr.value } ]; + lone = true; + } + for (var t in tokens) { + if (tokens.hasOwnProperty(t)) { + t = tokens[t]; + if (state.option.inESNext() && funct[t.id] === "const") { + warning("E011", null, t.id); + } + if (funct["(global)"] && predefined[t.id] === false) { + warning("W079", t.token, t.id); + } + if (t.id && !funct["(nolet)"]) { + addlabel(t.id, { type: "unused", token: t.token, islet: true }); + names.push(t.token); + } + } + } + if (prefix) { + break; + } + + this.first = this.first.concat(names); + + if (state.tokens.next.id === "=") { + advance("="); + if (state.tokens.next.id === "undefined") { + warning("W080", state.tokens.prev, state.tokens.prev.value); + } + if (peek(0).id === "=" && state.tokens.next.identifier) { + warning("W120", state.tokens.next, state.tokens.next.value); + } + value = expression(10); + if (lone) { + tokens[0].first = value; + } else { + destructuringExpressionMatch(names, value); + } + } + + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + if (letblock) { + advance(")"); + block(true, true); + this.block = true; + funct["(blockscope)"].unstack(); + } + + return this; + }); + letstatement.exps = true; + + blockstmt("class", function () { + return classdef.call(this, true); + }); + + function classdef(stmt) { + if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "class"); + } + if (stmt) { + this.name = identifier(); + addlabel(this.name, { type: "unused", token: state.tokens.curr }); + } else if (state.tokens.next.identifier && state.tokens.next.value !== "extends") { + this.name = identifier(); + } else { + this.name = state.nameStack.infer(); + } + classtail(this); + return this; + } + + function classtail(c) { + var strictness = state.directive["use strict"]; + if (state.tokens.next.value === "extends") { + advance("extends"); + c.heritage = expression(10); + } + state.directive["use strict"] = true; + advance("{"); + c.body = classbody(c); + advance("}"); + state.directive["use strict"] = strictness; + } + + function classbody(c) { + var name; + var isStatic; + var getset; + var props = {}; + var staticProps = {}; + var computed; + for (var i = 0; state.tokens.next.id !== "}"; ++i) { + name = state.tokens.next; + isStatic = false; + getset = null; + if (name.id === "[") { + name = computedPropertyName(); + } else if (isPropertyName(name)) { + advance(); + computed = false; + if (name.identifier && name.value === "static") { + if (isPropertyName(state.tokens.next) || state.tokens.next.id === "[") { + computed = state.tokens.next.id === "["; + isStatic = true; + name = state.tokens.next; + if (state.tokens.next.id === "[") { + name = computedPropertyName(); + } else advance(); + } + } + + if (name.identifier && (name.value === "get" || name.value === "set")) { + if (isPropertyName(state.tokens.next) || state.tokens.next.id === "[") { + computed = state.tokens.next.id === "["; + getset = name; + name = state.tokens.next; + if (state.tokens.next.id === "[") { + name = computedPropertyName(); + } else advance(); + } + } + } else { + warning("W052", state.tokens.next, state.tokens.next.value || state.tokens.next.type); + advance(); + continue; + } + + if (!checkPunctuators(state.tokens.next, ["("])) { + error("E054", state.tokens.next, state.tokens.next.value); + while (state.tokens.next.id !== "}" && + !checkPunctuators(state.tokens.next, ["("])) { + advance(); + } + if (state.tokens.next.value !== "(") { + doFunction(undefined, c, false, null); + } + } + + if (!computed) { + if (getset) { + saveAccessor( + getset.value, isStatic ? staticProps : props, name.value, name, true, isStatic); + } else { + if (name.value === "constructor") { + state.nameStack.set(c); + } else { + state.nameStack.set(name); + } + saveProperty(isStatic ? staticProps : props, name.value, name, true, isStatic); + } + } + + if (getset && name.value === "constructor") { + var propDesc = getset.value === "get" ? "class getter method" : "class setter method"; + error("E049", name, propDesc, "constructor"); + } else if (name.value === "prototype") { + error("E049", name, "class method", "prototype"); + } + + propertyName(name); + + doFunction(null, c, false, null); + } + + checkProperties(props); + } + + blockstmt("function", function () { + var generator = false; + if (state.tokens.next.value === "*") { + advance("*"); + if (state.option.inESNext(true)) { + generator = true; + } else { + warning("W119", state.tokens.curr, "function*"); + } + } + if (inblock) { + warning("W082", state.tokens.curr); + + } + var i = optionalidentifier(); + + if (i === undefined) { + warning("W025"); + } + + if (funct[i] === "const") { + warning("E011", null, i); + } + addlabel(i, { type: "unction", token: state.tokens.curr }); + + doFunction(i, { statement: true }, generator); + if (state.tokens.next.id === "(" && state.tokens.next.line === state.tokens.curr.line) { + error("E039"); + } + return this; + }); + + prefix("function", function () { + var generator = false; + + if (state.tokens.next.value === "*") { + if (!state.option.inESNext()) { + warning("W119", state.tokens.curr, "function*"); + } + advance("*"); + generator = true; + } + + var i = optionalidentifier(); + var fn = doFunction(i, undefined, generator); + + function isVariable(name) { return name[0] !== "("; } + function isLocal(name) { return fn[name] === "var"; } + + if (!state.option.loopfunc && funct["(loopage)"]) { + if (_.some(fn, function (val, name) { return isVariable(name) && !isLocal(name); })) { + warning("W083"); + } + } + return this; + }); + + blockstmt("if", function () { + var t = state.tokens.next; + increaseComplexityCount(); + state.condition = true; + advance("("); + var expr = expression(0); + checkCondAssignment(expr); + var forinifcheck = null; + if (state.option.forin && state.forinifcheckneeded) { + state.forinifcheckneeded = false; // We only need to analyze the first if inside the loop + forinifcheck = state.forinifchecks[state.forinifchecks.length - 1]; + if (expr.type === "(punctuator)" && expr.value === "!") { + forinifcheck.type = "(negative)"; + } else { + forinifcheck.type = "(positive)"; + } + } + + advance(")", t); + state.condition = false; + var s = block(true, true); + if (forinifcheck && forinifcheck.type === "(negative)") { + if (s && s.length === 1 && s[0].type === "(identifier)" && s[0].value === "continue") { + forinifcheck.type = "(negative-with-continue)"; + } + } + + if (state.tokens.next.id === "else") { + advance("else"); + if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") { + statement(); + } else { + block(true, true); + } + } + return this; + }); + + blockstmt("try", function () { + var b; + + function doCatch() { + var oldScope = scope; + var e; + + advance("catch"); + advance("("); + + scope = Object.create(oldScope); + + e = state.tokens.next.value; + if (state.tokens.next.type !== "(identifier)") { + e = null; + warning("E030", state.tokens.next, e); + } + + advance(); + + funct = functor("(catch)", state.tokens.next, scope, { + "(context)" : funct, + "(breakage)" : funct["(breakage)"], + "(loopage)" : funct["(loopage)"], + "(statement)": false, + "(catch)" : true + }); + + if (e) { + addlabel(e, { type: "exception" }); + } + + if (state.tokens.next.value === "if") { + if (!state.option.inMoz(true)) { + warning("W118", state.tokens.curr, "catch filter"); + } + advance("if"); + expression(0); + } + + advance(")"); + + state.tokens.curr.funct = funct; + functions.push(funct); + + block(false); + + scope = oldScope; + + funct["(last)"] = state.tokens.curr.line; + funct["(lastcharacter)"] = state.tokens.curr.character; + funct = funct["(context)"]; + } + + block(true); + + while (state.tokens.next.id === "catch") { + increaseComplexityCount(); + if (b && (!state.option.inMoz(true))) { + warning("W118", state.tokens.next, "multiple catch blocks"); + } + doCatch(); + b = true; + } + + if (state.tokens.next.id === "finally") { + advance("finally"); + block(true); + return; + } + + if (!b) { + error("E021", state.tokens.next, "catch", state.tokens.next.value); + } + + return this; + }); + + blockstmt("while", function () { + var t = state.tokens.next; + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + advance("("); + checkCondAssignment(expression(0)); + advance(")", t); + block(true, true); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + return this; + }).labelled = true; + + blockstmt("with", function () { + var t = state.tokens.next; + if (state.directive["use strict"]) { + error("E010", state.tokens.curr); + } else if (!state.option.withstmt) { + warning("W085", state.tokens.curr); + } + + advance("("); + expression(0); + advance(")", t); + block(true, true); + + return this; + }); + + blockstmt("switch", function () { + var t = state.tokens.next; + var g = false; + var noindent = false; + + funct["(breakage)"] += 1; + advance("("); + checkCondAssignment(expression(0)); + advance(")", t); + t = state.tokens.next; + advance("{"); + + if (state.tokens.next.from === indent) + noindent = true; + + if (!noindent) + indent += state.option.indent; + + this.cases = []; + + for (;;) { + switch (state.tokens.next.id) { + case "case": + switch (funct["(verb)"]) { + case "yield": + case "break": + case "case": + case "continue": + case "return": + case "switch": + case "throw": + break; + default: + if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) { + warning("W086", state.tokens.curr, "case"); + } + } + + advance("case"); + this.cases.push(expression(0)); + increaseComplexityCount(); + g = true; + advance(":"); + funct["(verb)"] = "case"; + break; + case "default": + switch (funct["(verb)"]) { + case "yield": + case "break": + case "continue": + case "return": + case "throw": + break; + default: + if (this.cases.length) { + if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) { + warning("W086", state.tokens.curr, "default"); + } + } + } + + advance("default"); + g = true; + advance(":"); + break; + case "}": + if (!noindent) + indent -= state.option.indent; + + advance("}", t); + funct["(breakage)"] -= 1; + funct["(verb)"] = undefined; + return; + case "(end)": + error("E023", state.tokens.next, "}"); + return; + default: + indent += state.option.indent; + if (g) { + switch (state.tokens.curr.id) { + case ",": + error("E040"); + return; + case ":": + g = false; + statements(); + break; + default: + error("E025", state.tokens.curr); + return; + } + } else { + if (state.tokens.curr.id === ":") { + advance(":"); + error("E024", state.tokens.curr, ":"); + statements(); + } else { + error("E021", state.tokens.next, "case", state.tokens.next.value); + return; + } + } + indent -= state.option.indent; + } + } + }).labelled = true; + + stmt("debugger", function () { + if (!state.option.debug) { + warning("W087", this); + } + return this; + }).exps = true; + + (function () { + var x = stmt("do", function () { + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + + this.first = block(true, true); + advance("while"); + var t = state.tokens.next; + advance("("); + checkCondAssignment(expression(0)); + advance(")", t); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + return this; + }); + x.labelled = true; + x.exps = true; + }()); + + blockstmt("for", function () { + var s, t = state.tokens.next; + var letscope = false; + var foreachtok = null; + + if (t.value === "each") { + foreachtok = t; + advance("each"); + if (!state.option.inMoz(true)) { + warning("W118", state.tokens.curr, "for each"); + } + } + + funct["(breakage)"] += 1; + funct["(loopage)"] += 1; + increaseComplexityCount(); + advance("("); + var nextop; // contains the token of the "in" or "of" operator + var i = 0; + var inof = ["in", "of"]; + do { + nextop = peek(i); + ++i; + } while (!_.contains(inof, nextop.value) && nextop.value !== ";" && + nextop.type !== "(end)"); + if (_.contains(inof, nextop.value)) { + if (!state.option.inESNext() && nextop.value === "of") { + error("W104", nextop, "for of"); + } + + if (state.tokens.next.id === "var") { + advance("var"); + state.syntax["var"].fud.call(state.syntax["var"].fud, true); + } else if (state.tokens.next.id === "let") { + advance("let"); + letscope = true; + funct["(blockscope)"].stack(); + state.syntax["let"].fud.call(state.syntax["let"].fud, true); + } else if (!state.tokens.next.identifier) { + error("E030", state.tokens.next, state.tokens.next.type); + advance(); + } else { + switch (funct[state.tokens.next.value]) { + case "unused": + funct[state.tokens.next.value] = "var"; + break; + case "var": + break; + default: + var ident = state.tokens.next.value; + if (!funct["(blockscope)"].getlabel(ident) && + !(scope[ident] || {})[ident]) + warning("W088", state.tokens.next, state.tokens.next.value); + } + advance(); + } + advance(nextop.value); + expression(20); + advance(")", t); + + if (nextop.value === "in" && state.option.forin) { + state.forinifcheckneeded = true; + + if (state.forinifchecks === undefined) { + state.forinifchecks = []; + } + state.forinifchecks.push({ + type: "(none)" + }); + } + + s = block(true, true); + + if (nextop.value === "in" && state.option.forin) { + if (state.forinifchecks && state.forinifchecks.length > 0) { + var check = state.forinifchecks.pop(); + + if (// No if statement or not the first statement in loop body + s && s.length > 0 && (typeof s[0] !== "object" || s[0].value !== "if") || + check.type === "(positive)" && s.length > 1 || + check.type === "(negative)") { + warning("W089", this); + } + } + state.forinifcheckneeded = false; + } + + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + } else { + if (foreachtok) { + error("E045", foreachtok); + } + if (state.tokens.next.id !== ";") { + if (state.tokens.next.id === "var") { + advance("var"); + state.syntax["var"].fud.call(state.syntax["var"].fud); + } else if (state.tokens.next.id === "let") { + advance("let"); + letscope = true; + funct["(blockscope)"].stack(); + state.syntax["let"].fud.call(state.syntax["let"].fud); + } else { + for (;;) { + expression(0, "for"); + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + } + } + nolinebreak(state.tokens.curr); + advance(";"); + if (state.tokens.next.id !== ";") { + checkCondAssignment(expression(0)); + } + nolinebreak(state.tokens.curr); + advance(";"); + if (state.tokens.next.id === ";") { + error("E021", state.tokens.next, ")", ";"); + } + if (state.tokens.next.id !== ")") { + for (;;) { + expression(0, "for"); + if (state.tokens.next.id !== ",") { + break; + } + comma(); + } + } + advance(")", t); + block(true, true); + funct["(breakage)"] -= 1; + funct["(loopage)"] -= 1; + + } + if (letscope) { + funct["(blockscope)"].unstack(); + } + return this; + }).labelled = true; + + + stmt("break", function () { + var v = state.tokens.next.value; + + if (funct["(breakage)"] === 0) + warning("W052", state.tokens.next, this.value); + + if (!state.option.asi) + nolinebreak(this); + + if (state.tokens.next.id !== ";" && !state.tokens.next.reach) { + if (state.tokens.curr.line === state.tokens.next.line) { + if (funct[v] !== "label") { + warning("W090", state.tokens.next, v); + } else if (scope[v] !== funct) { + warning("W091", state.tokens.next, v); + } + this.first = state.tokens.next; + advance(); + } + } + + reachable(this); + + return this; + }).exps = true; + + + stmt("continue", function () { + var v = state.tokens.next.value; + + if (funct["(breakage)"] === 0) + warning("W052", state.tokens.next, this.value); + + if (!state.option.asi) + nolinebreak(this); + + if (state.tokens.next.id !== ";" && !state.tokens.next.reach) { + if (state.tokens.curr.line === state.tokens.next.line) { + if (funct[v] !== "label") { + warning("W090", state.tokens.next, v); + } else if (scope[v] !== funct) { + warning("W091", state.tokens.next, v); + } + this.first = state.tokens.next; + advance(); + } + } else if (!funct["(loopage)"]) { + warning("W052", state.tokens.next, this.value); + } + + reachable(this); + + return this; + }).exps = true; + + + stmt("return", function () { + if (this.line === state.tokens.next.line) { + if (state.tokens.next.id !== ";" && !state.tokens.next.reach) { + this.first = expression(0); + + if (this.first && + this.first.type === "(punctuator)" && this.first.value === "=" && + !this.first.paren && !state.option.boss) { + warningAt("W093", this.first.line, this.first.character); + } + } + } else { + if (state.tokens.next.type === "(punctuator)" && + ["[", "{", "+", "-"].indexOf(state.tokens.next.value) > -1) { + nolinebreak(this); // always warn (Line breaking error) + } + } + + reachable(this); + + return this; + }).exps = true; + + (function (x) { + x.exps = true; + x.lbp = 25; + }(prefix("yield", function () { + var prev = state.tokens.prev; + if (state.option.inESNext(true) && !funct["(generator)"]) { + if (!("(catch)" === funct["(name)"] && funct["(context)"]["(generator)"])) { + error("E046", state.tokens.curr, "yield"); + } + } else if (!state.option.inESNext()) { + warning("W104", state.tokens.curr, "yield"); + } + funct["(generator)"] = "yielded"; + var delegatingYield = false; + + if (state.tokens.next.value === "*") { + delegatingYield = true; + advance("*"); + } + + if (this.line === state.tokens.next.line || !state.option.inMoz(true)) { + if (delegatingYield || + (state.tokens.next.id !== ";" && !state.tokens.next.reach && state.tokens.next.nud)) { + + nobreaknonadjacent(state.tokens.curr, state.tokens.next); + this.first = expression(10); + + if (this.first.type === "(punctuator)" && this.first.value === "=" && + !this.first.paren && !state.option.boss) { + warningAt("W093", this.first.line, this.first.character); + } + } + + if (state.option.inMoz(true) && state.tokens.next.id !== ")" && + (prev.lbp > 30 || (!prev.assign && !isEndOfExpr()) || prev.id === "yield")) { + error("E050", this); + } + } else if (!state.option.asi) { + nolinebreak(this); // always warn (Line breaking error) + } + return this; + }))); + + + stmt("throw", function () { + nolinebreak(this); + this.first = expression(20); + + reachable(this); + + return this; + }).exps = true; + + stmt("import", function () { + if (!state.option.inESNext()) { + warning("W119", state.tokens.curr, "import"); + } + + if (state.tokens.next.type === "(string)") { + advance("(string)"); + return this; + } + + if (state.tokens.next.identifier) { + this.name = identifier(); + addlabel(this.name, { type: "unused", token: state.tokens.curr }); + } else if (state.tokens.next.id === "*") { + advance("*"); + advance("as"); + if (state.tokens.next.identifier) { + this.name = identifier(); + addlabel(this.name, { type: "unused", token: state.tokens.curr }); + } + } else { + advance("{"); + for (;;) { + if (state.tokens.next.value === "}") { + advance("}"); + break; + } + var importName; + if (state.tokens.next.type === "default") { + importName = "default"; + advance("default"); + } else { + importName = identifier(); + } + if (state.tokens.next.value === "as") { + advance("as"); + importName = identifier(); + } + addlabel(importName, { type: "unused", token: state.tokens.curr }); + + if (state.tokens.next.value === ",") { + advance(","); + } else if (state.tokens.next.value === "}") { + advance("}"); + break; + } else { + error("E024", state.tokens.next, state.tokens.next.value); + break; + } + } + } + advance("from"); + advance("(string)"); + return this; + }).exps = true; + + stmt("export", function () { + var ok = true; + if (!state.option.inESNext()) { + warning("W119", state.tokens.curr, "export"); + ok = false; + } + + if (!funct["(global)"] || !funct["(blockscope)"].atTop()) { + error("E053", state.tokens.curr); + ok = false; + } + + if (state.tokens.next.value === "*") { + advance("*"); + advance("from"); + advance("(string)"); + return this; + } + + if (state.tokens.next.type === "default") { + state.nameStack.set(state.tokens.next); + advance("default"); + if (state.tokens.next.id === "function" || state.tokens.next.id === "class") { + this.block = true; + } + this.exportee = expression(10); + + return this; + } + + if (state.tokens.next.value === "{") { + advance("{"); + for (;;) { + var id; + exported[id = identifier(false, false, ok)] = ok; + if (ok) { + funct["(blockscope)"].setExported(id); + } + + if (state.tokens.next.value === ",") { + advance(","); + } else if (state.tokens.next.value === "}") { + advance("}"); + break; + } else { + error("E024", state.tokens.next, state.tokens.next.value); + break; + } + } + return this; + } + + if (state.tokens.next.id === "var") { + advance("var"); + exported[state.tokens.next.value] = ok; + state.tokens.next.exported = true; + state.syntax["var"].fud.call(state.syntax["var"].fud); + } else if (state.tokens.next.id === "let") { + advance("let"); + exported[state.tokens.next.value] = ok; + state.tokens.next.exported = true; + state.syntax["let"].fud.call(state.syntax["let"].fud); + } else if (state.tokens.next.id === "const") { + advance("const"); + exported[state.tokens.next.value] = ok; + state.tokens.next.exported = true; + state.syntax["const"].fud.call(state.syntax["const"].fud); + } else if (state.tokens.next.id === "function") { + this.block = true; + advance("function"); + exported[state.tokens.next.value] = ok; + state.tokens.next.exported = true; + state.syntax["function"].fud(); + } else if (state.tokens.next.id === "class") { + this.block = true; + advance("class"); + exported[state.tokens.next.value] = ok; + state.tokens.next.exported = true; + state.syntax["class"].fud(); + } else { + error("E024", state.tokens.next, state.tokens.next.value); + } + + return this; + }).exps = true; + + FutureReservedWord("abstract"); + FutureReservedWord("boolean"); + FutureReservedWord("byte"); + FutureReservedWord("char"); + FutureReservedWord("class", { es5: true, nud: classdef }); + FutureReservedWord("double"); + FutureReservedWord("enum", { es5: true }); + FutureReservedWord("export", { es5: true }); + FutureReservedWord("extends", { es5: true }); + FutureReservedWord("final"); + FutureReservedWord("float"); + FutureReservedWord("goto"); + FutureReservedWord("implements", { es5: true, strictOnly: true }); + FutureReservedWord("import", { es5: true }); + FutureReservedWord("int"); + FutureReservedWord("interface", { es5: true, strictOnly: true }); + FutureReservedWord("long"); + FutureReservedWord("native"); + FutureReservedWord("package", { es5: true, strictOnly: true }); + FutureReservedWord("private", { es5: true, strictOnly: true }); + FutureReservedWord("protected", { es5: true, strictOnly: true }); + FutureReservedWord("public", { es5: true, strictOnly: true }); + FutureReservedWord("short"); + FutureReservedWord("static", { es5: true, strictOnly: true }); + FutureReservedWord("super", { es5: true }); + FutureReservedWord("synchronized"); + FutureReservedWord("transient"); + FutureReservedWord("volatile"); + + var lookupBlockType = function () { + var pn, pn1; + var i = -1; + var bracketStack = 0; + var ret = {}; + if (checkPunctuators(state.tokens.curr, ["[", "{"])) + bracketStack += 1; + do { + pn = (i === -1) ? state.tokens.next : peek(i); + pn1 = peek(i + 1); + i = i + 1; + if (checkPunctuators(pn, ["[", "{"])) { + bracketStack += 1; + } else if (checkPunctuators(pn, ["]", "}"])) { + bracketStack -= 1; + } + if (pn.identifier && pn.value === "for" && bracketStack === 1) { + ret.isCompArray = true; + ret.notJson = true; + break; + } + if (checkPunctuators(pn, ["}", "]"]) && bracketStack === 0) { + if (pn1.value === "=") { + ret.isDestAssign = true; + ret.notJson = true; + break; + } else if (pn1.value === ".") { + ret.notJson = true; + break; + } + } + if (pn.value === ";") { + ret.isBlock = true; + ret.notJson = true; + } + } while (bracketStack > 0 && pn.id !== "(end)" && i < 15); + return ret; + }; + + function saveProperty(props, name, tkn, isClass, isStatic) { + var msg = ["key", "class method", "static class method"]; + msg = msg[(isClass || false) + (isStatic || false)]; + if (tkn.identifier) { + name = tkn.value; + } + + if (props[name] && _.has(props, name)) { + warning("W075", state.tokens.next, msg, name); + } else { + props[name] = {}; + } + + props[name].basic = true; + props[name].basictkn = tkn; + } + function saveAccessor(accessorType, props, name, tkn, isClass, isStatic) { + var flagName = accessorType === "get" ? "getterToken" : "setterToken"; + var msg = ""; + + if (isClass) { + if (isStatic) { + msg += "static "; + } + msg += accessorType + "ter method"; + } else { + msg = "key"; + } + + state.tokens.curr.accessorType = accessorType; + state.nameStack.set(tkn); + + if (props[name] && _.has(props, name)) { + if (props[name].basic || props[name][flagName]) { + warning("W075", state.tokens.next, msg, name); + } + } else { + props[name] = {}; + } + + props[name][flagName] = tkn; + } + + function computedPropertyName() { + advance("["); + if (!state.option.esnext) { + warning("W119", state.tokens.curr, "computed property names"); + } + var value = expression(10); + advance("]"); + return value; + } + function checkPunctuators(token, values) { + return token.type === "(punctuator)" && _.contains(values, token.value); + } + function destructuringAssignOrJsonValue() { + + var block = lookupBlockType(); + if (block.notJson) { + if (!state.option.inESNext() && block.isDestAssign) { + warning("W104", state.tokens.curr, "destructuring assignment"); + } + statements(); + } else { + state.option.laxbreak = true; + state.jsonMode = true; + jsonValue(); + } + } + + var arrayComprehension = function () { + var CompArray = function () { + this.mode = "use"; + this.variables = []; + }; + var _carrays = []; + var _current; + function declare(v) { + var l = _current.variables.filter(function (elt) { + if (elt.value === v) { + elt.undef = false; + return v; + } + }).length; + return l !== 0; + } + function use(v) { + var l = _current.variables.filter(function (elt) { + if (elt.value === v && !elt.undef) { + if (elt.unused === true) { + elt.unused = false; + } + return v; + } + }).length; + return (l === 0); + } + return {stack: function () { + _current = new CompArray(); + _carrays.push(_current); + }, + unstack: function () { + _current.variables.filter(function (v) { + if (v.unused) + warning("W098", v.token, v.raw_text || v.value); + if (v.undef) + isundef(v.funct, "W117", v.token, v.value); + }); + _carrays.splice(-1, 1); + _current = _carrays[_carrays.length - 1]; + }, + setState: function (s) { + if (_.contains(["use", "define", "generate", "filter"], s)) + _current.mode = s; + }, + check: function (v) { + if (!_current) { + return; + } + if (_current && _current.mode === "use") { + if (use(v)) { + _current.variables.push({ + funct: funct, + token: state.tokens.curr, + value: v, + undef: true, + unused: false + }); + } + return true; + } else if (_current && _current.mode === "define") { + if (!declare(v)) { + _current.variables.push({ + funct: funct, + token: state.tokens.curr, + value: v, + undef: false, + unused: true + }); + } + return true; + } else if (_current && _current.mode === "generate") { + isundef(funct, "W117", state.tokens.curr, v); + return true; + } else if (_current && _current.mode === "filter") { + if (use(v)) { + isundef(funct, "W117", state.tokens.curr, v); + } + return true; + } + return false; + } + }; + }; + + function jsonValue() { + function jsonObject() { + var o = {}, t = state.tokens.next; + advance("{"); + if (state.tokens.next.id !== "}") { + for (;;) { + if (state.tokens.next.id === "(end)") { + error("E026", state.tokens.next, t.line); + } else if (state.tokens.next.id === "}") { + warning("W094", state.tokens.curr); + break; + } else if (state.tokens.next.id === ",") { + error("E028", state.tokens.next); + } else if (state.tokens.next.id !== "(string)") { + warning("W095", state.tokens.next, state.tokens.next.value); + } + if (o[state.tokens.next.value] === true) { + warning("W075", state.tokens.next, state.tokens.next.value); + } else if ((state.tokens.next.value === "__proto__" && + !state.option.proto) || (state.tokens.next.value === "__iterator__" && + !state.option.iterator)) { + warning("W096", state.tokens.next, state.tokens.next.value); + } else { + o[state.tokens.next.value] = true; + } + advance(); + advance(":"); + jsonValue(); + if (state.tokens.next.id !== ",") { + break; + } + advance(","); + } + } + advance("}"); + } + + function jsonArray() { + var t = state.tokens.next; + advance("["); + if (state.tokens.next.id !== "]") { + for (;;) { + if (state.tokens.next.id === "(end)") { + error("E027", state.tokens.next, t.line); + } else if (state.tokens.next.id === "]") { + warning("W094", state.tokens.curr); + break; + } else if (state.tokens.next.id === ",") { + error("E028", state.tokens.next); + } + jsonValue(); + if (state.tokens.next.id !== ",") { + break; + } + advance(","); + } + } + advance("]"); + } + + switch (state.tokens.next.id) { + case "{": + jsonObject(); + break; + case "[": + jsonArray(); + break; + case "true": + case "false": + case "null": + case "(number)": + case "(string)": + advance(); + break; + case "-": + advance("-"); + advance("(number)"); + break; + default: + error("E003", state.tokens.next); + } + } + + var blockScope = function () { + var _current = {}; + var _variables = [_current]; + + function _checkBlockLabels() { + for (var t in _current) { + if (_current[t]["(type)"] === "unused") { + if (state.option.unused) { + var tkn = _current[t]["(token)"]; + if (tkn.exported) { + continue; + } + var line = tkn.line; + var chr = tkn.character; + warningAt("W098", line, chr, t); + } + } + } + } + + return { + stack: function () { + _current = {}; + _variables.push(_current); + }, + + unstack: function () { + _checkBlockLabels(); + _variables.splice(_variables.length - 1, 1); + _current = _.last(_variables); + }, + + getlabel: function (l) { + for (var i = _variables.length - 1 ; i >= 0; --i) { + if (_.has(_variables[i], l) && !_variables[i][l]["(shadowed)"]) { + return _variables[i]; + } + } + }, + + shadow: function (name) { + for (var i = _variables.length - 1; i >= 0; i--) { + if (_.has(_variables[i], name)) { + _variables[i][name]["(shadowed)"] = true; + } + } + }, + + unshadow: function (name) { + for (var i = _variables.length - 1; i >= 0; i--) { + if (_.has(_variables[i], name)) { + _variables[i][name]["(shadowed)"] = false; + } + } + }, + + atTop: function () { + return _variables.length === 1; + }, + + setExported: function (id) { + if (funct["(blockscope)"].atTop()) { + var item = _current[id]; + if (item && item["(token)"]) { + item["(token)"].exported = true; + } + } + }, + + current: { + has: function (t) { + return _.has(_current, t); + }, + + add: function (t, type, tok) { + _current[t] = { "(type)" : type, "(token)": tok, "(shadowed)": false }; + } + } + }; + }; + + var escapeRegex = function(str) { + return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&"); + }; + var itself = function (s, o, g) { + var i, k, x, reIgnoreStr, reIgnore; + var optionKeys; + var newOptionObj = {}; + var newIgnoredObj = {}; + + o = _.clone(o); + state.reset(); + + if (o && o.scope) { + JSHINT.scope = o.scope; + } else { + JSHINT.errors = []; + JSHINT.undefs = []; + JSHINT.internals = []; + JSHINT.blacklist = {}; + JSHINT.scope = "(main)"; + } + + predefined = Object.create(null); + combine(predefined, vars.ecmaIdentifiers); + combine(predefined, vars.reservedVars); + + combine(predefined, g || {}); + + declared = Object.create(null); + exported = Object.create(null); + + function each(obj, cb) { + if (!obj) + return; + + if (!Array.isArray(obj) && typeof obj === "object") + obj = Object.keys(obj); + + obj.forEach(cb); + } + + if (o) { + each(o.predef || null, function (item) { + var slice, prop; + + if (item[0] === "-") { + slice = item.slice(1); + JSHINT.blacklist[slice] = slice; + delete predefined[slice]; + } else { + prop = Object.getOwnPropertyDescriptor(o.predef, item); + predefined[item] = prop ? prop.value : false; + } + }); + + each(o.exported || null, function (item) { + exported[item] = true; + }); + + delete o.predef; + delete o.exported; + + optionKeys = Object.keys(o); + for (x = 0; x < optionKeys.length; x++) { + if (/^-W\d{3}$/g.test(optionKeys[x])) { + newIgnoredObj[optionKeys[x].slice(1)] = true; + } else { + newOptionObj[optionKeys[x]] = o[optionKeys[x]]; + + if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false) + newOptionObj["(explicitNewcap)"] = true; + } + } + } + + state.option = newOptionObj; + state.ignored = newIgnoredObj; + + state.option.indent = state.option.indent || 4; + state.option.maxerr = state.option.maxerr || 50; + + indent = 1; + global = Object.create(predefined); + scope = global; + + funct = functor("(global)", null, scope, { + "(global)" : true, + "(blockscope)": blockScope(), + "(comparray)" : arrayComprehension(), + "(metrics)" : createMetrics(state.tokens.next) + }); + + functions = [funct]; + urls = []; + stack = null; + member = {}; + membersOnly = null; + implied = {}; + inblock = false; + lookahead = []; + unuseds = []; + + if (!isString(s) && !Array.isArray(s)) { + errorAt("E004", 0); + return false; + } + + api = { + get isJSON() { + return state.jsonMode; + }, + + getOption: function (name) { + return state.option[name] || null; + }, + + getCache: function (name) { + return state.cache[name]; + }, + + setCache: function (name, value) { + state.cache[name] = value; + }, + + warn: function (code, data) { + warningAt.apply(null, [ code, data.line, data.char ].concat(data.data)); + }, + + on: function (names, listener) { + names.split(" ").forEach(function (name) { + emitter.on(name, listener); + }.bind(this)); + } + }; + + emitter.removeAllListeners(); + (extraModules || []).forEach(function (func) { + func(api); + }); + + state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"]; + + if (o && o.ignoreDelimiters) { + + if (!Array.isArray(o.ignoreDelimiters)) { + o.ignoreDelimiters = [o.ignoreDelimiters]; + } + + o.ignoreDelimiters.forEach(function (delimiterPair) { + if (!delimiterPair.start || !delimiterPair.end) + return; + + reIgnoreStr = escapeRegex(delimiterPair.start) + + "[\\s\\S]*?" + + escapeRegex(delimiterPair.end); + + reIgnore = new RegExp(reIgnoreStr, "ig"); + + s = s.replace(reIgnore, function(match) { + return match.replace(/./g, " "); + }); + }); + } + + lex = new Lexer(s); + + lex.on("warning", function (ev) { + warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data)); + }); + + lex.on("error", function (ev) { + errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data)); + }); + + lex.on("fatal", function (ev) { + quit("E041", ev.line, ev.from); + }); + + lex.on("Identifier", function (ev) { + emitter.emit("Identifier", ev); + }); + + lex.on("String", function (ev) { + emitter.emit("String", ev); + }); + + lex.on("Number", function (ev) { + emitter.emit("Number", ev); + }); + + lex.start(); + for (var name in o) { + if (_.has(o, name)) { + checkOption(name, state.tokens.curr); + } + } + + assume(); + combine(predefined, g || {}); + comma.first = true; + + try { + advance(); + switch (state.tokens.next.id) { + case "{": + case "[": + destructuringAssignOrJsonValue(); + break; + default: + directives(); + + if (state.directive["use strict"]) { + if (!state.option.globalstrict) { + if (!(state.option.node || state.option.phantom || state.option.browserify)) { + warning("W097", state.tokens.prev); + } + } + } + + statements(); + } + advance((state.tokens.next && state.tokens.next.value !== ".") ? "(end)" : undefined); + funct["(blockscope)"].unstack(); + + var markDefined = function (name, context) { + do { + if (typeof context[name] === "string") { + + if (context[name] === "unused") + context[name] = "var"; + else if (context[name] === "unction") + context[name] = "closure"; + + return true; + } + + context = context["(context)"]; + } while (context); + + return false; + }; + + var clearImplied = function (name, line) { + if (!implied[name]) + return; + + var newImplied = []; + for (var i = 0; i < implied[name].length; i += 1) { + if (implied[name][i] !== line) + newImplied.push(implied[name][i]); + } + + if (newImplied.length === 0) + delete implied[name]; + else + implied[name] = newImplied; + }; + + var warnUnused = function (name, tkn, type, unused_opt) { + var line = tkn.line; + var chr = tkn.from; + var raw_name = tkn.raw_text || name; + + if (unused_opt === undefined) { + unused_opt = state.option.unused; + } + + if (unused_opt === true) { + unused_opt = "last-param"; + } + + var warnable_types = { + "vars": ["var"], + "last-param": ["var", "param"], + "strict": ["var", "param", "last-param"] + }; + + if (unused_opt) { + if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) { + if (!tkn.exported) { + warningAt("W098", line, chr, raw_name); + } + } + } + + unuseds.push({ + name: name, + line: line, + character: chr + }); + }; + + var checkUnused = function (func, key) { + var type = func[key]; + var tkn = func["(tokens)"][key]; + + if (key.charAt(0) === "(") + return; + + if (type !== "unused" && type !== "unction" && type !== "const") + return; + if (func["(params)"] && func["(params)"].indexOf(key) !== -1) + return; + if (func["(global)"] && _.has(exported, key)) + return; + if (type === "const" && !getprop(func, key, "unused")) + return; + + warnUnused(key, tkn, "var"); + }; + for (i = 0; i < JSHINT.undefs.length; i += 1) { + k = JSHINT.undefs[i].slice(0); + + if (markDefined(k[2].value, k[0]) || k[2].forgiveUndef) { + clearImplied(k[2].value, k[2].line); + } else if (state.option.undef) { + warning.apply(warning, k.slice(1)); + } + } + + functions.forEach(function (func) { + if (func["(unusedOption)"] === false) { + return; + } + + for (var key in func) { + if (_.has(func, key)) { + checkUnused(func, key); + } + } + + if (!func["(params)"]) + return; + + var params = func["(params)"].slice(); + var param = params.pop(); + var type, unused_opt; + + while (param) { + type = func[param]; + unused_opt = func["(unusedOption)"] || state.option.unused; + unused_opt = unused_opt === true ? "last-param" : unused_opt; + + if (param === "undefined") + return; + + if (type === "unused" || type === "unction") { + warnUnused(param, func["(tokens)"][param], "param", func["(unusedOption)"]); + } else if (unused_opt === "last-param") { + return; + } + + param = params.pop(); + } + }); + + for (var key in declared) { + if (_.has(declared, key) && !_.has(global, key) && !_.has(exported, key)) { + warnUnused(key, declared[key], "var"); + } + } + + } catch (err) { + if (err && err.name === "JSHintError") { + var nt = state.tokens.next || {}; + JSHINT.errors.push({ + scope : "(main)", + raw : err.raw, + code : err.code, + reason : err.message, + line : err.line || nt.line, + character : err.character || nt.from + }, null); + } else { + throw err; + } + } + + if (JSHINT.scope === "(main)") { + o = o || {}; + + for (i = 0; i < JSHINT.internals.length; i += 1) { + k = JSHINT.internals[i]; + o.scope = k.elem; + itself(k.value, o, g); + } + } + + return JSHINT.errors.length === 0; + }; + itself.addModule = function (func) { + extraModules.push(func); + }; + + itself.addModule(style.register); + itself.data = function () { + var data = { + functions: [], + options: state.option + }; + + var implieds = []; + var members = []; + var fu, f, i, j, n, globals; + + if (itself.errors.length) { + data.errors = itself.errors; + } + + if (state.jsonMode) { + data.json = true; + } + + for (n in implied) { + if (_.has(implied, n)) { + implieds.push({ + name: n, + line: implied[n] + }); + } + } + + if (implieds.length > 0) { + data.implieds = implieds; + } + + if (urls.length > 0) { + data.urls = urls; + } + + globals = Object.keys(scope); + if (globals.length > 0) { + data.globals = globals; + } + + for (i = 1; i < functions.length; i += 1) { + f = functions[i]; + fu = {}; + + for (j = 0; j < functionicity.length; j += 1) { + fu[functionicity[j]] = []; + } + + for (j = 0; j < functionicity.length; j += 1) { + if (fu[functionicity[j]].length === 0) { + delete fu[functionicity[j]]; + } + } + + fu.name = f["(name)"]; + fu.param = f["(params)"]; + fu.line = f["(line)"]; + fu.character = f["(character)"]; + fu.last = f["(last)"]; + fu.lastcharacter = f["(lastcharacter)"]; + + fu.metrics = { + complexity: f["(metrics)"].ComplexityCount, + parameters: (f["(params)"] || []).length, + statements: f["(metrics)"].statementCount + }; + + data.functions.push(fu); + } + + if (unuseds.length > 0) { + data.unused = unuseds; + } + + members = []; + for (n in member) { + if (typeof member[n] === "number") { + data.member = member; + break; + } + } + + return data; + }; + + itself.jshint = itself; + + return itself; +}()); +if (typeof exports === "object" && exports) { + exports.JSHINT = JSHINT; +} + +}, +{"./lex.js":4,"./messages.js":5,"./options.js":7,"./reg.js":8,"./state.js":9,"./style.js":10,"./vars.js":11,"events":12,"underscore":2}], +4:[function(_dereq_,module,exports){ + +"use strict"; + +var _ = _dereq_("underscore"); +var events = _dereq_("events"); +var reg = _dereq_("./reg.js"); +var state = _dereq_("./state.js").state; + +var unicodeData = _dereq_("../data/ascii-identifier-data.js"); +var asciiIdentifierStartTable = unicodeData.asciiIdentifierStartTable; +var asciiIdentifierPartTable = unicodeData.asciiIdentifierPartTable; + +var Token = { + Identifier: 1, + Punctuator: 2, + NumericLiteral: 3, + StringLiteral: 4, + Comment: 5, + Keyword: 6, + NullLiteral: 7, + BooleanLiteral: 8, + RegExp: 9, + TemplateHead: 10, + TemplateMiddle: 11, + TemplateTail: 12 +}; + +function asyncTrigger() { + var _checks = []; + + return { + push: function (fn) { + _checks.push(fn); + }, + + check: function () { + for (var check = 0; check < _checks.length; ++check) { + _checks[check](); + } + + _checks.splice(0, _checks.length); + } + }; +} +function Lexer(source) { + var lines = source; + + if (typeof lines === "string") { + lines = lines + .replace(/\r\n/g, "\n") + .replace(/\r/g, "\n") + .split("\n"); + } + + if (lines[0] && lines[0].substr(0, 2) === "#!") { + if (lines[0].indexOf("node") !== -1) { + state.option.node = true; + } + lines[0] = ""; + } + + this.emitter = new events.EventEmitter(); + this.source = source; + this.setLines(lines); + this.prereg = true; + + this.line = 0; + this.char = 1; + this.from = 1; + this.input = ""; + this.inComment = false; + this.inTemplate = false; + this.templateLine = null; + this.templateChar = null; + + for (var i = 0; i < state.option.indent; i += 1) { + state.tab += " "; + } +} + +Lexer.prototype = { + _lines: [], + + getLines: function () { + this._lines = state.lines; + return this._lines; + }, + + setLines: function (val) { + this._lines = val; + state.lines = this._lines; + }, + peek: function (i) { + return this.input.charAt(i || 0); + }, + skip: function (i) { + i = i || 1; + this.char += i; + this.input = this.input.slice(i); + }, + on: function (names, listener) { + names.split(" ").forEach(function (name) { + this.emitter.on(name, listener); + }.bind(this)); + }, + trigger: function () { + this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments)); + }, + triggerAsync: function (type, args, checks, fn) { + checks.push(function () { + if (fn()) { + this.trigger(type, args); + } + }.bind(this)); + }, + scanPunctuator: function () { + var ch1 = this.peek(); + var ch2, ch3, ch4; + + switch (ch1) { + case ".": + if ((/^[0-9]$/).test(this.peek(1))) { + return null; + } + if (this.peek(1) === "." && this.peek(2) === ".") { + return { + type: Token.Punctuator, + value: "..." + }; + } + case "(": + case ")": + case ";": + case ",": + case "{": + case "}": + case "[": + case "]": + case ":": + case "~": + case "?": + return { + type: Token.Punctuator, + value: ch1 + }; + case "#": + return { + type: Token.Punctuator, + value: ch1 + }; + case "": + return null; + } + + ch2 = this.peek(1); + ch3 = this.peek(2); + ch4 = this.peek(3); + + if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") { + return { + type: Token.Punctuator, + value: ">>>=" + }; + } + + if (ch1 === "=" && ch2 === "=" && ch3 === "=") { + return { + type: Token.Punctuator, + value: "===" + }; + } + + if (ch1 === "!" && ch2 === "=" && ch3 === "=") { + return { + type: Token.Punctuator, + value: "!==" + }; + } + + if (ch1 === ">" && ch2 === ">" && ch3 === ">") { + return { + type: Token.Punctuator, + value: ">>>" + }; + } + + if (ch1 === "<" && ch2 === "<" && ch3 === "=") { + return { + type: Token.Punctuator, + value: "<<=" + }; + } + + if (ch1 === ">" && ch2 === ">" && ch3 === "=") { + return { + type: Token.Punctuator, + value: ">>=" + }; + } + if (ch1 === "=" && ch2 === ">") { + return { + type: Token.Punctuator, + value: ch1 + ch2 + }; + } + if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) { + return { + type: Token.Punctuator, + value: ch1 + ch2 + }; + } + + if ("<>=!+-*%&|^".indexOf(ch1) >= 0) { + if (ch2 === "=") { + return { + type: Token.Punctuator, + value: ch1 + ch2 + }; + } + + return { + type: Token.Punctuator, + value: ch1 + }; + } + + if (ch1 === "/") { + if (ch2 === "=") { + return { + type: Token.Punctuator, + value: "/=" + }; + } + + return { + type: Token.Punctuator, + value: "/" + }; + } + + return null; + }, + scanComments: function () { + var ch1 = this.peek(); + var ch2 = this.peek(1); + var rest = this.input.substr(2); + var startLine = this.line; + var startChar = this.char; + + function commentToken(label, body, opt) { + var special = ["jshint", "jslint", "members", "member", "globals", "global", "exported"]; + var isSpecial = false; + var value = label + body; + var commentType = "plain"; + opt = opt || {}; + + if (opt.isMultiline) { + value += "*/"; + } + + body = body.replace(/\n/g, " "); + + special.forEach(function (str) { + if (isSpecial) { + return; + } + if (label === "//" && str !== "jshint") { + return; + } + + if (body.charAt(str.length) === " " && body.substr(0, str.length) === str) { + isSpecial = true; + label = label + str; + body = body.substr(str.length); + } + + if (!isSpecial && body.charAt(0) === " " && body.charAt(str.length + 1) === " " && + body.substr(1, str.length) === str) { + isSpecial = true; + label = label + " " + str; + body = body.substr(str.length + 1); + } + + if (!isSpecial) { + return; + } + + switch (str) { + case "member": + commentType = "members"; + break; + case "global": + commentType = "globals"; + break; + default: + commentType = str; + } + }); + + return { + type: Token.Comment, + commentType: commentType, + value: value, + body: body, + isSpecial: isSpecial, + isMultiline: opt.isMultiline || false, + isMalformed: opt.isMalformed || false + }; + } + if (ch1 === "*" && ch2 === "/") { + this.trigger("error", { + code: "E018", + line: startLine, + character: startChar + }); + + this.skip(2); + return null; + } + if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) { + return null; + } + if (ch2 === "/") { + this.skip(this.input.length); // Skip to the EOL. + return commentToken("//", rest); + } + + var body = ""; + if (ch2 === "*") { + this.inComment = true; + this.skip(2); + + while (this.peek() !== "*" || this.peek(1) !== "/") { + if (this.peek() === "") { // End of Line + body += "\n"; + if (!this.nextLine()) { + this.trigger("error", { + code: "E017", + line: startLine, + character: startChar + }); + + this.inComment = false; + return commentToken("/*", body, { + isMultiline: true, + isMalformed: true + }); + } + } else { + body += this.peek(); + this.skip(); + } + } + + this.skip(2); + this.inComment = false; + return commentToken("/*", body, { isMultiline: true }); + } + }, + scanKeyword: function () { + var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input); + var keywords = [ + "if", "in", "do", "var", "for", "new", + "try", "let", "this", "else", "case", + "void", "with", "enum", "while", "break", + "catch", "throw", "const", "yield", "class", + "super", "return", "typeof", "delete", + "switch", "export", "import", "default", + "finally", "extends", "function", "continue", + "debugger", "instanceof" + ]; + + if (result && keywords.indexOf(result[0]) >= 0) { + return { + type: Token.Keyword, + value: result[0] + }; + } + + return null; + }, + scanIdentifier: function () { + var id = ""; + var index = 0; + var type, char; + + function isNonAsciiIdentifierStart(code) { + return code > 256; + } + + function isNonAsciiIdentifierPart(code) { + return code > 256; + } + + function isHexDigit(str) { + return (/^[0-9a-fA-F]$/).test(str); + } + + var readUnicodeEscapeSequence = function() { + index += 1; + + if (this.peek(index) !== "u") { + return null; + } + + var ch1 = this.peek(index + 1); + var ch2 = this.peek(index + 2); + var ch3 = this.peek(index + 3); + var ch4 = this.peek(index + 4); + var code; + + if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) { + code = parseInt(ch1 + ch2 + ch3 + ch4, 16); + + if (asciiIdentifierPartTable[code] || isNonAsciiIdentifierPart(code)) { + index += 5; + return "\\u" + ch1 + ch2 + ch3 + ch4; + } + + return null; + } + + return null; + }.bind(this); + + var getIdentifierStart = function () { + var chr = this.peek(index); + var code = chr.charCodeAt(0); + + if (code === 92) { + return readUnicodeEscapeSequence(); + } + + if (code < 128) { + if (asciiIdentifierStartTable[code]) { + index += 1; + return chr; + } + + return null; + } + + if (isNonAsciiIdentifierStart(code)) { + index += 1; + return chr; + } + + return null; + }.bind(this); + + var getIdentifierPart = function () { + var chr = this.peek(index); + var code = chr.charCodeAt(0); + + if (code === 92) { + return readUnicodeEscapeSequence(); + } + + if (code < 128) { + if (asciiIdentifierPartTable[code]) { + index += 1; + return chr; + } + + return null; + } + + if (isNonAsciiIdentifierPart(code)) { + index += 1; + return chr; + } + + return null; + }.bind(this); + + function removeEscapeSequences(id) { + return id.replace(/\\u([0-9a-fA-F]{4})/g, function(m0, codepoint) { + return String.fromCharCode(parseInt(codepoint, 16)); + }); + } + + char = getIdentifierStart(); + if (char === null) { + return null; + } + + id = char; + for (;;) { + char = getIdentifierPart(); + + if (char === null) { + break; + } + + id += char; + } + + switch (id) { + case "true": + case "false": + type = Token.BooleanLiteral; + break; + case "null": + type = Token.NullLiteral; + break; + default: + type = Token.Identifier; + } + + return { + type: type, + value: removeEscapeSequences(id), + text: id, + tokenLength: id.length + }; + }, + scanNumericLiteral: function () { + var index = 0; + var value = ""; + var length = this.input.length; + var char = this.peek(index); + var bad; + var isAllowedDigit = isDecimalDigit; + var base = 10; + var isLegacy = false; + + function isDecimalDigit(str) { + return (/^[0-9]$/).test(str); + } + + function isOctalDigit(str) { + return (/^[0-7]$/).test(str); + } + + function isBinaryDigit(str) { + return (/^[01]$/).test(str); + } + + function isHexDigit(str) { + return (/^[0-9a-fA-F]$/).test(str); + } + + function isIdentifierStart(ch) { + return (ch === "$") || (ch === "_") || (ch === "\\") || + (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z"); + } + + if (char !== "." && !isDecimalDigit(char)) { + return null; + } + + if (char !== ".") { + value = this.peek(index); + index += 1; + char = this.peek(index); + + if (value === "0") { + if (char === "x" || char === "X") { + isAllowedDigit = isHexDigit; + base = 16; + + index += 1; + value += char; + } + if (char === "o" || char === "O") { + isAllowedDigit = isOctalDigit; + base = 8; + + if (!state.option.esnext) { + this.trigger("warning", { + code: "W119", + line: this.line, + character: this.char, + data: [ "Octal integer literal" ] + }); + } + + index += 1; + value += char; + } + if (char === "b" || char === "B") { + isAllowedDigit = isBinaryDigit; + base = 2; + + if (!state.option.esnext) { + this.trigger("warning", { + code: "W119", + line: this.line, + character: this.char, + data: [ "Binary integer literal" ] + }); + } + + index += 1; + value += char; + } + if (isOctalDigit(char)) { + isAllowedDigit = isOctalDigit; + base = 8; + isLegacy = true; + bad = false; + + index += 1; + value += char; + } + + if (!isOctalDigit(char) && isDecimalDigit(char)) { + index += 1; + value += char; + } + } + + while (index < length) { + char = this.peek(index); + + if (isLegacy && isDecimalDigit(char)) { + bad = true; + } else if (!isAllowedDigit(char)) { + break; + } + value += char; + index += 1; + } + + if (isAllowedDigit !== isDecimalDigit) { + if (!isLegacy && value.length <= 2) { // 0x + return { + type: Token.NumericLiteral, + value: value, + isMalformed: true + }; + } + + if (index < length) { + char = this.peek(index); + if (isIdentifierStart(char)) { + return null; + } + } + + return { + type: Token.NumericLiteral, + value: value, + base: base, + isLegacy: isLegacy, + isMalformed: false + }; + } + } + + if (char === ".") { + value += char; + index += 1; + + while (index < length) { + char = this.peek(index); + if (!isDecimalDigit(char)) { + break; + } + value += char; + index += 1; + } + } + + if (char === "e" || char === "E") { + value += char; + index += 1; + char = this.peek(index); + + if (char === "+" || char === "-") { + value += this.peek(index); + index += 1; + } + + char = this.peek(index); + if (isDecimalDigit(char)) { + value += char; + index += 1; + + while (index < length) { + char = this.peek(index); + if (!isDecimalDigit(char)) { + break; + } + value += char; + index += 1; + } + } else { + return null; + } + } + + if (index < length) { + char = this.peek(index); + if (isIdentifierStart(char)) { + return null; + } + } + + return { + type: Token.NumericLiteral, + value: value, + base: base, + isMalformed: !isFinite(value) + }; + }, + scanEscapeSequence: function (checks) { + var allowNewLine = false; + var jump = 1; + this.skip(); + var char = this.peek(); + + switch (char) { + case "'": + this.triggerAsync("warning", { + code: "W114", + line: this.line, + character: this.char, + data: [ "\\'" ] + }, checks, function () {return state.jsonMode; }); + break; + case "b": + char = "\\b"; + break; + case "f": + char = "\\f"; + break; + case "n": + char = "\\n"; + break; + case "r": + char = "\\r"; + break; + case "t": + char = "\\t"; + break; + case "0": + char = "\\0"; + var n = parseInt(this.peek(1), 10); + this.triggerAsync("warning", { + code: "W115", + line: this.line, + character: this.char + }, checks, + function () { return n >= 0 && n <= 7 && state.directive["use strict"]; }); + break; + case "u": + char = String.fromCharCode(parseInt(this.input.substr(1, 4), 16)); + jump = 5; + break; + case "v": + this.triggerAsync("warning", { + code: "W114", + line: this.line, + character: this.char, + data: [ "\\v" ] + }, checks, function () { return state.jsonMode; }); + + char = "\v"; + break; + case "x": + var x = parseInt(this.input.substr(1, 2), 16); + + this.triggerAsync("warning", { + code: "W114", + line: this.line, + character: this.char, + data: [ "\\x-" ] + }, checks, function () { return state.jsonMode; }); + + char = String.fromCharCode(x); + jump = 3; + break; + case "\\": + char = "\\\\"; + break; + case "\"": + char = "\\\""; + break; + case "/": + break; + case "": + allowNewLine = true; + char = ""; + break; + } + + return {char: char, jump: jump, allowNewLine: allowNewLine}; + }, + scanTemplateLiteral: function (checks) { + var tokenType; + var value = ''; + var ch; + if (!this.inTemplate) { + if (!state.option.esnext || this.peek() !== "`") { + return null; + } + this.templateLine = this.line; + this.templateChar = this.char; + this.skip(1); + } else if (this.peek() !== '}') { + return null; + } + + while (this.peek() !== "`") { + while ((ch = this.peek()) === "") { + if (!this.nextLine()) { + tokenType = this.inTemplate ? Token.TemplateHead : Token.TemplateMiddle; + this.inTemplate = false; + this.trigger("error", { + code: "E052", + line: this.templateLine, + character: this.templateChar + }); + return { + type: tokenType, + value: value, + isUnclosed: true + }; + } + } + + if (ch === '$' && this.peek(1) === '{') { + value += '${'; + tokenType = value.charAt(0) === '}' ? Token.TemplateMiddle : Token.TemplateHead; + this.skip(2); + this.inTemplate = true; + return { + type: tokenType, + value: value, + isUnclosed: false + }; + } else if (ch === '\\') { + var escape = this.scanEscapeSequence(checks); + value += escape.char; + this.skip(escape.jump); + } else if (ch === '`') { + break; + } else { + value += ch; + this.skip(1); + } + } + tokenType = this.inTemplate ? Token.TemplateTail : Token.StringLiteral; + this.inTemplate = false; + this.skip(1); + + return { + type: tokenType, + value: value, + isUnclosed: false, + quote: "`" + }; + }, + scanStringLiteral: function (checks) { + var quote = this.peek(); + if (quote !== "\"" && quote !== "'") { + return null; + } + this.triggerAsync("warning", { + code: "W108", + line: this.line, + character: this.char // +1? + }, checks, function () { return state.jsonMode && quote !== "\""; }); + + var value = ""; + var startLine = this.line; + var startChar = this.char; + var allowNewLine = false; + + this.skip(); + + outer: while (this.peek() !== quote) { + while (this.peek() === "") { // End Of Line + + if (!allowNewLine) { + this.trigger("warning", { + code: "W112", + line: this.line, + character: this.char + }); + } else { + allowNewLine = false; + + this.triggerAsync("warning", { + code: "W043", + line: this.line, + character: this.char + }, checks, function () { return !state.option.multistr; }); + + this.triggerAsync("warning", { + code: "W042", + line: this.line, + character: this.char + }, checks, function () { return state.jsonMode && state.option.multistr; }); + } + + if (!this.nextLine()) { + this.trigger("error", { + code: "E029", + line: startLine, + character: startChar + }); + + return { + type: Token.StringLiteral, + value: value, + isUnclosed: true, + quote: quote + }; + } + + if (this.peek() == quote) + break outer; + } + + allowNewLine = false; + var char = this.peek(); + var jump = 1; // A length of a jump, after we're done + + if (char < " ") { + this.trigger("warning", { + code: "W113", + line: this.line, + character: this.char, + data: [ "" ] + }); + } + if (char === "\\") { + var parsed = this.scanEscapeSequence(checks); + char = parsed.char; + jump = parsed.jump; + allowNewLine = parsed.allowNewLine; + } + + value += char; + this.skip(jump); + } + + this.skip(); + return { + type: Token.StringLiteral, + value: value, + isUnclosed: false, + quote: quote + }; + }, + scanRegExp: function () { + var index = 0; + var length = this.input.length; + var char = this.peek(); + var value = char; + var body = ""; + var flags = []; + var malformed = false; + var isCharSet = false; + var terminated; + + var scanUnexpectedChars = function () { + if (char < " ") { + malformed = true; + this.trigger("warning", { + code: "W048", + line: this.line, + character: this.char + }); + } + if (char === "<") { + malformed = true; + this.trigger("warning", { + code: "W049", + line: this.line, + character: this.char, + data: [ char ] + }); + } + }.bind(this); + if (!this.prereg || char !== "/") { + return null; + } + + index += 1; + terminated = false; + + while (index < length) { + char = this.peek(index); + value += char; + body += char; + + if (isCharSet) { + if (char === "]") { + if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") { + isCharSet = false; + } + } + + if (char === "\\") { + index += 1; + char = this.peek(index); + body += char; + value += char; + + scanUnexpectedChars(); + } + + index += 1; + continue; + } + + if (char === "\\") { + index += 1; + char = this.peek(index); + body += char; + value += char; + + scanUnexpectedChars(); + + if (char === "/") { + index += 1; + continue; + } + + if (char === "[") { + index += 1; + continue; + } + } + + if (char === "[") { + isCharSet = true; + index += 1; + continue; + } + + if (char === "/") { + body = body.substr(0, body.length - 1); + terminated = true; + index += 1; + break; + } + + index += 1; + } + + if (!terminated) { + this.trigger("error", { + code: "E015", + line: this.line, + character: this.from + }); + + return void this.trigger("fatal", { + line: this.line, + from: this.from + }); + } + + while (index < length) { + char = this.peek(index); + if (!/[gim]/.test(char)) { + break; + } + flags.push(char); + value += char; + index += 1; + } + + try { + new RegExp(body, flags.join("")); + } catch (err) { + malformed = true; + this.trigger("error", { + code: "E016", + line: this.line, + character: this.char, + data: [ err.message ] // Platform dependent! + }); + } + + return { + type: Token.RegExp, + value: value, + flags: flags, + isMalformed: malformed + }; + }, + scanNonBreakingSpaces: function () { + return state.option.nonbsp ? + this.input.search(/(\u00A0)/) : -1; + }, + scanUnsafeChars: function () { + return this.input.search(reg.unsafeChars); + }, + next: function (checks) { + this.from = this.char; + var start; + if (/\s/.test(this.peek())) { + start = this.char; + + while (/\s/.test(this.peek())) { + this.from += 1; + this.skip(); + } + } + + var match = this.scanComments() || + this.scanStringLiteral(checks) || + this.scanTemplateLiteral(checks); + + if (match) { + return match; + } + + match = + this.scanRegExp() || + this.scanPunctuator() || + this.scanKeyword() || + this.scanIdentifier() || + this.scanNumericLiteral(); + + if (match) { + this.skip(match.tokenLength || match.value.length); + return match; + } + + return null; + }, + nextLine: function () { + var char; + + if (this.line >= this.getLines().length) { + return false; + } + + this.input = this.getLines()[this.line]; + this.line += 1; + this.char = 1; + this.from = 1; + + var inputTrimmed = this.input.trim(); + + var startsWith = function () { + return _.some(arguments, function (prefix) { + return inputTrimmed.indexOf(prefix) === 0; + }); + }; + + var endsWith = function () { + return _.some(arguments, function (suffix) { + return inputTrimmed.indexOf(suffix, inputTrimmed.length - suffix.length) !== -1; + }); + }; + if (state.ignoreLinterErrors === true) { + if (!startsWith("/*", "//") && !(this.inComment && endsWith("*/"))) { + this.input = ""; + } + } + + char = this.scanNonBreakingSpaces(); + if (char >= 0) { + this.trigger("warning", { code: "W125", line: this.line, character: char + 1 }); + } + + this.input = this.input.replace(/\t/g, state.tab); + char = this.scanUnsafeChars(); + + if (char >= 0) { + this.trigger("warning", { code: "W100", line: this.line, character: char }); + } + + if (state.option.maxlen && state.option.maxlen < this.input.length) { + var inComment = this.inComment || + startsWith.call(inputTrimmed, "//") || + startsWith.call(inputTrimmed, "/*"); + + var shouldTriggerError = !inComment || !reg.maxlenException.test(inputTrimmed); + + if (shouldTriggerError) { + this.trigger("warning", { code: "W101", line: this.line, character: this.input.length }); + } + } + + return true; + }, + start: function () { + this.nextLine(); + }, + token: function () { + var checks = asyncTrigger(); + var token; + + + function isReserved(token, isProperty) { + if (!token.reserved) { + return false; + } + var meta = token.meta; + + if (meta && meta.isFutureReservedWord && state.option.inES5()) { + if (!meta.es5) { + return false; + } + if (meta.strictOnly) { + if (!state.option.strict && !state.directive["use strict"]) { + return false; + } + } + + if (isProperty) { + return false; + } + } + + return true; + } + var create = function (type, value, isProperty, token) { + var obj; + + if (type !== "(endline)" && type !== "(end)") { + this.prereg = false; + } + + if (type === "(punctuator)") { + switch (value) { + case ".": + case ")": + case "~": + case "#": + case "]": + case "++": + case "--": + this.prereg = false; + break; + default: + this.prereg = true; + } + + obj = Object.create(state.syntax[value] || state.syntax["(error)"]); + } + + if (type === "(identifier)") { + if (value === "return" || value === "case" || value === "typeof") { + this.prereg = true; + } + + if (_.has(state.syntax, value)) { + obj = Object.create(state.syntax[value] || state.syntax["(error)"]); + if (!isReserved(obj, isProperty && type === "(identifier)")) { + obj = null; + } + } + } + + if (!obj) { + obj = Object.create(state.syntax[type]); + } + + obj.identifier = (type === "(identifier)"); + obj.type = obj.type || type; + obj.value = value; + obj.line = this.line; + obj.character = this.char; + obj.from = this.from; + if (obj.identifier && token) obj.raw_text = token.text || token.value; + + if (isProperty && obj.identifier) { + obj.isProperty = isProperty; + } + + obj.check = checks.check; + + return obj; + }.bind(this); + + for (;;) { + if (!this.input.length) { + return create(this.nextLine() ? "(endline)" : "(end)", ""); + } + + token = this.next(checks); + + if (!token) { + if (this.input.length) { + this.trigger("error", { + code: "E024", + line: this.line, + character: this.char, + data: [ this.peek() ] + }); + + this.input = ""; + } + + continue; + } + + switch (token.type) { + case Token.StringLiteral: + this.triggerAsync("String", { + line: this.line, + char: this.char, + from: this.from, + value: token.value, + quote: token.quote + }, checks, function () { return true; }); + + return create("(string)", token.value); + + case Token.TemplateHead: + this.trigger("TemplateHead", { + line: this.line, + char: this.char, + from: this.from, + value: token.value + }); + return create("(template)", token.value); + + case Token.TemplateMiddle: + this.trigger("TemplateMiddle", { + line: this.line, + char: this.char, + from: this.from, + value: token.value + }); + return create("(template middle)", token.value); + + case Token.TemplateTail: + this.trigger("TemplateTail", { + line: this.line, + char: this.char, + from: this.from, + value: token.value + }); + return create("(template tail)", token.value); + + case Token.Identifier: + this.trigger("Identifier", { + line: this.line, + char: this.char, + from: this.form, + name: token.value, + raw_name: token.text, + isProperty: state.tokens.curr.id === "." + }); + case Token.Keyword: + case Token.NullLiteral: + case Token.BooleanLiteral: + return create("(identifier)", token.value, state.tokens.curr.id === ".", token); + + case Token.NumericLiteral: + if (token.isMalformed) { + this.trigger("warning", { + code: "W045", + line: this.line, + character: this.char, + data: [ token.value ] + }); + } + + this.triggerAsync("warning", { + code: "W114", + line: this.line, + character: this.char, + data: [ "0x-" ] + }, checks, function () { return token.base === 16 && state.jsonMode; }); + + this.triggerAsync("warning", { + code: "W115", + line: this.line, + character: this.char + }, checks, function () { + return state.directive["use strict"] && token.base === 8 && token.isLegacy; + }); + + this.trigger("Number", { + line: this.line, + char: this.char, + from: this.from, + value: token.value, + base: token.base, + isMalformed: token.malformed + }); + + return create("(number)", token.value); + + case Token.RegExp: + return create("(regexp)", token.value); + + case Token.Comment: + state.tokens.curr.comment = true; + + if (token.isSpecial) { + return { + id: '(comment)', + value: token.value, + body: token.body, + type: token.commentType, + isSpecial: token.isSpecial, + line: this.line, + character: this.char, + from: this.from + }; + } + + break; + + case "": + break; + + default: + return create("(punctuator)", token.value); + } + } + } +}; + +exports.Lexer = Lexer; + +}, +{"../data/ascii-identifier-data.js":1,"./reg.js":8,"./state.js":9,"events":12,"underscore":2}], +5:[function(_dereq_,module,exports){ +"use strict"; + +var _ = _dereq_("underscore"); + +var errors = { + E001: "Bad option: '{a}'.", + E002: "Bad option value.", + E003: "Expected a JSON value.", + E004: "Input is neither a string nor an array of strings.", + E005: "Input is empty.", + E006: "Unexpected early end of program.", + E007: "Missing \"use strict\" statement.", + E008: "Strict violation.", + E009: "Option 'validthis' can't be used in a global scope.", + E010: "'with' is not allowed in strict mode.", + E011: "const '{a}' has already been declared.", + E012: "const '{a}' is initialized to 'undefined'.", + E013: "Attempting to override '{a}' which is a constant.", + E014: "A regular expression literal can be confused with '/='.", + E015: "Unclosed regular expression.", + E016: "Invalid regular expression.", + E017: "Unclosed comment.", + E018: "Unbegun comment.", + E019: "Unmatched '{a}'.", + E020: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.", + E021: "Expected '{a}' and instead saw '{b}'.", + E022: "Line breaking error '{a}'.", + E023: "Missing '{a}'.", + E024: "Unexpected '{a}'.", + E025: "Missing ':' on a case clause.", + E026: "Missing '}' to match '{' from line {a}.", + E027: "Missing ']' to match '[' from line {a}.", + E028: "Illegal comma.", + E029: "Unclosed string.", + E030: "Expected an identifier and instead saw '{a}'.", + E031: "Bad assignment.", // FIXME: Rephrase + E032: "Expected a small integer or 'false' and instead saw '{a}'.", + E033: "Expected an operator and instead saw '{a}'.", + E034: "get/set are ES5 features.", + E035: "Missing property name.", + E036: "Expected to see a statement and instead saw a block.", + E037: null, + E038: null, + E039: "Function declarations are not invocable. Wrap the whole function invocation in parens.", + E040: "Each value should have its own case label.", + E041: "Unrecoverable syntax error.", + E042: "Stopping.", + E043: "Too many errors.", + E044: null, + E045: "Invalid for each loop.", + E046: "A yield statement shall be within a generator function (with syntax: `function*`)", + E047: null, // Vacant + E048: "Let declaration not directly within block.", + E049: "A {a} cannot be named '{b}'.", + E050: "Mozilla requires the yield expression to be parenthesized here.", + E051: "Regular parameters cannot come after default parameters.", + E052: "Unclosed template literal.", + E053: "Export declaration must be in global scope.", + E054: "Class properties must be methods. Expected '(' but instead saw '{a}'." +}; + +var warnings = { + W001: "'hasOwnProperty' is a really bad name.", + W002: "Value of '{a}' may be overwritten in IE 8 and earlier.", + W003: "'{a}' was used before it was defined.", + W004: "'{a}' is already defined.", + W005: "A dot following a number can be confused with a decimal point.", + W006: "Confusing minuses.", + W007: "Confusing plusses.", + W008: "A leading decimal point can be confused with a dot: '{a}'.", + W009: "The array literal notation [] is preferable.", + W010: "The object literal notation {} is preferable.", + W011: null, + W012: null, + W013: null, + W014: "Bad line breaking before '{a}'.", + W015: null, + W016: "Unexpected use of '{a}'.", + W017: "Bad operand.", + W018: "Confusing use of '{a}'.", + W019: "Use the isNaN function to compare with NaN.", + W020: "Read only.", + W021: "'{a}' is a function.", + W022: "Do not assign to the exception parameter.", + W023: "Expected an identifier in an assignment and instead saw a function invocation.", + W024: "Expected an identifier and instead saw '{a}' (a reserved word).", + W025: "Missing name in function declaration.", + W026: "Inner functions should be listed at the top of the outer function.", + W027: "Unreachable '{a}' after '{b}'.", + W028: "Label '{a}' on {b} statement.", + W030: "Expected an assignment or function call and instead saw an expression.", + W031: "Do not use 'new' for side effects.", + W032: "Unnecessary semicolon.", + W033: "Missing semicolon.", + W034: "Unnecessary directive \"{a}\".", + W035: "Empty block.", + W036: "Unexpected /*member '{a}'.", + W037: "'{a}' is a statement label.", + W038: "'{a}' used out of scope.", + W039: "'{a}' is not allowed.", + W040: "Possible strict violation.", + W041: "Use '{a}' to compare with '{b}'.", + W042: "Avoid EOL escaping.", + W043: "Bad escaping of EOL. Use option multistr if needed.", + W044: "Bad or unnecessary escaping.", /* TODO(caitp): remove W044 */ + W045: "Bad number '{a}'.", + W046: "Don't use extra leading zeros '{a}'.", + W047: "A trailing decimal point can be confused with a dot: '{a}'.", + W048: "Unexpected control character in regular expression.", + W049: "Unexpected escaped character '{a}' in regular expression.", + W050: "JavaScript URL.", + W051: "Variables should not be deleted.", + W052: "Unexpected '{a}'.", + W053: "Do not use {a} as a constructor.", + W054: "The Function constructor is a form of eval.", + W055: "A constructor name should start with an uppercase letter.", + W056: "Bad constructor.", + W057: "Weird construction. Is 'new' necessary?", + W058: "Missing '()' invoking a constructor.", + W059: "Avoid arguments.{a}.", + W060: "document.write can be a form of eval.", + W061: "eval can be harmful.", + W062: "Wrap an immediate function invocation in parens " + + "to assist the reader in understanding that the expression " + + "is the result of a function, and not the function itself.", + W063: "Math is not a function.", + W064: "Missing 'new' prefix when invoking a constructor.", + W065: "Missing radix parameter.", + W066: "Implied eval. Consider passing a function instead of a string.", + W067: "Bad invocation.", + W068: "Wrapping non-IIFE function literals in parens is unnecessary.", + W069: "['{a}'] is better written in dot notation.", + W070: "Extra comma. (it breaks older versions of IE)", + W071: "This function has too many statements. ({a})", + W072: "This function has too many parameters. ({a})", + W073: "Blocks are nested too deeply. ({a})", + W074: "This function's cyclomatic complexity is too high. ({a})", + W075: "Duplicate {a} '{b}'.", + W076: "Unexpected parameter '{a}' in get {b} function.", + W077: "Expected a single parameter in set {a} function.", + W078: "Setter is defined without getter.", + W079: "Redefinition of '{a}'.", + W080: "It's not necessary to initialize '{a}' to 'undefined'.", + W081: null, + W082: "Function declarations should not be placed in blocks. " + + "Use a function expression or move the statement to the top of " + + "the outer function.", + W083: "Don't make functions within a loop.", + W084: "Assignment in conditional expression", + W085: "Don't use 'with'.", + W086: "Expected a 'break' statement before '{a}'.", + W087: "Forgotten 'debugger' statement?", + W088: "Creating global 'for' variable. Should be 'for (var {a} ...'.", + W089: "The body of a for in should be wrapped in an if statement to filter " + + "unwanted properties from the prototype.", + W090: "'{a}' is not a statement label.", + W091: "'{a}' is out of scope.", + W093: "Did you mean to return a conditional instead of an assignment?", + W094: "Unexpected comma.", + W095: "Expected a string and instead saw {a}.", + W096: "The '{a}' key may produce unexpected results.", + W097: "Use the function form of \"use strict\".", + W098: "'{a}' is defined but never used.", + W099: null, + W100: "This character may get silently deleted by one or more browsers.", + W101: "Line is too long.", + W102: null, + W103: "The '{a}' property is deprecated.", + W104: "'{a}' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).", + W105: "Unexpected {a} in '{b}'.", + W106: "Identifier '{a}' is not in camel case.", + W107: "Script URL.", + W108: "Strings must use doublequote.", + W109: "Strings must use singlequote.", + W110: "Mixed double and single quotes.", + W112: "Unclosed string.", + W113: "Control character in string: {a}.", + W114: "Avoid {a}.", + W115: "Octal literals are not allowed in strict mode.", + W116: "Expected '{a}' and instead saw '{b}'.", + W117: "'{a}' is not defined.", + W118: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).", + W119: "'{a}' is only available in ES6 (use esnext option).", + W120: "You might be leaking a variable ({a}) here.", + W121: "Extending prototype of native object: '{a}'.", + W122: "Invalid typeof value '{a}'", + W123: "'{a}' is already defined in outer scope.", + W124: "A generator function shall contain a yield statement.", + W125: "This line contains non-breaking spaces: http://jshint.com/doc/options/#nonbsp", + W126: "Grouping operator is unnecessary for lone expressions.", + W127: "Unexpected use of a comma operator.", + W128: "Empty array elements require elision=true." +}; + +var info = { + I001: "Comma warnings can be turned off with 'laxcomma'.", + I002: null, + I003: "ES5 option is now set per default" +}; + +exports.errors = {}; +exports.warnings = {}; +exports.info = {}; + +_.each(errors, function (desc, code) { + exports.errors[code] = { code: code, desc: desc }; +}); + +_.each(warnings, function (desc, code) { + exports.warnings[code] = { code: code, desc: desc }; +}); + +_.each(info, function (desc, code) { + exports.info[code] = { code: code, desc: desc }; +}); + +}, +{"underscore":2}], +6:[function(_dereq_,module,exports){ +"use strict"; + +function NameStack() { + this._stack = []; +} + +Object.defineProperty(NameStack.prototype, "length", { + get: function() { + return this._stack.length; + } +}); +NameStack.prototype.push = function() { + this._stack.push(null); +}; +NameStack.prototype.pop = function() { + this._stack.pop(); +}; +NameStack.prototype.set = function(token) { + this._stack[this.length - 1] = token; +}; +NameStack.prototype.infer = function() { + var nameToken = this._stack[this.length - 1]; + var prefix = ""; + var type; + if (!nameToken || nameToken.type === "class") { + nameToken = this._stack[this.length - 2]; + } + + if (!nameToken) { + return "(empty)"; + } + + type = nameToken.type; + + if (type !== "(string)" && type !== "(number)" && type !== "(identifier)" && type !== "default") { + return "(expression)"; + } + + if (nameToken.accessorType) { + prefix = nameToken.accessorType + " "; + } + + return prefix + nameToken.value; +}; + +module.exports = NameStack; + +}, +{}], +7:[function(_dereq_,module,exports){ +"use strict"; +exports.bool = { + enforcing: { + bitwise : true, + freeze : true, + camelcase : true, + curly : true, + eqeqeq : true, + notypeof : true, + es3 : true, + es5 : true, + forin : true, + funcscope : true, + globalstrict: true, + immed : true, + iterator : true, + newcap : true, + noarg : true, + nocomma : true, + noempty : true, + nonbsp : true, + nonew : true, + undef : true, + singleGroups: false, + enforceall : false + }, + relaxing: { + asi : true, + multistr : true, + debug : true, + boss : true, + phantom : true, + evil : true, + plusplus : true, + proto : true, + scripturl : true, + strict : true, + sub : true, + supernew : true, + laxbreak : true, + laxcomma : true, + validthis : true, + withstmt : true, + moz : true, + noyield : true, + eqnull : true, + lastsemic : true, + loopfunc : true, + expr : true, + esnext : true, + elision : true, + }, + environments: { + mootools : true, + couch : true, + jasmine : true, + jquery : true, + node : true, + qunit : true, + rhino : true, + shelljs : true, + prototypejs : true, + yui : true, + mocha : true, + wsh : true, + worker : true, + nonstandard : true, + browser : true, + browserify : true, + devel : true, + dojo : true, + typed : true + }, + obsolete: { + onecase : true, // if one case switch statements should be allowed + regexp : true, // if the . should not be allowed in regexp literals + regexdash : true // if unescaped first/last dash (-) inside brackets + } +}; +exports.val = { + maxlen : false, + indent : false, + maxerr : false, + + predef : false, // predef is deprecated and being replaced by globals + globals : false, + quotmark : false, + + scope : false, + maxstatements: false, + maxdepth : false, + maxparams : false, + maxcomplexity: false, + shadow : false, + unused : true, + latedef : false, + + ignore : false, // start/end ignoring lines of code, bypassing the lexer + ignoreDelimiters: false // array of start/end delimiters used to ignore +}; +exports.inverted = { + bitwise : true, + forin : true, + newcap : true, + plusplus: true, + regexp : true, + undef : true, + eqeqeq : true, + strict : true +}; + +exports.validNames = Object.keys(exports.val) + .concat(Object.keys(exports.bool.relaxing)) + .concat(Object.keys(exports.bool.enforcing)) + .concat(Object.keys(exports.bool.obsolete)) + .concat(Object.keys(exports.bool.environments)); +exports.renamed = { + eqeq : "eqeqeq", + windows: "wsh", + sloppy : "strict" +}; + +exports.removed = { + nomen: true, + onevar: true, + passfail: true, + white: true, + gcl: true, + smarttabs: true, + trailing: true +}; + +}, +{}], +8:[function(_dereq_,module,exports){ + +"use strict"; +exports.unsafeString = + /@cc|<\/?|script|\]\s*\]|<\s*!|</i; +exports.unsafeChars = + /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; +exports.needEsc = + /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; + +exports.needEscGlobal = + /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; +exports.starSlash = /\*\//; +exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/; +exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|livescript)\s*:/i; +exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/; +exports.maxlenException = /^(?:(?:\/\/|\/\*|\*) ?)?[^ ]+$/; + +}, +{}], +9:[function(_dereq_,module,exports){ +"use strict"; +var NameStack = _dereq_("./name-stack.js"); + +var state = { + syntax: {}, + + reset: function () { + this.tokens = { + prev: null, + next: null, + curr: null + }; + + this.option = {}; + this.ignored = {}; + this.directive = {}; + this.jsonMode = false; + this.jsonWarnings = []; + this.lines = []; + this.tab = ""; + this.cache = {}; // Node.JS doesn't have Map. Sniff. + this.ignoredLines = {}; + this.forinifcheckneeded = false; + this.nameStack = new NameStack(); + this.ignoreLinterErrors = false; + } +}; + +exports.state = state; + +}, +{"./name-stack.js":6}], +10:[function(_dereq_,module,exports){ +"use strict"; + +exports.register = function (linter) { + + linter.on("Identifier", function style_scanProto(data) { + if (linter.getOption("proto")) { + return; + } + + if (data.name === "__proto__") { + linter.warn("W103", { + line: data.line, + char: data.char, + data: [ data.name ] + }); + } + }); + + linter.on("Identifier", function style_scanIterator(data) { + if (linter.getOption("iterator")) { + return; + } + + if (data.name === "__iterator__") { + linter.warn("W104", { + line: data.line, + char: data.char, + data: [ data.name ] + }); + } + }); + + linter.on("Identifier", function style_scanCamelCase(data) { + if (!linter.getOption("camelcase")) { + return; + } + + if (data.name.replace(/^_+|_+$/g, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) { + linter.warn("W106", { + line: data.line, + char: data.from, + data: [ data.name ] + }); + } + }); + + linter.on("String", function style_scanQuotes(data) { + var quotmark = linter.getOption("quotmark"); + var esnext = linter.getOption("esnext"); + var code; + + if (!quotmark) { + return; + } + if (esnext && data.quote === "`") { + return; + } + + if (quotmark === "single" && data.quote !== "'") { + code = "W109"; + } + + if (quotmark === "double" && data.quote !== "\"") { + code = "W108"; + } + + if (quotmark === true) { + if (!linter.getCache("quotmark")) { + linter.setCache("quotmark", data.quote); + } + + if (linter.getCache("quotmark") !== data.quote) { + code = "W110"; + } + } + + if (code) { + linter.warn(code, { + line: data.line, + char: data.char, + }); + } + }); + + linter.on("Number", function style_scanNumbers(data) { + if (data.value.charAt(0) === ".") { + linter.warn("W008", { + line: data.line, + char: data.char, + data: [ data.value ] + }); + } + + if (data.value.substr(data.value.length - 1) === ".") { + linter.warn("W047", { + line: data.line, + char: data.char, + data: [ data.value ] + }); + } + + if (/^00+/.test(data.value)) { + linter.warn("W046", { + line: data.line, + char: data.char, + data: [ data.value ] + }); + } + }); + + linter.on("String", function style_scanJavaScriptURLs(data) { + var re = /^(?:javascript|jscript|ecmascript|vbscript|livescript)\s*:/i; + + if (linter.getOption("scripturl")) { + return; + } + + if (re.test(data.value)) { + linter.warn("W107", { + line: data.line, + char: data.char + }); + } + }); +}; + +}, +{}], +11:[function(_dereq_,module,exports){ + +"use strict"; + +exports.reservedVars = { + arguments : false, + NaN : false +}; + +exports.ecmaIdentifiers = { + Array : false, + Boolean : false, + Date : false, + decodeURI : false, + decodeURIComponent : false, + encodeURI : false, + encodeURIComponent : false, + Error : false, + "eval" : false, + EvalError : false, + Function : false, + hasOwnProperty : false, + isFinite : false, + isNaN : false, + JSON : false, + Map : false, + Math : false, + Number : false, + Object : false, + Proxy : false, + Promise : false, + parseInt : false, + parseFloat : false, + RangeError : false, + ReferenceError : false, + RegExp : false, + Set : false, + String : false, + SyntaxError : false, + TypeError : false, + URIError : false, + WeakMap : false, + WeakSet : false +}; + +exports.newEcmaIdentifiers = { + Set : false, + Map : false, + WeakMap : false, + WeakSet : false, + Proxy : false, + Promise : false, + Reflect : false, + Symbol : false, + System : false +}; + +exports.browser = { + Audio : false, + Blob : false, + addEventListener : false, + applicationCache : false, + atob : false, + blur : false, + btoa : false, + cancelAnimationFrame : false, + CanvasGradient : false, + CanvasPattern : false, + CanvasRenderingContext2D: false, + CSS : false, + clearInterval : false, + clearTimeout : false, + close : false, + closed : false, + CustomEvent : false, + DOMParser : false, + defaultStatus : false, + Document : false, + document : false, + Element : false, + ElementTimeControl : false, + Event : false, + event : false, + FileReader : false, + FormData : false, + focus : false, + frames : false, + getComputedStyle : false, + HTMLElement : false, + HTMLAnchorElement : false, + HTMLBaseElement : false, + HTMLBlockquoteElement: false, + HTMLBodyElement : false, + HTMLBRElement : false, + HTMLButtonElement : false, + HTMLCanvasElement : false, + HTMLDirectoryElement : false, + HTMLDivElement : false, + HTMLDListElement : false, + HTMLFieldSetElement : false, + HTMLFontElement : false, + HTMLFormElement : false, + HTMLFrameElement : false, + HTMLFrameSetElement : false, + HTMLHeadElement : false, + HTMLHeadingElement : false, + HTMLHRElement : false, + HTMLHtmlElement : false, + HTMLIFrameElement : false, + HTMLImageElement : false, + HTMLInputElement : false, + HTMLIsIndexElement : false, + HTMLLabelElement : false, + HTMLLayerElement : false, + HTMLLegendElement : false, + HTMLLIElement : false, + HTMLLinkElement : false, + HTMLMapElement : false, + HTMLMenuElement : false, + HTMLMetaElement : false, + HTMLModElement : false, + HTMLObjectElement : false, + HTMLOListElement : false, + HTMLOptGroupElement : false, + HTMLOptionElement : false, + HTMLParagraphElement : false, + HTMLParamElement : false, + HTMLPreElement : false, + HTMLQuoteElement : false, + HTMLScriptElement : false, + HTMLSelectElement : false, + HTMLStyleElement : false, + HTMLTableCaptionElement: false, + HTMLTableCellElement : false, + HTMLTableColElement : false, + HTMLTableElement : false, + HTMLTableRowElement : false, + HTMLTableSectionElement: false, + HTMLTextAreaElement : false, + HTMLTitleElement : false, + HTMLUListElement : false, + HTMLVideoElement : false, + history : false, + Image : false, + Intl : false, + length : false, + localStorage : false, + location : false, + matchMedia : false, + MessageChannel : false, + MessageEvent : false, + MessagePort : false, + MouseEvent : false, + moveBy : false, + moveTo : false, + MutationObserver : false, + name : false, + Node : false, + NodeFilter : false, + NodeList : false, + navigator : false, + onbeforeunload : true, + onblur : true, + onerror : true, + onfocus : true, + onload : true, + onresize : true, + onunload : true, + open : false, + openDatabase : false, + opener : false, + Option : false, + parent : false, + print : false, + requestAnimationFrame : false, + removeEventListener : false, + resizeBy : false, + resizeTo : false, + screen : false, + scroll : false, + scrollBy : false, + scrollTo : false, + sessionStorage : false, + setInterval : false, + setTimeout : false, + SharedWorker : false, + status : false, + SVGAElement : false, + SVGAltGlyphDefElement: false, + SVGAltGlyphElement : false, + SVGAltGlyphItemElement: false, + SVGAngle : false, + SVGAnimateColorElement: false, + SVGAnimateElement : false, + SVGAnimateMotionElement: false, + SVGAnimateTransformElement: false, + SVGAnimatedAngle : false, + SVGAnimatedBoolean : false, + SVGAnimatedEnumeration: false, + SVGAnimatedInteger : false, + SVGAnimatedLength : false, + SVGAnimatedLengthList: false, + SVGAnimatedNumber : false, + SVGAnimatedNumberList: false, + SVGAnimatedPathData : false, + SVGAnimatedPoints : false, + SVGAnimatedPreserveAspectRatio: false, + SVGAnimatedRect : false, + SVGAnimatedString : false, + SVGAnimatedTransformList: false, + SVGAnimationElement : false, + SVGCSSRule : false, + SVGCircleElement : false, + SVGClipPathElement : false, + SVGColor : false, + SVGColorProfileElement: false, + SVGColorProfileRule : false, + SVGComponentTransferFunctionElement: false, + SVGCursorElement : false, + SVGDefsElement : false, + SVGDescElement : false, + SVGDocument : false, + SVGElement : false, + SVGElementInstance : false, + SVGElementInstanceList: false, + SVGEllipseElement : false, + SVGExternalResourcesRequired: false, + SVGFEBlendElement : false, + SVGFEColorMatrixElement: false, + SVGFEComponentTransferElement: false, + SVGFECompositeElement: false, + SVGFEConvolveMatrixElement: false, + SVGFEDiffuseLightingElement: false, + SVGFEDisplacementMapElement: false, + SVGFEDistantLightElement: false, + SVGFEFloodElement : false, + SVGFEFuncAElement : false, + SVGFEFuncBElement : false, + SVGFEFuncGElement : false, + SVGFEFuncRElement : false, + SVGFEGaussianBlurElement: false, + SVGFEImageElement : false, + SVGFEMergeElement : false, + SVGFEMergeNodeElement: false, + SVGFEMorphologyElement: false, + SVGFEOffsetElement : false, + SVGFEPointLightElement: false, + SVGFESpecularLightingElement: false, + SVGFESpotLightElement: false, + SVGFETileElement : false, + SVGFETurbulenceElement: false, + SVGFilterElement : false, + SVGFilterPrimitiveStandardAttributes: false, + SVGFitToViewBox : false, + SVGFontElement : false, + SVGFontFaceElement : false, + SVGFontFaceFormatElement: false, + SVGFontFaceNameElement: false, + SVGFontFaceSrcElement: false, + SVGFontFaceUriElement: false, + SVGForeignObjectElement: false, + SVGGElement : false, + SVGGlyphElement : false, + SVGGlyphRefElement : false, + SVGGradientElement : false, + SVGHKernElement : false, + SVGICCColor : false, + SVGImageElement : false, + SVGLangSpace : false, + SVGLength : false, + SVGLengthList : false, + SVGLineElement : false, + SVGLinearGradientElement: false, + SVGLocatable : false, + SVGMPathElement : false, + SVGMarkerElement : false, + SVGMaskElement : false, + SVGMatrix : false, + SVGMetadataElement : false, + SVGMissingGlyphElement: false, + SVGNumber : false, + SVGNumberList : false, + SVGPaint : false, + SVGPathElement : false, + SVGPathSeg : false, + SVGPathSegArcAbs : false, + SVGPathSegArcRel : false, + SVGPathSegClosePath : false, + SVGPathSegCurvetoCubicAbs: false, + SVGPathSegCurvetoCubicRel: false, + SVGPathSegCurvetoCubicSmoothAbs: false, + SVGPathSegCurvetoCubicSmoothRel: false, + SVGPathSegCurvetoQuadraticAbs: false, + SVGPathSegCurvetoQuadraticRel: false, + SVGPathSegCurvetoQuadraticSmoothAbs: false, + SVGPathSegCurvetoQuadraticSmoothRel: false, + SVGPathSegLinetoAbs : false, + SVGPathSegLinetoHorizontalAbs: false, + SVGPathSegLinetoHorizontalRel: false, + SVGPathSegLinetoRel : false, + SVGPathSegLinetoVerticalAbs: false, + SVGPathSegLinetoVerticalRel: false, + SVGPathSegList : false, + SVGPathSegMovetoAbs : false, + SVGPathSegMovetoRel : false, + SVGPatternElement : false, + SVGPoint : false, + SVGPointList : false, + SVGPolygonElement : false, + SVGPolylineElement : false, + SVGPreserveAspectRatio: false, + SVGRadialGradientElement: false, + SVGRect : false, + SVGRectElement : false, + SVGRenderingIntent : false, + SVGSVGElement : false, + SVGScriptElement : false, + SVGSetElement : false, + SVGStopElement : false, + SVGStringList : false, + SVGStylable : false, + SVGStyleElement : false, + SVGSwitchElement : false, + SVGSymbolElement : false, + SVGTRefElement : false, + SVGTSpanElement : false, + SVGTests : false, + SVGTextContentElement: false, + SVGTextElement : false, + SVGTextPathElement : false, + SVGTextPositioningElement: false, + SVGTitleElement : false, + SVGTransform : false, + SVGTransformList : false, + SVGTransformable : false, + SVGURIReference : false, + SVGUnitTypes : false, + SVGUseElement : false, + SVGVKernElement : false, + SVGViewElement : false, + SVGViewSpec : false, + SVGZoomAndPan : false, + TextDecoder : false, + TextEncoder : false, + TimeEvent : false, + top : false, + URL : false, + WebGLActiveInfo : false, + WebGLBuffer : false, + WebGLContextEvent : false, + WebGLFramebuffer : false, + WebGLProgram : false, + WebGLRenderbuffer : false, + WebGLRenderingContext: false, + WebGLShader : false, + WebGLShaderPrecisionFormat: false, + WebGLTexture : false, + WebGLUniformLocation : false, + WebSocket : false, + window : false, + Worker : false, + XDomainRequest : false, + XMLHttpRequest : false, + XMLSerializer : false, + XPathEvaluator : false, + XPathException : false, + XPathExpression : false, + XPathNamespace : false, + XPathNSResolver : false, + XPathResult : false +}; + +exports.devel = { + alert : false, + confirm: false, + console: false, + Debug : false, + opera : false, + prompt : false +}; + +exports.worker = { + importScripts : true, + postMessage : true, + self : true, + FileReaderSync : true +}; +exports.nonstandard = { + escape : false, + unescape: false +}; + +exports.couch = { + "require" : false, + respond : false, + getRow : false, + emit : false, + send : false, + start : false, + sum : false, + log : false, + exports : false, + module : false, + provides : false +}; + +exports.node = { + __filename : false, + __dirname : false, + GLOBAL : false, + global : false, + module : false, + require : false, + + Buffer : true, + console : true, + exports : true, + process : true, + setTimeout : true, + clearTimeout : true, + setInterval : true, + clearInterval : true, + setImmediate : true, // v0.9.1+ + clearImmediate: true // v0.9.1+ +}; + +exports.browserify = { + __filename : false, + __dirname : false, + global : false, + module : false, + require : false, + Buffer : true, + exports : true, + process : true +}; + +exports.phantom = { + phantom : true, + require : true, + WebPage : true, + console : true, // in examples, but undocumented + exports : true // v1.7+ +}; + +exports.qunit = { + asyncTest : false, + deepEqual : false, + equal : false, + expect : false, + module : false, + notDeepEqual : false, + notEqual : false, + notPropEqual : false, + notStrictEqual : false, + ok : false, + propEqual : false, + QUnit : false, + raises : false, + start : false, + stop : false, + strictEqual : false, + test : false, + "throws" : false +}; + +exports.rhino = { + defineClass : false, + deserialize : false, + gc : false, + help : false, + importClass : false, + importPackage: false, + "java" : false, + load : false, + loadClass : false, + Packages : false, + print : false, + quit : false, + readFile : false, + readUrl : false, + runCommand : false, + seal : false, + serialize : false, + spawn : false, + sync : false, + toint32 : false, + version : false +}; + +exports.shelljs = { + target : false, + echo : false, + exit : false, + cd : false, + pwd : false, + ls : false, + find : false, + cp : false, + rm : false, + mv : false, + mkdir : false, + test : false, + cat : false, + sed : false, + grep : false, + which : false, + dirs : false, + pushd : false, + popd : false, + env : false, + exec : false, + chmod : false, + config : false, + error : false, + tempdir : false +}; + +exports.typed = { + ArrayBuffer : false, + ArrayBufferView : false, + DataView : false, + Float32Array : false, + Float64Array : false, + Int16Array : false, + Int32Array : false, + Int8Array : false, + Uint16Array : false, + Uint32Array : false, + Uint8Array : false, + Uint8ClampedArray : false +}; + +exports.wsh = { + ActiveXObject : true, + Enumerator : true, + GetObject : true, + ScriptEngine : true, + ScriptEngineBuildVersion : true, + ScriptEngineMajorVersion : true, + ScriptEngineMinorVersion : true, + VBArray : true, + WSH : true, + WScript : true, + XDomainRequest : true +}; + +exports.dojo = { + dojo : false, + dijit : false, + dojox : false, + define : false, + "require": false +}; + +exports.jquery = { + "$" : false, + jQuery : false +}; + +exports.mootools = { + "$" : false, + "$$" : false, + Asset : false, + Browser : false, + Chain : false, + Class : false, + Color : false, + Cookie : false, + Core : false, + Document : false, + DomReady : false, + DOMEvent : false, + DOMReady : false, + Drag : false, + Element : false, + Elements : false, + Event : false, + Events : false, + Fx : false, + Group : false, + Hash : false, + HtmlTable : false, + IFrame : false, + IframeShim : false, + InputValidator: false, + instanceOf : false, + Keyboard : false, + Locale : false, + Mask : false, + MooTools : false, + Native : false, + Options : false, + OverText : false, + Request : false, + Scroller : false, + Slick : false, + Slider : false, + Sortables : false, + Spinner : false, + Swiff : false, + Tips : false, + Type : false, + typeOf : false, + URI : false, + Window : false +}; + +exports.prototypejs = { + "$" : false, + "$$" : false, + "$A" : false, + "$F" : false, + "$H" : false, + "$R" : false, + "$break" : false, + "$continue" : false, + "$w" : false, + Abstract : false, + Ajax : false, + Class : false, + Enumerable : false, + Element : false, + Event : false, + Field : false, + Form : false, + Hash : false, + Insertion : false, + ObjectRange : false, + PeriodicalExecuter: false, + Position : false, + Prototype : false, + Selector : false, + Template : false, + Toggle : false, + Try : false, + Autocompleter : false, + Builder : false, + Control : false, + Draggable : false, + Draggables : false, + Droppables : false, + Effect : false, + Sortable : false, + SortableObserver : false, + Sound : false, + Scriptaculous : false +}; + +exports.yui = { + YUI : false, + Y : false, + YUI_config: false +}; + +exports.mocha = { + describe : false, + it : false, + before : false, + after : false, + beforeEach : false, + afterEach : false, + suite : false, + test : false, + setup : false, + teardown : false, + suiteSetup : false, + suiteTeardown : false +}; + +exports.jasmine = { + jasmine : false, + describe : false, + it : false, + xit : false, + beforeEach : false, + afterEach : false, + setFixtures : false, + loadFixtures: false, + spyOn : false, + expect : false, + runs : false, + waitsFor : false, + waits : false, + beforeAll : false, + afterAll : false, + fail : false, + fdescribe : false, + fit : false +}; + +}, +{}], +12:[function(_dereq_,module,exports){ + +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; +EventEmitter.defaultMaxListeners = 10; +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + throw TypeError('Uncaught, unspecified "error" event.'); + } + return false; + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + default: + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + handler.apply(this, args); + } + } else if (isObject(handler)) { + len = arguments.length; + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + this._events[type] = listener; + else if (isObject(this._events[type])) + this._events[type].push(listener); + else + this._events[type] = [this._events[type], listener]; + if (isObject(this._events[type]) && !this._events[type].warned) { + var m; + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else { + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.listenerCount = function(emitter, type) { + var ret; + if (!emitter._events || !emitter._events[type]) + ret = 0; + else if (isFunction(emitter._events[type])) + ret = 1; + else + ret = emitter._events[type].length; + return ret; +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +}, +{}]},{},[3]) +(3) + +}); + +define("ace/mode/javascript_worker",["require","exports","module","ace/lib/oop","ace/worker/mirror","ace/mode/javascript/jshint"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var Mirror = require("../worker/mirror").Mirror; +var lint = require("./javascript/jshint").JSHINT; + +function startRegex(arr) { + return RegExp("^(" + arr.join("|") + ")"); +} + +var disabledWarningsRe = startRegex([ + "Bad for in variable '(.+)'.", + 'Missing "use strict"' +]); +var errorsRe = startRegex([ + "Unexpected", + "Expected ", + "Confusing (plus|minus)", + "\\{a\\} unterminated regular expression", + "Unclosed ", + "Unmatched ", + "Unbegun comment", + "Bad invocation", + "Missing space after", + "Missing operator at" +]); +var infoRe = startRegex([ + "Expected an assignment", + "Bad escapement of EOL", + "Unexpected comma", + "Unexpected space", + "Missing radix parameter.", + "A leading decimal point can", + "\\['{a}'\\] is better written in dot notation.", + "'{a}' used out of scope" +]); + +var JavaScriptWorker = exports.JavaScriptWorker = function(sender) { + Mirror.call(this, sender); + this.setTimeout(500); + this.setOptions(); +}; + +oop.inherits(JavaScriptWorker, Mirror); + +(function() { + this.setOptions = function(options) { + this.options = options || { + esnext: true, + moz: true, + devel: true, + browser: true, + node: true, + laxcomma: true, + laxbreak: true, + lastsemic: true, + onevar: false, + passfail: false, + maxerr: 100, + expr: true, + multistr: true, + globalstrict: true + }; + this.doc.getValue() && this.deferredUpdate.schedule(100); + }; + + this.changeOptions = function(newOptions) { + oop.mixin(this.options, newOptions); + this.doc.getValue() && this.deferredUpdate.schedule(100); + }; + + this.isValidJS = function(str) { + try { + eval("throw 0;" + str); + } catch(e) { + if (e === 0) + return true; + } + return false + }; + + this.onUpdate = function() { + var value = this.doc.getValue(); + value = value.replace(/^#!.*\n/, "\n"); + if (!value) + return this.sender.emit("annotate", []); + + var errors = []; + var maxErrorLevel = this.isValidJS(value) ? "warning" : "error"; + lint(value, this.options); + var results = lint.errors; + + var errorAdded = false + for (var i = 0; i < results.length; i++) { + var error = results[i]; + if (!error) + continue; + var raw = error.raw; + var type = "warning"; + + if (raw == "Missing semicolon.") { + var str = error.evidence.substr(error.character); + str = str.charAt(str.search(/\S/)); + if (maxErrorLevel == "error" && str && /[\w\d{(['"]/.test(str)) { + error.reason = 'Missing ";" before statement'; + type = "error"; + } else { + type = "info"; + } + } + else if (disabledWarningsRe.test(raw)) { + continue; + } + else if (infoRe.test(raw)) { + type = "info" + } + else if (errorsRe.test(raw)) { + errorAdded = true; + type = maxErrorLevel; + } + else if (raw == "'{a}' is not defined.") { + type = "warning"; + } + else if (raw == "'{a}' is defined but never used.") { + type = "info"; + } + + errors.push({ + row: error.line-1, + column: error.character-1, + text: error.reason, + type: type, + raw: raw + }); + + if (errorAdded) { + } + } + + this.sender.emit("annotate", errors); + }; + +}).call(JavaScriptWorker.prototype); + +}); + +define("ace/lib/es5-shim",["require","exports","module"], function(require, exports, module) { + +function Empty() {} + +if (!Function.prototype.bind) { + Function.prototype.bind = function bind(that) { // .length is 1 + var target = this; + if (typeof target != "function") { + throw new TypeError("Function.prototype.bind called on incompatible " + target); + } + var args = slice.call(arguments, 1); // for normal call + var bound = function () { + + if (this instanceof bound) { + + var result = target.apply( + this, + args.concat(slice.call(arguments)) + ); + if (Object(result) === result) { + return result; + } + return this; + + } else { + return target.apply( + that, + args.concat(slice.call(arguments)) + ); + + } + + }; + if(target.prototype) { + Empty.prototype = target.prototype; + bound.prototype = new Empty(); + Empty.prototype = null; + } + return bound; + }; +} +var call = Function.prototype.call; +var prototypeOfArray = Array.prototype; +var prototypeOfObject = Object.prototype; +var slice = prototypeOfArray.slice; +var _toString = call.bind(prototypeOfObject.toString); +var owns = call.bind(prototypeOfObject.hasOwnProperty); +var defineGetter; +var defineSetter; +var lookupGetter; +var lookupSetter; +var supportsAccessors; +if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) { + defineGetter = call.bind(prototypeOfObject.__defineGetter__); + defineSetter = call.bind(prototypeOfObject.__defineSetter__); + lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); + lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); +} +if ([1,2].splice(0).length != 2) { + if(function() { // test IE < 9 to splice bug - see issue #138 + function makeArray(l) { + var a = new Array(l+2); + a[0] = a[1] = 0; + return a; + } + var array = [], lengthBefore; + + array.splice.apply(array, makeArray(20)); + array.splice.apply(array, makeArray(26)); + + lengthBefore = array.length; //46 + array.splice(5, 0, "XXX"); // add one element + + lengthBefore + 1 == array.length + + if (lengthBefore + 1 == array.length) { + return true;// has right splice implementation without bugs + } + }()) {//IE 6/7 + var array_splice = Array.prototype.splice; + Array.prototype.splice = function(start, deleteCount) { + if (!arguments.length) { + return []; + } else { + return array_splice.apply(this, [ + start === void 0 ? 0 : start, + deleteCount === void 0 ? (this.length - start) : deleteCount + ].concat(slice.call(arguments, 2))) + } + }; + } else {//IE8 + Array.prototype.splice = function(pos, removeCount){ + var length = this.length; + if (pos > 0) { + if (pos > length) + pos = length; + } else if (pos == void 0) { + pos = 0; + } else if (pos < 0) { + pos = Math.max(length + pos, 0); + } + + if (!(pos+removeCount < length)) + removeCount = length - pos; + + var removed = this.slice(pos, pos+removeCount); + var insert = slice.call(arguments, 2); + var add = insert.length; + if (pos === length) { + if (add) { + this.push.apply(this, insert); + } + } else { + var remove = Math.min(removeCount, length - pos); + var tailOldPos = pos + remove; + var tailNewPos = tailOldPos + add - remove; + var tailCount = length - tailOldPos; + var lengthAfterRemove = length - remove; + + if (tailNewPos < tailOldPos) { // case A + for (var i = 0; i < tailCount; ++i) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } else if (tailNewPos > tailOldPos) { // case B + for (i = tailCount; i--; ) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } // else, add == remove (nothing to do) + + if (add && pos === lengthAfterRemove) { + this.length = lengthAfterRemove; // truncate array + this.push.apply(this, insert); + } else { + this.length = lengthAfterRemove + add; // reserves space + for (i = 0; i < add; ++i) { + this[pos+i] = insert[i]; + } + } + } + return removed; + }; + } +} +if (!Array.isArray) { + Array.isArray = function isArray(obj) { + return _toString(obj) == "[object Array]"; + }; +} +var boxedString = Object("a"), + splitString = boxedString[0] != "a" || !(0 in boxedString); + +if (!Array.prototype.forEach) { + Array.prototype.forEach = function forEach(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + thisp = arguments[1], + i = -1, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + while (++i < length) { + if (i in self) { + fun.call(thisp, self[i], i, object); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function map(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = Array(length), + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) + result[i] = fun.call(thisp, self[i], i, object); + } + return result; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function filter(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = [], + value, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) { + value = self[i]; + if (fun.call(thisp, value, i, object)) { + result.push(value); + } + } + } + return result; + }; +} +if (!Array.prototype.every) { + Array.prototype.every = function every(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && !fun.call(thisp, self[i], i, object)) { + return false; + } + } + return true; + }; +} +if (!Array.prototype.some) { + Array.prototype.some = function some(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, object)) { + return true; + } + } + return false; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function reduce(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduce of empty array with no initial value"); + } + + var i = 0; + var result; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i++]; + break; + } + if (++i >= length) { + throw new TypeError("reduce of empty array with no initial value"); + } + } while (true); + } + + for (; i < length; i++) { + if (i in self) { + result = fun.call(void 0, result, self[i], i, object); + } + } + + return result; + }; +} +if (!Array.prototype.reduceRight) { + Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + + var result, i = length - 1; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i--]; + break; + } + if (--i < 0) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + } while (true); + } + + do { + if (i in this) { + result = fun.call(void 0, result, self[i], i, object); + } + } while (i--); + + return result; + }; +} +if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) { + Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + + var i = 0; + if (arguments.length > 1) { + i = toInteger(arguments[1]); + } + i = i >= 0 ? i : Math.max(0, length + i); + for (; i < length; i++) { + if (i in self && self[i] === sought) { + return i; + } + } + return -1; + }; +} +if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) { + Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + var i = length - 1; + if (arguments.length > 1) { + i = Math.min(i, toInteger(arguments[1])); + } + i = i >= 0 ? i : length - Math.abs(i); + for (; i >= 0; i--) { + if (i in self && sought === self[i]) { + return i; + } + } + return -1; + }; +} +if (!Object.getPrototypeOf) { + Object.getPrototypeOf = function getPrototypeOf(object) { + return object.__proto__ || ( + object.constructor ? + object.constructor.prototype : + prototypeOfObject + ); + }; +} +if (!Object.getOwnPropertyDescriptor) { + var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + + "non-object: "; + Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT + object); + if (!owns(object, property)) + return; + + var descriptor, getter, setter; + descriptor = { enumerable: true, configurable: true }; + if (supportsAccessors) { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + + var getter = lookupGetter(object, property); + var setter = lookupSetter(object, property); + object.__proto__ = prototype; + + if (getter || setter) { + if (getter) descriptor.get = getter; + if (setter) descriptor.set = setter; + return descriptor; + } + } + descriptor.value = object[property]; + return descriptor; + }; +} +if (!Object.getOwnPropertyNames) { + Object.getOwnPropertyNames = function getOwnPropertyNames(object) { + return Object.keys(object); + }; +} +if (!Object.create) { + var createEmpty; + if (Object.prototype.__proto__ === null) { + createEmpty = function () { + return { "__proto__": null }; + }; + } else { + createEmpty = function () { + var empty = {}; + for (var i in empty) + empty[i] = null; + empty.constructor = + empty.hasOwnProperty = + empty.propertyIsEnumerable = + empty.isPrototypeOf = + empty.toLocaleString = + empty.toString = + empty.valueOf = + empty.__proto__ = null; + return empty; + } + } + + Object.create = function create(prototype, properties) { + var object; + if (prototype === null) { + object = createEmpty(); + } else { + if (typeof prototype != "object") + throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); + var Type = function () {}; + Type.prototype = prototype; + object = new Type(); + object.__proto__ = prototype; + } + if (properties !== void 0) + Object.defineProperties(object, properties); + return object; + }; +} + +function doesDefinePropertyWork(object) { + try { + Object.defineProperty(object, "sentinel", {}); + return "sentinel" in object; + } catch (exception) { + } +} +if (Object.defineProperty) { + var definePropertyWorksOnObject = doesDefinePropertyWork({}); + var definePropertyWorksOnDom = typeof document == "undefined" || + doesDefinePropertyWork(document.createElement("div")); + if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { + var definePropertyFallback = Object.defineProperty; + } +} + +if (!Object.defineProperty || definePropertyFallback) { + var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; + var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " + var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + + "on this javascript engine"; + + Object.defineProperty = function defineProperty(object, property, descriptor) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT_TARGET + object); + if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) + throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); + if (definePropertyFallback) { + try { + return definePropertyFallback.call(Object, object, property, descriptor); + } catch (exception) { + } + } + if (owns(descriptor, "value")) { + + if (supportsAccessors && (lookupGetter(object, property) || + lookupSetter(object, property))) + { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + delete object[property]; + object[property] = descriptor.value; + object.__proto__ = prototype; + } else { + object[property] = descriptor.value; + } + } else { + if (!supportsAccessors) + throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); + if (owns(descriptor, "get")) + defineGetter(object, property, descriptor.get); + if (owns(descriptor, "set")) + defineSetter(object, property, descriptor.set); + } + + return object; + }; +} +if (!Object.defineProperties) { + Object.defineProperties = function defineProperties(object, properties) { + for (var property in properties) { + if (owns(properties, property)) + Object.defineProperty(object, property, properties[property]); + } + return object; + }; +} +if (!Object.seal) { + Object.seal = function seal(object) { + return object; + }; +} +if (!Object.freeze) { + Object.freeze = function freeze(object) { + return object; + }; +} +try { + Object.freeze(function () {}); +} catch (exception) { + Object.freeze = (function freeze(freezeObject) { + return function freeze(object) { + if (typeof object == "function") { + return object; + } else { + return freezeObject(object); + } + }; + })(Object.freeze); +} +if (!Object.preventExtensions) { + Object.preventExtensions = function preventExtensions(object) { + return object; + }; +} +if (!Object.isSealed) { + Object.isSealed = function isSealed(object) { + return false; + }; +} +if (!Object.isFrozen) { + Object.isFrozen = function isFrozen(object) { + return false; + }; +} +if (!Object.isExtensible) { + Object.isExtensible = function isExtensible(object) { + if (Object(object) === object) { + throw new TypeError(); // TODO message + } + var name = ''; + while (owns(object, name)) { + name += '?'; + } + object[name] = true; + var returnValue = owns(object, name); + delete object[name]; + return returnValue; + }; +} +if (!Object.keys) { + var hasDontEnumBug = true, + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + dontEnumsLength = dontEnums.length; + + for (var key in {"toString": null}) { + hasDontEnumBug = false; + } + + Object.keys = function keys(object) { + + if ( + (typeof object != "object" && typeof object != "function") || + object === null + ) { + throw new TypeError("Object.keys called on a non-object"); + } + + var keys = []; + for (var name in object) { + if (owns(object, name)) { + keys.push(name); + } + } + + if (hasDontEnumBug) { + for (var i = 0, ii = dontEnumsLength; i < ii; i++) { + var dontEnum = dontEnums[i]; + if (owns(object, dontEnum)) { + keys.push(dontEnum); + } + } + } + return keys; + }; + +} +if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; +} +var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + + "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + + "\u2029\uFEFF"; +if (!String.prototype.trim || ws.trim()) { + ws = "[" + ws + "]"; + var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), + trimEndRegexp = new RegExp(ws + ws + "*$"); + String.prototype.trim = function trim() { + return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); + }; +} + +function toInteger(n) { + n = +n; + if (n !== n) { // isNaN + n = 0; + } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + return n; +} + +function isPrimitive(input) { + var type = typeof input; + return ( + input === null || + type === "undefined" || + type === "boolean" || + type === "number" || + type === "string" + ); +} + +function toPrimitive(input) { + var val, valueOf, toString; + if (isPrimitive(input)) { + return input; + } + valueOf = input.valueOf; + if (typeof valueOf === "function") { + val = valueOf.call(input); + if (isPrimitive(val)) { + return val; + } + } + toString = input.toString; + if (typeof toString === "function") { + val = toString.call(input); + if (isPrimitive(val)) { + return val; + } + } + throw new TypeError(); +} +var toObject = function (o) { + if (o == null) { // this matches both null and undefined + throw new TypeError("can't convert "+o+" to object"); + } + return Object(o); +}; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/ace/worker-json.js b/Patent2Net/media/graph-recipes/app/assets/ace/worker-json.js new file mode 100644 index 00000000..de02bf20 --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/ace/worker-json.js @@ -0,0 +1,2318 @@ +"no use strict"; +;(function(window) { +if (typeof window.window != "undefined" && window.document) { + return; +} + +window.console = function() { + var msgs = Array.prototype.slice.call(arguments, 0); + postMessage({type: "log", data: msgs}); +}; +window.console.error = +window.console.warn = +window.console.log = +window.console.trace = window.console; + +window.window = window; +window.ace = window; + +window.onerror = function(message, file, line, col, err) { + postMessage({type: "error", data: { + message: message, + file: file, + line: line, + col: col, + stack: err.stack + }}); +}; + +window.normalizeModule = function(parentId, moduleName) { + // normalize plugin requires + if (moduleName.indexOf("!") !== -1) { + var chunks = moduleName.split("!"); + return window.normalizeModule(parentId, chunks[0]) + "!" + window.normalizeModule(parentId, chunks[1]); + } + // normalize relative requires + if (moduleName.charAt(0) == ".") { + var base = parentId.split("/").slice(0, -1).join("/"); + moduleName = (base ? base + "/" : "") + moduleName; + + while(moduleName.indexOf(".") !== -1 && previous != moduleName) { + var previous = moduleName; + moduleName = moduleName.replace(/^\.\//, "").replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); + } + } + + return moduleName; +}; + +window.require = function(parentId, id) { + if (!id) { + id = parentId; + parentId = null; + } + if (!id.charAt) + throw new Error("worker.js require() accepts only (parentId, id) as arguments"); + + id = window.normalizeModule(parentId, id); + + var module = window.require.modules[id]; + if (module) { + if (!module.initialized) { + module.initialized = true; + module.exports = module.factory().exports; + } + return module.exports; + } + + var chunks = id.split("/"); + if (!window.require.tlns) + return console.log("unable to load " + id); + chunks[0] = window.require.tlns[chunks[0]] || chunks[0]; + var path = chunks.join("/") + ".js"; + + window.require.id = id; + importScripts(path); + return window.require(parentId, id); +}; +window.require.modules = {}; +window.require.tlns = {}; + +window.define = function(id, deps, factory) { + if (arguments.length == 2) { + factory = deps; + if (typeof id != "string") { + deps = id; + id = window.require.id; + } + } else if (arguments.length == 1) { + factory = id; + deps = []; + id = window.require.id; + } + + if (typeof factory != "function") { + window.require.modules[id] = { + exports: factory, + initialized: true + }; + return; + } + + if (!deps.length) + // If there is no dependencies, we inject 'require', 'exports' and + // 'module' as dependencies, to provide CommonJS compatibility. + deps = ['require', 'exports', 'module']; + + var req = function(childId) { + return window.require(id, childId); + }; + + window.require.modules[id] = { + exports: {}, + factory: function() { + var module = this; + var returnExports = factory.apply(this, deps.map(function(dep) { + switch(dep) { + // Because 'require', 'exports' and 'module' aren't actual + // dependencies, we must handle them seperately. + case 'require': return req; + case 'exports': return module.exports; + case 'module': return module; + // But for all other dependencies, we can just go ahead and + // require them. + default: return req(dep); + } + })); + if (returnExports) + module.exports = returnExports; + return module; + } + }; +}; +window.define.amd = {}; + +window.initBaseUrls = function initBaseUrls(topLevelNamespaces) { + require.tlns = topLevelNamespaces; +}; + +window.initSender = function initSender() { + + var EventEmitter = window.require("ace/lib/event_emitter").EventEmitter; + var oop = window.require("ace/lib/oop"); + + var Sender = function() {}; + + (function() { + + oop.implement(this, EventEmitter); + + this.callback = function(data, callbackId) { + postMessage({ + type: "call", + id: callbackId, + data: data + }); + }; + + this.emit = function(name, data) { + postMessage({ + type: "event", + name: name, + data: data + }); + }; + + }).call(Sender.prototype); + + return new Sender(); +}; + +var main = window.main = null; +var sender = window.sender = null; + +window.onmessage = function(e) { + var msg = e.data; + if (msg.command) { + if (main[msg.command]) + main[msg.command].apply(main, msg.args); + else + throw new Error("Unknown command:" + msg.command); + } + else if (msg.init) { + initBaseUrls(msg.tlns); + require("ace/lib/es5-shim"); + sender = window.sender = initSender(); + var clazz = require(msg.module)[msg.classname]; + main = window.main = new clazz(sender); + } + else if (msg.event && sender) { + sender._signal(msg.event, msg.data); + } +}; +})(this); + +define("ace/lib/oop",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.inherits = function(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); +}; + +exports.mixin = function(obj, mixin) { + for (var key in mixin) { + obj[key] = mixin[key]; + } + return obj; +}; + +exports.implement = function(proto, mixin) { + exports.mixin(proto, mixin); +}; + +}); + +define("ace/lib/event_emitter",["require","exports","module"], function(require, exports, module) { +"use strict"; + +var EventEmitter = {}; +var stopPropagation = function() { this.propagationStopped = true; }; +var preventDefault = function() { this.defaultPrevented = true; }; + +EventEmitter._emit = +EventEmitter._dispatchEvent = function(eventName, e) { + this._eventRegistry || (this._eventRegistry = {}); + this._defaultHandlers || (this._defaultHandlers = {}); + + var listeners = this._eventRegistry[eventName] || []; + var defaultHandler = this._defaultHandlers[eventName]; + if (!listeners.length && !defaultHandler) + return; + + if (typeof e != "object" || !e) + e = {}; + + if (!e.type) + e.type = eventName; + if (!e.stopPropagation) + e.stopPropagation = stopPropagation; + if (!e.preventDefault) + e.preventDefault = preventDefault; + + listeners = listeners.slice(); + for (var i=0; i [" + this.end.row + "/" + this.end.column + "]"); + }; + + this.contains = function(row, column) { + return this.compare(row, column) == 0; + }; + this.compareRange = function(range) { + var cmp, + end = range.end, + start = range.start; + + cmp = this.compare(end.row, end.column); + if (cmp == 1) { + cmp = this.compare(start.row, start.column); + if (cmp == 1) { + return 2; + } else if (cmp == 0) { + return 1; + } else { + return 0; + } + } else if (cmp == -1) { + return -2; + } else { + cmp = this.compare(start.row, start.column); + if (cmp == -1) { + return -1; + } else if (cmp == 1) { + return 42; + } else { + return 0; + } + } + }; + this.comparePoint = function(p) { + return this.compare(p.row, p.column); + }; + this.containsRange = function(range) { + return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; + }; + this.intersects = function(range) { + var cmp = this.compareRange(range); + return (cmp == -1 || cmp == 0 || cmp == 1); + }; + this.isEnd = function(row, column) { + return this.end.row == row && this.end.column == column; + }; + this.isStart = function(row, column) { + return this.start.row == row && this.start.column == column; + }; + this.setStart = function(row, column) { + if (typeof row == "object") { + this.start.column = row.column; + this.start.row = row.row; + } else { + this.start.row = row; + this.start.column = column; + } + }; + this.setEnd = function(row, column) { + if (typeof row == "object") { + this.end.column = row.column; + this.end.row = row.row; + } else { + this.end.row = row; + this.end.column = column; + } + }; + this.inside = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column) || this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideStart = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideEnd = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.compare = function(row, column) { + if (!this.isMultiLine()) { + if (row === this.start.row) { + return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); + }; + } + + if (row < this.start.row) + return -1; + + if (row > this.end.row) + return 1; + + if (this.start.row === row) + return column >= this.start.column ? 0 : -1; + + if (this.end.row === row) + return column <= this.end.column ? 0 : 1; + + return 0; + }; + this.compareStart = function(row, column) { + if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.compareEnd = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else { + return this.compare(row, column); + } + }; + this.compareInside = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.clipRows = function(firstRow, lastRow) { + if (this.end.row > lastRow) + var end = {row: lastRow + 1, column: 0}; + else if (this.end.row < firstRow) + var end = {row: firstRow, column: 0}; + + if (this.start.row > lastRow) + var start = {row: lastRow + 1, column: 0}; + else if (this.start.row < firstRow) + var start = {row: firstRow, column: 0}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + this.extend = function(row, column) { + var cmp = this.compare(row, column); + + if (cmp == 0) + return this; + else if (cmp == -1) + var start = {row: row, column: column}; + else + var end = {row: row, column: column}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + + this.isEmpty = function() { + return (this.start.row === this.end.row && this.start.column === this.end.column); + }; + this.isMultiLine = function() { + return (this.start.row !== this.end.row); + }; + this.clone = function() { + return Range.fromPoints(this.start, this.end); + }; + this.collapseRows = function() { + if (this.end.column == 0) + return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) + else + return new Range(this.start.row, 0, this.end.row, 0) + }; + this.toScreenRange = function(session) { + var screenPosStart = session.documentToScreenPosition(this.start); + var screenPosEnd = session.documentToScreenPosition(this.end); + + return new Range( + screenPosStart.row, screenPosStart.column, + screenPosEnd.row, screenPosEnd.column + ); + }; + this.moveBy = function(row, column) { + this.start.row += row; + this.start.column += column; + this.end.row += row; + this.end.column += column; + }; + +}).call(Range.prototype); +Range.fromPoints = function(start, end) { + return new Range(start.row, start.column, end.row, end.column); +}; +Range.comparePoints = comparePoints; + +Range.comparePoints = function(p1, p2) { + return p1.row - p2.row || p1.column - p2.column; +}; + + +exports.Range = Range; +}); + +define("ace/anchor",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; + +var Anchor = exports.Anchor = function(doc, row, column) { + this.$onChange = this.onChange.bind(this); + this.attach(doc); + + if (typeof column == "undefined") + this.setPosition(row.row, row.column); + else + this.setPosition(row, column); +}; + +(function() { + + oop.implement(this, EventEmitter); + this.getPosition = function() { + return this.$clipPositionToDocument(this.row, this.column); + }; + this.getDocument = function() { + return this.document; + }; + this.$insertRight = false; + this.onChange = function(e) { + var delta = e.data; + var range = delta.range; + + if (range.start.row == range.end.row && range.start.row != this.row) + return; + + if (range.start.row > this.row) + return; + + if (range.start.row == this.row && range.start.column > this.column) + return; + + var row = this.row; + var column = this.column; + var start = range.start; + var end = range.end; + + if (delta.action === "insertText") { + if (start.row === row && start.column <= column) { + if (start.column === column && this.$insertRight) { + } else if (start.row === end.row) { + column += end.column - start.column; + } else { + column -= start.column; + row += end.row - start.row; + } + } else if (start.row !== end.row && start.row < row) { + row += end.row - start.row; + } + } else if (delta.action === "insertLines") { + if (start.row === row && column === 0 && this.$insertRight) { + } + else if (start.row <= row) { + row += end.row - start.row; + } + } else if (delta.action === "removeText") { + if (start.row === row && start.column < column) { + if (end.column >= column) + column = start.column; + else + column = Math.max(0, column - (end.column - start.column)); + + } else if (start.row !== end.row && start.row < row) { + if (end.row === row) + column = Math.max(0, column - end.column) + start.column; + row -= (end.row - start.row); + } else if (end.row === row) { + row -= end.row - start.row; + column = Math.max(0, column - end.column) + start.column; + } + } else if (delta.action == "removeLines") { + if (start.row <= row) { + if (end.row <= row) + row -= end.row - start.row; + else { + row = start.row; + column = 0; + } + } + } + + this.setPosition(row, column, true); + }; + this.setPosition = function(row, column, noClip) { + var pos; + if (noClip) { + pos = { + row: row, + column: column + }; + } else { + pos = this.$clipPositionToDocument(row, column); + } + + if (this.row == pos.row && this.column == pos.column) + return; + + var old = { + row: this.row, + column: this.column + }; + + this.row = pos.row; + this.column = pos.column; + this._signal("change", { + old: old, + value: pos + }); + }; + this.detach = function() { + this.document.removeEventListener("change", this.$onChange); + }; + this.attach = function(doc) { + this.document = doc || this.document; + this.document.on("change", this.$onChange); + }; + this.$clipPositionToDocument = function(row, column) { + var pos = {}; + + if (row >= this.document.getLength()) { + pos.row = Math.max(0, this.document.getLength() - 1); + pos.column = this.document.getLine(pos.row).length; + } + else if (row < 0) { + pos.row = 0; + pos.column = 0; + } + else { + pos.row = row; + pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); + } + + if (column < 0) + pos.column = 0; + + return pos; + }; + +}).call(Anchor.prototype); + +}); + +define("ace/document",["require","exports","module","ace/lib/oop","ace/lib/event_emitter","ace/range","ace/anchor"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var Range = require("./range").Range; +var Anchor = require("./anchor").Anchor; + +var Document = function(text) { + this.$lines = []; + if (text.length === 0) { + this.$lines = [""]; + } else if (Array.isArray(text)) { + this._insertLines(0, text); + } else { + this.insert({row: 0, column:0}, text); + } +}; + +(function() { + + oop.implement(this, EventEmitter); + this.setValue = function(text) { + var len = this.getLength(); + this.remove(new Range(0, 0, len, this.getLine(len-1).length)); + this.insert({row: 0, column:0}, text); + }; + this.getValue = function() { + return this.getAllLines().join(this.getNewLineCharacter()); + }; + this.createAnchor = function(row, column) { + return new Anchor(this, row, column); + }; + if ("aaa".split(/a/).length === 0) + this.$split = function(text) { + return text.replace(/\r\n|\r/g, "\n").split("\n"); + }; + else + this.$split = function(text) { + return text.split(/\r\n|\r|\n/); + }; + + + this.$detectNewLine = function(text) { + var match = text.match(/^.*?(\r\n|\r|\n)/m); + this.$autoNewLine = match ? match[1] : "\n"; + this._signal("changeNewLineMode"); + }; + this.getNewLineCharacter = function() { + switch (this.$newLineMode) { + case "windows": + return "\r\n"; + case "unix": + return "\n"; + default: + return this.$autoNewLine || "\n"; + } + }; + + this.$autoNewLine = ""; + this.$newLineMode = "auto"; + this.setNewLineMode = function(newLineMode) { + if (this.$newLineMode === newLineMode) + return; + + this.$newLineMode = newLineMode; + this._signal("changeNewLineMode"); + }; + this.getNewLineMode = function() { + return this.$newLineMode; + }; + this.isNewLine = function(text) { + return (text == "\r\n" || text == "\r" || text == "\n"); + }; + this.getLine = function(row) { + return this.$lines[row] || ""; + }; + this.getLines = function(firstRow, lastRow) { + return this.$lines.slice(firstRow, lastRow + 1); + }; + this.getAllLines = function() { + return this.getLines(0, this.getLength()); + }; + this.getLength = function() { + return this.$lines.length; + }; + this.getTextRange = function(range) { + if (range.start.row == range.end.row) { + return this.getLine(range.start.row) + .substring(range.start.column, range.end.column); + } + var lines = this.getLines(range.start.row, range.end.row); + lines[0] = (lines[0] || "").substring(range.start.column); + var l = lines.length - 1; + if (range.end.row - range.start.row == l) + lines[l] = lines[l].substring(0, range.end.column); + return lines.join(this.getNewLineCharacter()); + }; + + this.$clipPosition = function(position) { + var length = this.getLength(); + if (position.row >= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length-1).length; + } else if (position.row < 0) + position.row = 0; + return position; + }; + this.insert = function(position, text) { + if (!text || text.length === 0) + return position; + + position = this.$clipPosition(position); + if (this.getLength() <= 1) + this.$detectNewLine(text); + + var lines = this.$split(text); + var firstLine = lines.splice(0, 1)[0]; + var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0]; + + position = this.insertInLine(position, firstLine); + if (lastLine !== null) { + position = this.insertNewLine(position); // terminate first line + position = this._insertLines(position.row, lines); + position = this.insertInLine(position, lastLine || ""); + } + return position; + }; + this.insertLines = function(row, lines) { + if (row >= this.getLength()) + return this.insert({row: row, column: 0}, "\n" + lines.join("\n")); + return this._insertLines(Math.max(row, 0), lines); + }; + this._insertLines = function(row, lines) { + if (lines.length == 0) + return {row: row, column: 0}; + while (lines.length > 20000) { + var end = this._insertLines(row, lines.slice(0, 20000)); + lines = lines.slice(20000); + row = end.row; + } + + var args = [row, 0]; + args.push.apply(args, lines); + this.$lines.splice.apply(this.$lines, args); + + var range = new Range(row, 0, row + lines.length, 0); + var delta = { + action: "insertLines", + range: range, + lines: lines + }; + this._signal("change", { data: delta }); + return range.end; + }; + this.insertNewLine = function(position) { + position = this.$clipPosition(position); + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column); + this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length)); + + var end = { + row : position.row + 1, + column : 0 + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: this.getNewLineCharacter() + }; + this._signal("change", { data: delta }); + + return end; + }; + this.insertInLine = function(position, text) { + if (text.length == 0) + return position; + + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column) + text + + line.substring(position.column); + + var end = { + row : position.row, + column : position.column + text.length + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: text + }; + this._signal("change", { data: delta }); + + return end; + }; + this.remove = function(range) { + if (!(range instanceof Range)) + range = Range.fromPoints(range.start, range.end); + range.start = this.$clipPosition(range.start); + range.end = this.$clipPosition(range.end); + + if (range.isEmpty()) + return range.start; + + var firstRow = range.start.row; + var lastRow = range.end.row; + + if (range.isMultiLine()) { + var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1; + var lastFullRow = lastRow - 1; + + if (range.end.column > 0) + this.removeInLine(lastRow, 0, range.end.column); + + if (lastFullRow >= firstFullRow) + this._removeLines(firstFullRow, lastFullRow); + + if (firstFullRow != firstRow) { + this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length); + this.removeNewLine(range.start.row); + } + } + else { + this.removeInLine(firstRow, range.start.column, range.end.column); + } + return range.start; + }; + this.removeInLine = function(row, startColumn, endColumn) { + if (startColumn == endColumn) + return; + + var range = new Range(row, startColumn, row, endColumn); + var line = this.getLine(row); + var removed = line.substring(startColumn, endColumn); + var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length); + this.$lines.splice(row, 1, newLine); + + var delta = { + action: "removeText", + range: range, + text: removed + }; + this._signal("change", { data: delta }); + return range.start; + }; + this.removeLines = function(firstRow, lastRow) { + if (firstRow < 0 || lastRow >= this.getLength()) + return this.remove(new Range(firstRow, 0, lastRow + 1, 0)); + return this._removeLines(firstRow, lastRow); + }; + + this._removeLines = function(firstRow, lastRow) { + var range = new Range(firstRow, 0, lastRow + 1, 0); + var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1); + + var delta = { + action: "removeLines", + range: range, + nl: this.getNewLineCharacter(), + lines: removed + }; + this._signal("change", { data: delta }); + return removed; + }; + this.removeNewLine = function(row) { + var firstLine = this.getLine(row); + var secondLine = this.getLine(row+1); + + var range = new Range(row, firstLine.length, row+1, 0); + var line = firstLine + secondLine; + + this.$lines.splice(row, 2, line); + + var delta = { + action: "removeText", + range: range, + text: this.getNewLineCharacter() + }; + this._signal("change", { data: delta }); + }; + this.replace = function(range, text) { + if (!(range instanceof Range)) + range = Range.fromPoints(range.start, range.end); + if (text.length == 0 && range.isEmpty()) + return range.start; + if (text == this.getTextRange(range)) + return range.end; + + this.remove(range); + if (text) { + var end = this.insert(range.start, text); + } + else { + end = range.start; + } + + return end; + }; + this.applyDeltas = function(deltas) { + for (var i=0; i=0; i--) { + var delta = deltas[i]; + + var range = Range.fromPoints(delta.range.start, delta.range.end); + + if (delta.action == "insertLines") + this._removeLines(range.start.row, range.end.row - 1); + else if (delta.action == "insertText") + this.remove(range); + else if (delta.action == "removeLines") + this._insertLines(range.start.row, delta.lines); + else if (delta.action == "removeText") + this.insert(range.start, delta.text); + } + }; + this.indexToPosition = function(index, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + for (var i = startRow || 0, l = lines.length; i < l; i++) { + index -= lines[i].length + newlineLength; + if (index < 0) + return {row: i, column: index + lines[i].length + newlineLength}; + } + return {row: l-1, column: lines[l-1].length}; + }; + this.positionToIndex = function(pos, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + var index = 0; + var row = Math.min(pos.row, lines.length); + for (var i = startRow || 0; i < row; ++i) + index += lines[i].length + newlineLength; + + return index + pos.column; + }; + +}).call(Document.prototype); + +exports.Document = Document; +}); + +define("ace/lib/lang",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.last = function(a) { + return a[a.length - 1]; +}; + +exports.stringReverse = function(string) { + return string.split("").reverse().join(""); +}; + +exports.stringRepeat = function (string, count) { + var result = ''; + while (count > 0) { + if (count & 1) + result += string; + + if (count >>= 1) + string += string; + } + return result; +}; + +var trimBeginRegexp = /^\s\s*/; +var trimEndRegexp = /\s\s*$/; + +exports.stringTrimLeft = function (string) { + return string.replace(trimBeginRegexp, ''); +}; + +exports.stringTrimRight = function (string) { + return string.replace(trimEndRegexp, ''); +}; + +exports.copyObject = function(obj) { + var copy = {}; + for (var key in obj) { + copy[key] = obj[key]; + } + return copy; +}; + +exports.copyArray = function(array){ + var copy = []; + for (var i=0, l=array.length; i= '0' && ch <= '9') { + string += ch; + next(); + } + if (ch === '.') { + string += '.'; + while (next() && ch >= '0' && ch <= '9') { + string += ch; + } + } + if (ch === 'e' || ch === 'E') { + string += ch; + next(); + if (ch === '-' || ch === '+') { + string += ch; + next(); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + } + number = +string; + if (isNaN(number)) { + error("Bad number"); + } else { + return number; + } + }, + + string = function () { + + var hex, + i, + string = '', + uffff; + + if (ch === '"') { + while (next()) { + if (ch === '"') { + next(); + return string; + } else if (ch === '\\') { + next(); + if (ch === 'u') { + uffff = 0; + for (i = 0; i < 4; i += 1) { + hex = parseInt(next(), 16); + if (!isFinite(hex)) { + break; + } + uffff = uffff * 16 + hex; + } + string += String.fromCharCode(uffff); + } else if (typeof escapee[ch] === 'string') { + string += escapee[ch]; + } else { + break; + } + } else { + string += ch; + } + } + } + error("Bad string"); + }, + + white = function () { + + while (ch && ch <= ' ') { + next(); + } + }, + + word = function () { + + switch (ch) { + case 't': + next('t'); + next('r'); + next('u'); + next('e'); + return true; + case 'f': + next('f'); + next('a'); + next('l'); + next('s'); + next('e'); + return false; + case 'n': + next('n'); + next('u'); + next('l'); + next('l'); + return null; + } + error("Unexpected '" + ch + "'"); + }, + + value, // Place holder for the value function. + + array = function () { + + var array = []; + + if (ch === '[') { + next('['); + white(); + if (ch === ']') { + next(']'); + return array; // empty array + } + while (ch) { + array.push(value()); + white(); + if (ch === ']') { + next(']'); + return array; + } + next(','); + white(); + } + } + error("Bad array"); + }, + + object = function () { + + var key, + object = {}; + + if (ch === '{') { + next('{'); + white(); + if (ch === '}') { + next('}'); + return object; // empty object + } + while (ch) { + key = string(); + white(); + next(':'); + if (Object.hasOwnProperty.call(object, key)) { + error('Duplicate key "' + key + '"'); + } + object[key] = value(); + white(); + if (ch === '}') { + next('}'); + return object; + } + next(','); + white(); + } + } + error("Bad object"); + }; + + value = function () { + + white(); + switch (ch) { + case '{': + return object(); + case '[': + return array(); + case '"': + return string(); + case '-': + return number(); + default: + return ch >= '0' && ch <= '9' ? number() : word(); + } + }; + + return function (source, reviver) { + var result; + + text = source; + at = 0; + ch = ' '; + result = value(); + white(); + if (ch) { + error("Syntax error"); + } + + return typeof reviver === 'function' ? function walk(holder, key) { + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + }({'': result}, '') : result; + }; +}); + +define("ace/mode/json_worker",["require","exports","module","ace/lib/oop","ace/worker/mirror","ace/mode/json/json_parse"], function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var Mirror = require("../worker/mirror").Mirror; +var parse = require("./json/json_parse"); + +var JsonWorker = exports.JsonWorker = function(sender) { + Mirror.call(this, sender); + this.setTimeout(200); +}; + +oop.inherits(JsonWorker, Mirror); + +(function() { + + this.onUpdate = function() { + var value = this.doc.getValue(); + var errors = []; + try { + if (value) + parse(value); + } catch (e) { + var pos = this.doc.indexToPosition(e.at-1); + errors.push({ + row: pos.row, + column: pos.column, + text: e.message, + type: "error" + }); + } + this.sender.emit("annotate", errors); + }; + +}).call(JsonWorker.prototype); + +}); + +define("ace/lib/es5-shim",["require","exports","module"], function(require, exports, module) { + +function Empty() {} + +if (!Function.prototype.bind) { + Function.prototype.bind = function bind(that) { // .length is 1 + var target = this; + if (typeof target != "function") { + throw new TypeError("Function.prototype.bind called on incompatible " + target); + } + var args = slice.call(arguments, 1); // for normal call + var bound = function () { + + if (this instanceof bound) { + + var result = target.apply( + this, + args.concat(slice.call(arguments)) + ); + if (Object(result) === result) { + return result; + } + return this; + + } else { + return target.apply( + that, + args.concat(slice.call(arguments)) + ); + + } + + }; + if(target.prototype) { + Empty.prototype = target.prototype; + bound.prototype = new Empty(); + Empty.prototype = null; + } + return bound; + }; +} +var call = Function.prototype.call; +var prototypeOfArray = Array.prototype; +var prototypeOfObject = Object.prototype; +var slice = prototypeOfArray.slice; +var _toString = call.bind(prototypeOfObject.toString); +var owns = call.bind(prototypeOfObject.hasOwnProperty); +var defineGetter; +var defineSetter; +var lookupGetter; +var lookupSetter; +var supportsAccessors; +if ((supportsAccessors = owns(prototypeOfObject, "__defineGetter__"))) { + defineGetter = call.bind(prototypeOfObject.__defineGetter__); + defineSetter = call.bind(prototypeOfObject.__defineSetter__); + lookupGetter = call.bind(prototypeOfObject.__lookupGetter__); + lookupSetter = call.bind(prototypeOfObject.__lookupSetter__); +} +if ([1,2].splice(0).length != 2) { + if(function() { // test IE < 9 to splice bug - see issue #138 + function makeArray(l) { + var a = new Array(l+2); + a[0] = a[1] = 0; + return a; + } + var array = [], lengthBefore; + + array.splice.apply(array, makeArray(20)); + array.splice.apply(array, makeArray(26)); + + lengthBefore = array.length; //46 + array.splice(5, 0, "XXX"); // add one element + + lengthBefore + 1 == array.length + + if (lengthBefore + 1 == array.length) { + return true;// has right splice implementation without bugs + } + }()) {//IE 6/7 + var array_splice = Array.prototype.splice; + Array.prototype.splice = function(start, deleteCount) { + if (!arguments.length) { + return []; + } else { + return array_splice.apply(this, [ + start === void 0 ? 0 : start, + deleteCount === void 0 ? (this.length - start) : deleteCount + ].concat(slice.call(arguments, 2))) + } + }; + } else {//IE8 + Array.prototype.splice = function(pos, removeCount){ + var length = this.length; + if (pos > 0) { + if (pos > length) + pos = length; + } else if (pos == void 0) { + pos = 0; + } else if (pos < 0) { + pos = Math.max(length + pos, 0); + } + + if (!(pos+removeCount < length)) + removeCount = length - pos; + + var removed = this.slice(pos, pos+removeCount); + var insert = slice.call(arguments, 2); + var add = insert.length; + if (pos === length) { + if (add) { + this.push.apply(this, insert); + } + } else { + var remove = Math.min(removeCount, length - pos); + var tailOldPos = pos + remove; + var tailNewPos = tailOldPos + add - remove; + var tailCount = length - tailOldPos; + var lengthAfterRemove = length - remove; + + if (tailNewPos < tailOldPos) { // case A + for (var i = 0; i < tailCount; ++i) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } else if (tailNewPos > tailOldPos) { // case B + for (i = tailCount; i--; ) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } // else, add == remove (nothing to do) + + if (add && pos === lengthAfterRemove) { + this.length = lengthAfterRemove; // truncate array + this.push.apply(this, insert); + } else { + this.length = lengthAfterRemove + add; // reserves space + for (i = 0; i < add; ++i) { + this[pos+i] = insert[i]; + } + } + } + return removed; + }; + } +} +if (!Array.isArray) { + Array.isArray = function isArray(obj) { + return _toString(obj) == "[object Array]"; + }; +} +var boxedString = Object("a"), + splitString = boxedString[0] != "a" || !(0 in boxedString); + +if (!Array.prototype.forEach) { + Array.prototype.forEach = function forEach(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + thisp = arguments[1], + i = -1, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + while (++i < length) { + if (i in self) { + fun.call(thisp, self[i], i, object); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function map(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = Array(length), + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) + result[i] = fun.call(thisp, self[i], i, object); + } + return result; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function filter(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = [], + value, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) { + value = self[i]; + if (fun.call(thisp, value, i, object)) { + result.push(value); + } + } + } + return result; + }; +} +if (!Array.prototype.every) { + Array.prototype.every = function every(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && !fun.call(thisp, self[i], i, object)) { + return false; + } + } + return true; + }; +} +if (!Array.prototype.some) { + Array.prototype.some = function some(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, object)) { + return true; + } + } + return false; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function reduce(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduce of empty array with no initial value"); + } + + var i = 0; + var result; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i++]; + break; + } + if (++i >= length) { + throw new TypeError("reduce of empty array with no initial value"); + } + } while (true); + } + + for (; i < length; i++) { + if (i in self) { + result = fun.call(void 0, result, self[i], i, object); + } + } + + return result; + }; +} +if (!Array.prototype.reduceRight) { + Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + + var result, i = length - 1; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i--]; + break; + } + if (--i < 0) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + } while (true); + } + + do { + if (i in this) { + result = fun.call(void 0, result, self[i], i, object); + } + } while (i--); + + return result; + }; +} +if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) { + Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + + var i = 0; + if (arguments.length > 1) { + i = toInteger(arguments[1]); + } + i = i >= 0 ? i : Math.max(0, length + i); + for (; i < length; i++) { + if (i in self && self[i] === sought) { + return i; + } + } + return -1; + }; +} +if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) { + Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + var i = length - 1; + if (arguments.length > 1) { + i = Math.min(i, toInteger(arguments[1])); + } + i = i >= 0 ? i : length - Math.abs(i); + for (; i >= 0; i--) { + if (i in self && sought === self[i]) { + return i; + } + } + return -1; + }; +} +if (!Object.getPrototypeOf) { + Object.getPrototypeOf = function getPrototypeOf(object) { + return object.__proto__ || ( + object.constructor ? + object.constructor.prototype : + prototypeOfObject + ); + }; +} +if (!Object.getOwnPropertyDescriptor) { + var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + + "non-object: "; + Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT + object); + if (!owns(object, property)) + return; + + var descriptor, getter, setter; + descriptor = { enumerable: true, configurable: true }; + if (supportsAccessors) { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + + var getter = lookupGetter(object, property); + var setter = lookupSetter(object, property); + object.__proto__ = prototype; + + if (getter || setter) { + if (getter) descriptor.get = getter; + if (setter) descriptor.set = setter; + return descriptor; + } + } + descriptor.value = object[property]; + return descriptor; + }; +} +if (!Object.getOwnPropertyNames) { + Object.getOwnPropertyNames = function getOwnPropertyNames(object) { + return Object.keys(object); + }; +} +if (!Object.create) { + var createEmpty; + if (Object.prototype.__proto__ === null) { + createEmpty = function () { + return { "__proto__": null }; + }; + } else { + createEmpty = function () { + var empty = {}; + for (var i in empty) + empty[i] = null; + empty.constructor = + empty.hasOwnProperty = + empty.propertyIsEnumerable = + empty.isPrototypeOf = + empty.toLocaleString = + empty.toString = + empty.valueOf = + empty.__proto__ = null; + return empty; + } + } + + Object.create = function create(prototype, properties) { + var object; + if (prototype === null) { + object = createEmpty(); + } else { + if (typeof prototype != "object") + throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); + var Type = function () {}; + Type.prototype = prototype; + object = new Type(); + object.__proto__ = prototype; + } + if (properties !== void 0) + Object.defineProperties(object, properties); + return object; + }; +} + +function doesDefinePropertyWork(object) { + try { + Object.defineProperty(object, "sentinel", {}); + return "sentinel" in object; + } catch (exception) { + } +} +if (Object.defineProperty) { + var definePropertyWorksOnObject = doesDefinePropertyWork({}); + var definePropertyWorksOnDom = typeof document == "undefined" || + doesDefinePropertyWork(document.createElement("div")); + if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { + var definePropertyFallback = Object.defineProperty; + } +} + +if (!Object.defineProperty || definePropertyFallback) { + var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; + var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " + var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + + "on this javascript engine"; + + Object.defineProperty = function defineProperty(object, property, descriptor) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT_TARGET + object); + if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) + throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); + if (definePropertyFallback) { + try { + return definePropertyFallback.call(Object, object, property, descriptor); + } catch (exception) { + } + } + if (owns(descriptor, "value")) { + + if (supportsAccessors && (lookupGetter(object, property) || + lookupSetter(object, property))) + { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + delete object[property]; + object[property] = descriptor.value; + object.__proto__ = prototype; + } else { + object[property] = descriptor.value; + } + } else { + if (!supportsAccessors) + throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); + if (owns(descriptor, "get")) + defineGetter(object, property, descriptor.get); + if (owns(descriptor, "set")) + defineSetter(object, property, descriptor.set); + } + + return object; + }; +} +if (!Object.defineProperties) { + Object.defineProperties = function defineProperties(object, properties) { + for (var property in properties) { + if (owns(properties, property)) + Object.defineProperty(object, property, properties[property]); + } + return object; + }; +} +if (!Object.seal) { + Object.seal = function seal(object) { + return object; + }; +} +if (!Object.freeze) { + Object.freeze = function freeze(object) { + return object; + }; +} +try { + Object.freeze(function () {}); +} catch (exception) { + Object.freeze = (function freeze(freezeObject) { + return function freeze(object) { + if (typeof object == "function") { + return object; + } else { + return freezeObject(object); + } + }; + })(Object.freeze); +} +if (!Object.preventExtensions) { + Object.preventExtensions = function preventExtensions(object) { + return object; + }; +} +if (!Object.isSealed) { + Object.isSealed = function isSealed(object) { + return false; + }; +} +if (!Object.isFrozen) { + Object.isFrozen = function isFrozen(object) { + return false; + }; +} +if (!Object.isExtensible) { + Object.isExtensible = function isExtensible(object) { + if (Object(object) === object) { + throw new TypeError(); // TODO message + } + var name = ''; + while (owns(object, name)) { + name += '?'; + } + object[name] = true; + var returnValue = owns(object, name); + delete object[name]; + return returnValue; + }; +} +if (!Object.keys) { + var hasDontEnumBug = true, + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + dontEnumsLength = dontEnums.length; + + for (var key in {"toString": null}) { + hasDontEnumBug = false; + } + + Object.keys = function keys(object) { + + if ( + (typeof object != "object" && typeof object != "function") || + object === null + ) { + throw new TypeError("Object.keys called on a non-object"); + } + + var keys = []; + for (var name in object) { + if (owns(object, name)) { + keys.push(name); + } + } + + if (hasDontEnumBug) { + for (var i = 0, ii = dontEnumsLength; i < ii; i++) { + var dontEnum = dontEnums[i]; + if (owns(object, dontEnum)) { + keys.push(dontEnum); + } + } + } + return keys; + }; + +} +if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; +} +var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + + "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + + "\u2029\uFEFF"; +if (!String.prototype.trim || ws.trim()) { + ws = "[" + ws + "]"; + var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), + trimEndRegexp = new RegExp(ws + ws + "*$"); + String.prototype.trim = function trim() { + return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); + }; +} + +function toInteger(n) { + n = +n; + if (n !== n) { // isNaN + n = 0; + } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + return n; +} + +function isPrimitive(input) { + var type = typeof input; + return ( + input === null || + type === "undefined" || + type === "boolean" || + type === "number" || + type === "string" + ); +} + +function toPrimitive(input) { + var val, valueOf, toString; + if (isPrimitive(input)) { + return input; + } + valueOf = input.valueOf; + if (typeof valueOf === "function") { + val = valueOf.call(input); + if (isPrimitive(val)) { + return val; + } + } + toString = input.toString; + if (typeof toString === "function") { + val = toString.call(input); + if (isPrimitive(val)) { + return val; + } + } + throw new TypeError(); +} +var toObject = function (o) { + if (o == null) { // this matches both null and undefined + throw new TypeError("can't convert "+o+" to object"); + } + return Object(o); +}; + +}); diff --git a/Patent2Net/media/graph-recipes/app/assets/doc/attributestapas.png b/Patent2Net/media/graph-recipes/app/assets/doc/attributestapas.png new file mode 100644 index 0000000000000000000000000000000000000000..9ec264bf2913f599b4d648f9c6a6083595acbccc GIT binary patch literal 14835 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 literal 0 HcmV?d00001 diff --git a/Patent2Net/media/graph-recipes/app/assets/doc/cloud_default.png b/Patent2Net/media/graph-recipes/app/assets/doc/cloud_default.png new file mode 100644 index 0000000000000000000000000000000000000000..f3bfeb65a0bf212b9c09ec43c54b02c951fd956e GIT binary patch literal 152261 zcmYIvWmH>R*L4UM++7;n-95NlvEuI10>z;X?o!;LxVyU*x8e@P9f}qx^rQE=_x*k( z8RLwRv-Vy#=br1Fa5WWKG-P6A004j{FDLaD0D!px0DyQPgx4!{v}o+FKS&?sbX@@e z6r8^w7(jX^;p;`Px!hZ20Kl6D0DuMp01tm&e~$nFx7R-$n*acUsQ>`M`*`DTG63LP zMR_T4P0y9nXWaw~`DF4iKiLZ&k66Dk5hkwky0SKJ7L&H`P!keVm^7kMXuZ0Hg_Mkp z97XVZ+!vUL%QP|n_r80u#&Q%$Z$n@wO>A?&N6X|BeALm=vewepT1fV>vXE+7o_GC~ zE2}m2y?k+8n3I!H0c9Jx58jHUW(FWC%^9(rOQ&dChsA-QmhEamicu7kALrvH@$e9 z%5_~;Gg0#sIq#7wS>RVB?v={ipH*2A5_uDYY#ep(HQ>#y{Oa4z)VdBoGTFeV(S`r4 z4Uvtfc<%%uA8%tC3VtsBgx9rnjfqk)cjuC^8e9DnYEL{wM9lM(FGubtil(lA zTnT*j=dCp0x^*#fZdLj*iWCZhMV~J8Wupu!tq-t3IX>E~Ft#0>MJr(hXn-2cVgX-K zSHx?D>D3Tn8{!pyzDNsxCPbA*Q8QkA&8Jr}<6M zB+GZBO#B4kgH(WUQS~@hAJVYb=${y*VJcW`!*FsZv$eif^-4<_W#k14a1acx%rrlB zE(X#P11j<{EH!E_IIahbj2W*PazOFL!wO8TZn)At7vG&>So{#S`j5pnZHVzATTs?L z>EofL3R`T`CGjM;7o8Zlc#G`9KU}tS*pN#s5wxPV=JqC6GhM?z_heZ^a;(*6_2Q4nnG$DHA$t_ z_Ww%&V*vZ&mpZdv#!9Vnek)e&#y3?^VkSAoOzd1$tW0s=^qDhk7?myAU>n4xx*m== zy7N|^=0PORGqBW_DFBTGHA5N33zez|HpDat6&4J`jT#5C+?UIpl=HjC^i?#*yPPvU zgsaH?uRQ%kAx6;RvlN^%ph)?wvMyQtI}XLU>=sWMa=H&ukj$P0;DZxl436A8m`tdD z#5C%jJ-pn#u}CQv_uX}y0GNs#FPw^R@Zhi45W1Q0L2+-(z{ z{Z>^BH9WXnH=0meWkoe7dcN`>>#xnr%`e#=X`Eo_d)={t;<5ZREoL?pb&ErSGmI%t zF%u9De-oeE5tEUWo7gm<(l9)8{ZaQ*43V&W11GECAT8j8kaVx^_du945JLzx11HEC z)(Qa)l^79@$X~oiPQ)D>2DwKT8uEL;H67YTiG%ordF1$-P5;EUjkRx*Ank!NHKVpZ zHLdkiw4O{3?WI#Fe-<4$hZaI4AVKetxklQ$VP(V5)8LCVx9TFqQ=RcKM1(q&$gOd< z)!h+A$ytJs5A-0kB=%8~boPQ$~MEMu9SvSArmzS5I8je60Y>BMN8_CIu)Y z{bvm6G9&BJgp;=R-%9<*Jo!l8B$|_ErB;Iwdk*+Z<6Ko<^E!SvObxc^L250)1Kg7j+t|B5SV85H39HRv%nZ_WPhp z5N-%LPS}`xB>x#^^Fe7hsyJvD+EMedzf0ptki%W!r`1SFWsPp<=SeNLOR_Q^hrEFm zwiI9yQIEhMW>~&2UHE?Q#NplXYuG(KvW@aTOd2b8-kWN4v1y^B=2CFon)qHI;oh`b z@Qcl<8teW=zrQWp4a=Q1gm<#SK)s~Wdf$tbWl%FO+dVw(eRG(;* z#rLLh8kn&CwBaYf!5eL~M`8Y?wP4O)Os9%j8dG8dpcST)*Ft~AA$vpF+H3D(9p0xnzG^#A`EKuu%ZM?FkrYPF8U`_{W`qhs2i9aSg6;Ctt zk^tE5nReS_DzGMugJD&~(-2iRi{Cc0E9mP3;1-ZOQ=h^h0rUdeyDSb_SRNSIsgj7B z3PON5-!g1S;yFcA-Inl%y%1Cz|8L9rTl6BRLQ^BAW+A0|Sec-c4mbDDTpK6HSF{>t z`@Wyv)Mem4`F3|CE|JB-ic={mnlao$Gc((=kjo228WEhUr|R4&EPqspxM}6rcd2N{ zS*gg0#o09bN2&^O6*C5zF9$#qH23L%{xI74q*gpd99Hu!vslYDIeY1GHZ{nCaxPB8$%#lDzBzb2`4HMJg+|sc&U8xJ*xOdQTzH{s!uw>PA%9@&~_UKUIou1d#n&3*+J|c&#=M7L(^>nssU9ch~?VH{L9IQ~Q9W zn*vEWh)O0oT^ujir7*L!WRpP$AU6Zryn_h~@NO%v9sv&>VyVe4B10m7j??M+ZTy>v zRpw#sgddv`IP28xrc9ZLdD>Pf&zmq~q{Fj0<&`cvEcef!))e``Z%k6#@%npj=U8km zhPXMUBN#)N&_CqnxlCR0e_-vk&qbC@jLlV7@XW^y=YzQ$W;P29j zLvb5ND@>}H4Ye-#c{?os?E>D%-#a*eqLTDMkTQ^(wzYzFd%hfYdLcViEo`M9teA0Z`nmJ z{*MDBJ8#^?sL!ABY?4Ngiaa!o6>uGBL_j76*$t)JGdQMl*T)l9H_^H(jC8%Ynyh+0 z$&3p%FaKyH4$q6YM>h%iE#&2(^t`ovb9sI0sdnqFRQJ#~ckP-&*t<$*L#SaZ3J0n$ z+b9Hh{q#yXzA!Q~S~Pn29}H=`Z@o4>S1WiE$8r)e&Ig9Kp14gfyt3Ye@ViYjn=vm_8bEwETAV(obkZ&zvTSOD;{)72i;O2B+ z+bD9xZED;Dw7kLtBh;)UGADxN>aASynXbe(Dsch@78KS-G}?6`C6@rxPG&<&;S3j? z%1eNI>-pvYK&85{%DXtpSoMADubx1~v^=e_ z16z9Errwxh1_OP^i<##LEFJa8((>TCrbxRQ=Jp>7V^_gcp|VdzJomrZ&`MN=NXbdhU!Sp~Rw`%V??rFEuh83bK+-l^bHAMHW%Jq1+ zHz$3UCwFXeqzlbL;YvbA-3TTjtn4F1%XvVXyM#1n*412HXsN{Vo&vz(_%SR&K_soG zQ1}+4(s|PYGo;M;-98}8Mjk9(ktevqGss!a{~tQ6g#HeJEgSMW&p7!!(rg&~p)~Cj z_xRgnL(RvrPNsU+Kh~YgSuwq6A%cO8b(Y5#-y5#-MNJHmD*UW0d`UcKJ;*@LZ zFp@#B<@Nr%fRmATrhX_3x3>5KTRNh48B=-)tULO4w6HP3Jo>bT?@~F5JLmEWFw%xXtXv{ z9`2A(h~5;!OxlZl!ikF_70)RHb$yzdpuLh+jF-qiE$`KSvE7K#25TA*GJ#s?U=eWS zpaYRLgg}UP!~7&TjU>WgNg!&LbQrhC7GXchzqlG>lCI-+ww-H|?XWA-u&e zt)N9PZbDh|_i??BzQje?Gma!%U7?P=tN^WMb8SvUVRHhQCXKi0?Tk%?OxhWtW=ozl zN6Vf?A@$VTtb+?lkiLxoUQ8gJrQpHh8#wCQMto<3@dVfkOOI!^jLG9)=_cpI%^{5y zuM}JI_0YrIM`UBo(oC|)_bM78oBy~HN^;bp@qu1==}QZt>K7J?ITCph$&U>zaBffE z<@<1y^(2i^8U2}wMrXRH_t_M$p6a)*&Isc3@L})t+*Fh;XStMynw4h!DfegNT;z&a zdK~dSt@Nu_E#mtB7!I;KIhd2#b4~N~~^;TZz*!BRJSd<4uxa*BiHA zvF5}sHGBwXqpfYsxSaB|uHj@yn$xUsI^R+nb|;Owi@Q@h`D6B@J{JxLphfHzF{cLGIER4_bYNc}q8 zas7S%<`3@0=Z`VYxzcJE=kx~4Fe->@k(gaGx!Ufxw|fz=Tj}W8XZdhViM2faqwSXW z`^%%Fga2_M%fw+q<7EMbD4RFe!fSe-XFCP=KFucR7`#^i?fuFvup7Z|@9rI@Gq^CA=2L1bS zw%CeV^}aDwRKIXC!`sD7WsmbyB_lol_2NU`Tt$dQ@AZ_y;O7?%qoMgRx>Q}RXSCkM#5ZwB54^gUTvYWse6n_n0t*9Q06q9IH|-jh(*`sK&F$8i=Xt;WBnyT7UD z?a(yzixY<}>-KGk>av-?4Zcpq0m5|BP@?6N2!vC`3QDPlul!70|96BZa%{G{*A>(aF;D-N8*!HFp=1!Y zA142iv;g}I(FRN0Vych8@gw?UPjj`Y_;=Y(b^dFW)LK4Dwig`U+?Ntwvj51>?D$GF zOIoT$UA$ZqfFkSo;mgu*x$;7xl z_G}#=0o1L9rq%RLY><_b+0K#|P%0fvJHxgw2}u*WgG?V6ADb!Y>)8J4lNf6HY^~}H zGC(oXAh9rG0!M46tM2lD>Tu=B_R@yuWC3X2{OE2bHYT(n6s9_n1O4~d=O>Nd9^Kcl zN;vH^zX*X&>%x+RhZKM(EH%r=Q=@;hays)$#(OtEqu(M(-K-#~8%(g}NU4TbKT79p zcQiB>YVDN$WArGlXRQILpk)4A?Ik6^z|*wx#6%Ch9OC#N39j&e2J*{b1n&C$aksac z{p{3z*C+&5s4cyF7^DvyUyAy8bCQ7a)9qng{^hThLFZFR^J;bf_wUs64}7vxF|&@5 zxl{;aR0h}G)Z1x|g!^Q=?9%@8Q8-wiZt7!yR{yyvUOM0IQ;{4W?7b(oxMTDDZjvvK z`N(~7_xFBDUtg0Z)@&lxZJMKe`ZwgUhh94Smo1LBa ziExY64n0!_yaKz9N9*s|UF4#dLV3VWrrpsTbT)E^_qwHptWlTIv#hzhV;W4U`u?9@ z_eu0u_u!7mN0-Sc^5W&f@gDwJm!H~}n%F!VB%*fLIf2xJOZ5Ktp`@?N`$e||92h5~ z?x5-p7o2`f!Ae+;&-pL$+yci{dDFl3V}2~}6C63jL638QAFb$>pkGq(7eE0%|^i7Ty3#$$AvXClcB zPHOW(U7akAbac|8md)8)!M~|6W+7{Pe?Ed51Zi=-M$MQ|<3$nS-85gWT=9F!w3vGK zRqeD`Hu+=VGbI!vK_Bi2cZ~6?`v0UzvcL_;JCD*H0@W*%_}&h}37*8l;Kz`pefsL8mzP)*Y`}4T@JP!4VP4l5JFr8xFd(guq&@i@MM7H50 z4H7*cBb|`OP7RHdFmT~6ub(nRxOFm_K>q!@5%boC_}88!;>dP;d-FzJj=@Y^mrB2t zKubGHrMjcCn?xy}lq@3gGb>!&?vbl99hc>=cxj_|^~%bMV0?Q2r*$9w%)wsJ$?r&q zv9lSSnxqMMtEVIZlxh;(c5xejvC^%5JMYx{HU684CcRLm|6%g00+}$}g@GDt{hcI; zllZtBhFu|5&Mb~-jYzjpRPiQp#h4YUf6fH|OJ3_(x6-Jmi&CT@&)3^X$||htPg@Z^ zA!6U>n`UE{0D&(8xRU^~kP#FE8XzF3m2tE1Zby0sfl>sx_^kLMu=wItN&Ra=90Y@l z(8F;P%)jz?5~g~pr+9wijXNy13F;Zj3x{zVtE)U@iuIBYyx%F*5ULPt8tZf*tbhi$%PVUdj-QT8qd4JJ;*e zX})IS$r1HA_lY=PW+xP+E;sHh#~k0s9*C#!LI=;YP!0RV{Lq#$2G!)CPC&pMzpn61 zPXyKx&!#tavOm?Sm|hG zGAx4-{|b;D=JnV~**4oH?2KknYReL8EQA`D;V6@nmT^HwLh z>*xShf^f!12^JFpZ|KWYEUIEoXVKrN{e?3P<*9qgoRdNg;7543_lw6w<@{#M(efxA zBN67u%JL+su?<3_Ov;pF?U*m>4({h^9Cj zMWE#eK=QJfYlJMCU~HDwRbw&ws>6MWtb6?r>*qMX>VVHqZl}j#N7&)$*-t=9r`U1`E--X+!jCg?8y|6sn64e z*ZP%X5~lrFsxzlmrwW2egZW1GEZ_QRaU+vBZ3@I>{};pmQg9cR@jN!BbtG(TI)u=m z^F)O+4mit1Dt7c9Ucr9c@*DITksUQ?Od=YU+M@y-RweR>G6*ar(c(xi&6}$wiAb#X z=rTFa=)k>VyL>CztG{doZ%Jc>qSoGWEwAg$(t?e$6Tj5KVCingPm%I)kbWW;L*=8K z-SLj-5Z=Iljz@Ifgvy|^B}Mf}!Ovk~OJelXmahNEn%zfT0*wxYB!snN6lmpnq_)j@ z-T$VuZmL50b8tRI#?EKZRdSo4)Pbv?&R{(ufWTB z`mEEd|d4t{k_X$__l-V=%uTEx<;u95n10DmX~Wj zEL`ZuTS3vDtW|p6gkYJHx^)@rwk5BRFs_O3-R193>E!;)oMsyfP|%{6y_*6ia#bi= z(|^W29_}D)A(^PFO@h;ocPQgO@TU~jmqt-KKQ=Yc7}&7df{q?{k_+CYp=fk zpW@BK&&qDOwpNV?p9aB1$_0bo&YyES^*AG@HHC}lClDb}W4?p)Pb#Iekb#)}9uNN_ zNl2~vc+hH{-E9S-af_qMCmE|hnKM0N$!k}`qiVX=t`kU}=kidoF-&ba`BLs8a=#+* zn6nzh4?__}a+XtUCwr9ATz|mDu{PTEx{AM=ca>z=c~NtxtnTDNa$KDz18Up^ARbL( z4XmO;WH<(Xm!(^7SuWS;ADsL!cJbw78*u((5xeKJUZ8YRJ%KYR%N*4-yo<>Q!6zg4 z<_K?s@w{p}V*kv9xqMNCU>H+j7_Wu*9zbMlAFJe8{AZmkCvAx z_0}e?losWvzwOY#8bZsZpo}6JZh=*O^`ezZaxIv_?4bup3owCaJxjAUCX&|7Q8=Nl z=)0IMXtVrI9--(+RO(U0f4Sp?23>vAyyu=0?Sy+=vG>u*=a90ndlG88pY#YN>g{ue2WnSK#ihTv1?JKC(gIl=1qHw(xtj!FtGTq;CT z>KR}dC1!dN#R(B0gNZm@0{#O?9Xs2WMpmN&91D;}%E?E*y7(^c#iUxC1d7tp1#@kv zbtX=|>enm34YeC%TOoX%-gUjneWMnFwzOjAODRj@wpcPB{nh`5HNmVMwf5^ z)}~&33$*{vd&KLMInYMCQmDu&8^|Py;e~4?vd$1!wpv&-_ox-Rj2^!zg1SD?El5F% zzyBRg@nC~g&_|MtnD=%3n(xF%D?%gcCfbzT6}Q@P`i%Nt;T8LMIcH8tR$s3dhGr+( zi_dj&PZ%PauaQr^DaaPQ`lUlIU(dCkR;n?xDUR8|JB5jvanMsbmCdttJ@+Ba`7RK( zGmA@BcEah*#5FwY8{wE|4_jVSnv4VG--7FH0(e~Mw z4=au`ke$Z_iQD>}7awpmanGs*{|q$~thY(iP&i#!@6?-(AW;kqXpUChv+?h&yBYtL z)|$K#&hDUs#YHDgO)Lf1OW&_>`v^x(tXjy&yzZ zEH;%>`cw}S7i9qlTt17hMNLz00#B-|+#G-vb{ykQxig^cQEj#i*#+H zzwRkq(3TXkyNbUx$6=aAEnSR;;V$Vf91@GguVga`a5jvhP6qfsN zw@$@y8_PB{^=_Q#2b!(?y+8QaVQ-LkCmjaEx7e9lxgy8p2oge_(gYk;*t4@~+(n(Z zUEJya2&iZNbdU|rdRnZlyZ$#4<^2QgVojfptXMli2h1A9aR7eQ(nir3_}@qYAQ;tG z^*qlvXD_?&T_fZ7dGP#P*Yh(I%VrAX6pJe{2 z^6n4G8}&gv%vqpsl)U~iG4)3j44kw}I#Sk{p3U&!Q41Ig4pOH21u0&MJ3CcMfuc1h z72aB;fkL>txJJ7v8qeB2yEOH6!Ou>?E?Koa=3puw?sb$O)I>w585*dq<6T6vQ7>_d zryDDcoUZwH?CgeAm)y^`Vn*Y7yElH><(+>^f)E zb~oyu-W4)F3~zUh3`QkXQQ^qU#=TD6Mc~u6a)KC2lpMM5b*7~(EVf<`fm+_&2~*a!B*x$#*ttkh!BWdg53}^>CAc?32O!(SjQ*z7*1G#`O2xaj3{S~w^GB$7e5Y13y_RfK634$Mxxm@z03 z68V_c>y4AY!j-_0*Q$axeqr$Q^D3WEW}2(NB(_Cf!_&^UcPb!DTE@b;Rnt}n~wB7?CPPpFReiFLby zJ(M+Cu8Ovt1}1a#vOmn!HGXZAcVrST|D_noP9DTZi)Fk4r&}##PfHd1%hN|;${A(b z&xbv#%gF+_R`SVcVjVf7|2y7kBN@)CCeuVgsWvQ~Gtrhi@* z7;Uk6#^CI0pxklMT(``b?@oN7@ckaCSdTM&Ip!Wz%!Q@%jx}-!f~ZPb!(eS&&1x!i*2_1K;yYg4wb7 zsfFGVhj5p7t%`4}q}2>IG47~7JNu zy%7waW6}Yu{&6ge@FRTNB_MY&5$cVKS%?bV0=jGv7WH}z`})D?c;9S_cV~~ zv;}jC1|tkFFBNU1Ea}~10>&W$z-6e;iq313Z2V4{4f5U5 z6s>-1a{q@y?g-9Xqm%nNb zn-D}fe(8SMXB^dGpwczmI;S7NYftWlU7NoD#w2#|=2VYnkjm-K_TD)d} z)aBm2icdXDd)r&VIjXLxZ8Xph0(bUn`XIu;N7EsaIEq!&uCZpv5a`Z2#*gzJU(-p^ z*6w;=zhPVWt|&Vi&EnI`Q}=<#`rO9nAGtY^EY}60rCU6X0@#0$QtYCeVC;0eYzZoQ zx`28mdKc}DB&k9}_4Y;IUrIyk)Tmwksf7Bs8h^COcMxf7#g$**!pUy1ia`aoa2fJq0r_TcN2 z$*|M0>$O5MPX24`&6LAs#?l(?b&;w0R!#&?ggFmmK!yq&J01l~HNku$NeKW)N_O=# z6Xgb`H2F?K!&zyuHm?9p+e!Jsec(JeWaf#w53|gQi5o;OGd&!~5I{{S6~ZpbA7B<_ zp>_a*^r$aC`J0zu7p1$)P?UcUG~F7VzFu0!jF_(E{HZqg>vcH)C;%1KxKP?kER>Jj zQx*SnLka2n`02pUtJFE6d?}SksuREF=Z~pAO5eS_&$ z&YE(8w~roGb8)RshnpZhTS|%dkA3gqbWDt2+dItlGQXV1Q1&u^29Dv454>p_*YD-o znnG^ZcsXajk(Bh)(4y|1O!qAT!|`zy$)Rd6K}+hNywOW3L@^SK<6DW{aX$L;4fV}# zUydS}frm|7Nw62Q67}t(IUIsKlr^e{<90S!t0mcK4C*91erhdW#!7eQcyRc3)V<;> zrz7$Bl!EaZur*>0NF?U|OSF`wHl_K?TIPfL=?Oy%|2^Tu_Cr>1>G+Fp3i9r}hnTAV zp;x%KFQhE%y-()U`eOm9n3GIAy;cs~e1@^&#nB7VoFtFMTQ*<-lE8LZqir=oBQpKa z`{Y8j`mH?`M@k5=R1!cZiG$)TvuTbg{Hab5qTZzm)9qse!I@=D z#3ihfZLu|n@R^;%&hkr%*Yjh;sT^J-ThZKzY*MzU$_Lv_uv6WkjJ}fW$7qZhA}(C} zyGxJiIS)IZ)J1pOnlOg1>C@hQrP4u|y!}n{4s89L7DKYXqW~lFhZ$+t(_Q3ps=c&m z&lVo|Zk0*AT#?kJMNKZsz)X2=tP9!O0EWZS;kK)gI;WaI*CW6Az&@w)QUu>S(@o?X z&3&ll9xaQcQfVbX^dJ(Dk#o|)-4bTDgk*3`hy!EN2~9}0zb2d&9@6s}l~QI8qjB6- zna*cj>mE+HhKO~d9GArCS#)Dqgu>$fzTwh55QrxYFT*5~XqD4oSU#a;mhn3cDdd5e zE`Lz5W9lKla%f3bXv{GZHAmdNtFIEH`_)wn?`kU(r^9Y6*lY>2rJOX8dEv#C;&Rk# zv4|`y(tRr&iz-3)bGEwGT_=gTk?+#X+PobwA@n0-f%pIzgD@ z9EB{9Fgqp2nn=8i73J>IOTVw>J}2Izfad@q4?0h#d`bgV_k}CHG{n9ApoO0dGYK1s z+qx^J7IU<19Fj-{s3I0(PNjq3)&j*qy(GIS{*;A+{)Ow4Rj$daVBjs)*hQ*gVtH-U z*-rsCj)xg*OnLM7qjhp{php38`W%)J^?V(YCig=D{OPQW4ow*S{sBj~!Ix}{*;KvY zQdx(IsLyr^rv#$SBv#BteF#2Pb@(3`*%LNmh9OZ%q+0sD%tz&)a(D>u%H6O>)w{0` zHXCB=c$^W=;@~oIhiy49fu0IlIl0X!_D@!z+!9;=eZqhOY*8dUtSZcOb0)VxdrL=Y zcyl_CKif4fpX(x*3-#4PjBbJp6P={ZmTOVQ&-Tlq>(T=pZ4$c@Nay&L&IS4M^20m@ zPY5go2{G)pUTVy0gcp~`KUlbaOc31d3QIh1029dY#?GB)9_Gg2Gl%^qzs(v3cof#> z$v9>N`Gb8}-^1)5;HO3tch-H-aA7IiHyNB}*0|sJxe*tVO}-O{QhOEhWpyD9t8RW& z?~(7|r}V;S>o{Jskt??q|DD98Rx+O(ePNcY`>e-;P6TJO5zZrJ&2LE*LA#`cS04vb z-`@6>^eLn99#maS-%iWZvSmEkbs;`KEG@ivt0{*=qz*WBFO}v)C7fFoL#1LbI0`?#$VqMEyjLQ&C<&Ox zrceT;|7`JHKa6S>nM~k1@dgsL3AGwjcbuol+x=nITA%Zj`eQyK}jRt`3v3s({l;4A-dnd zRW~o3qn1{licEM+k=T5J>f+QF5#=r042W+t(}BB}VsvgT%@+Q2c>2s^_OpU0tMqUC zayD78FpRM2iep0I&p3ww%W-nVOu~*D`CXKs*&goYNRGVND^J zje<#1Go?`t@XBkW^(C6T%mo~|Tu&=>{-ynlK~KpkdJ|OvxdwU7#-=Lw=h{BKmPL0q%O5iGE%02T@#Q|e=Xas(>ebqdVpWj5@ zOMw~%&C>W=l?hv)_3Ot@;!(c5+>2(Z-dNJyF*7UB(hfVJ5X)Zf!(QPTh6jl zhlb`#PiC2w7`0wDe4dGmqRd;tYIOaG3t=^+&m(-8hMBp6#NYig)_4)GXk=Ygzx zq~u{Mel9Yd192D!$aQQ$y2%`vQt;qYul*46F;nhm{Pthx z;!Uw>if7SOWkdJeG}0#x@b72kr#OnngbTM6d?aut{0rB=Pa5nr2xp6A&-~I9l;_gl zBE(ANxI_?^iOYn9d_1_iG%X>TpmuA{N^4Wj^3OT@^ft9^NXE`!efSq#ZpqpR;3+t! zaFTX=n$~=9fPnQ8W4_wAk1aRSL{zADymf*jT$jpT-$B9e$`*0?4AVpZ@{Sa{xUWhQ z!NpHZlEYnoDi0`>87s=;nEbndp!s^+Z=wF!VD4FM)G=OWPs$HT&O`~rAMnBSvS2aV zk+?a77L|?;v=dJG2ZVaWWGXk`kryM2wfChQ++^1J4?YDu+&%wpZm9n%V&&w1*|BPu z<`>!`BD?04P@j4}EeS^4)?DkGZVe-mMEXjb8jU*pq0b=>luFchP}V0hD^)m0fXbhi zGChCY`7U%Nb>CnxpGx7vxIy@qN;k9pgWh7t{%u&&pT%0Ir`SEdgXt%UGky7&iSyqt zk{nlb@WX7mfei1fU0oaYZtc$F`3@Wy9XnS2n-8|u1w7l8ql6&`-OBRooG!VYv%&c9ZO`qQ%M8r#OC!OewhV((W!I zaSBJ`KCq<*1SJ1apY-qs@r?F?@^wIuH~r?DbnYr&b8#Y>>X;R#piV>!)1KS1Bi5^R zTb-r%Hlq%jYpK7HlseD6&ZqF>ZbhfGH(68#|DB*1;u~mMLz$-Aa$LrrsV=! zw7H{1LJH?%NH&~>b2EI77<7OE<|eL3;Qe$U&`0eCozaCkkN=~T^Fo2;L%tJaojY^| z(p>jdHEJzY8^61J`XlNXYAYypUN}VBdY|Wm4Gz{XIKukEpYN)Jr^AUI4MATPH<_u0 zM0pEL42?}7#x1$C6{qR3Q*Az~TPZ`cEvHt&0^t_4EZ>g8r)Cpz_XZosi~yrZ%7}1k z6W46C1zu8l&hM zd#Vt6;11Q>A1*dLu6AtRI)fc{(oxwq@v$3psRxQ=+AVY5q^T)Zc)@CwzkAb=&U7fh z8G;)+O!~Uey-yUf?J;c(U?{bOCqRNBZl0X;3sozk&yn#B&K1zy=^bzew)4{b7C{kt zE0nQN49(%UdbpmeoI*t`K$!c!xXs5_pR8U4*Xq_7@CsS6cWoQV`NtAKY5KA?MtXQhKim`q0>(AY{ z&hUTscFrlH7pONay9p$sc|S(DIE6M9le@I~q3<%3bu}{-OqwqLTG6$tLQoGVvv?DR zSJPOjt#F}PhseE2Qe6ZOGcuWs8`so<+Y5`6)*Pi^+)7!aK( ze8;)c`p>4lb-I0xcQ8}Ljn4FOQcswV&q;khp{KbIm+71Uv}CnQRvhz*40SJ^vQw}s ztuuk`FXcsGOI|}*Gdq=WxQ(v^t`SI&V7$QsWyufb?|2ljYJfF#z_~Xtu7CO*m9ppD z5)q1Ksiv9WL?DRcdpZy7}A$OV@-ye^}J zxrx&y@iJOFhBS{2P*^>%0-WyVk(*%detQ}`UZ#E32zOWAMB#7tHIqt2#Kc0S?anj6 zwoq%z=A6fJ0LRbaLu4nf1`K7jA%DJI9F7!`H1;wTPFa!W&rvYmuSgZ#EGfL1;B+k$ zy7rYYU(nINWVIz$m++#77rjlmwPySPvluy$o6kf_#eSxMtO0@<7{N}iOEIX~q3fJ! zAIF}^W^TJbN_#@y$iYaR;%2WRUB4Uuc4(YOq&Ukliʼn)r{nswap+VbfO0c@uX% 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

    ?5|vaH!E%Xc`_lt{re|CL4hqdo&? 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%0ARL=)Jb##q6}|p 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 literal 0 HcmV?d00001 diff --git a/Patent2Net/media/graph-recipes/app/assets/doc/fuzzyclusters_blurry.png b/Patent2Net/media/graph-recipes/app/assets/doc/fuzzyclusters_blurry.png new file mode 100644 index 0000000000000000000000000000000000000000..524665151545e5c8928d3a78928e266ad653bcd7 GIT binary patch literal 58281 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

  • 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%0A{v>Fo`?02oTC1_VK2Gem${fTP zR?HFSq6>L^PAFGeIz0b7{vJiW@WbEdcaK4u&(+ZRi~cTOV^~-qNv^T7wP8d&MG7)7 z?we&Ip~I$({=|OYZ~C!RrS}i6F51g?_BeX>w7y14zaXS4z2XK5nseZMpys@>n@7gg zd95xyciF5mB#3715g&r8I+o2a)sC%1_0IJ}!T+zZ&BH%0$_29r#=Q7_S6s$@FyN<) zu=VIxziK(Ue=`iEQZ<3SAJ-JMT9J7YBpLFj&B7vi-9uX2n`ws~BWSS_KVH~c9 z#;#I&uB$_B_X{pPi6P=9)9pT0O#{Zw$tF&(9v8mgTy7Ri4yt58iFokNE0zr&WM^#%7_dI9r#jWC}X5O(4B)nFlRUZ-l&nl+67%zM^ljL0rB;aVr8fY@9p_ zAUCOf`3r*hfrCgOE9NW}G8m?lEPEl{jLSh0|oPxK5BR{jAk zk1;Utv(mu1wOjlxWNGk=GzE>T`~*cn+irYxN&^k2%fOZ3g5lkqvUa|$`auKt(Z9k- zWID0Zo$&-*{2&E(JG_k^dm&rDV~g720>GD~kZ_?!JzWGlAft;EeVO#dMJ3xN+O@lTG>SIM)Qcf8hz>tDDcMBB5IjRZ14N7Dt_nrVOU!!~ge@5}i{z|h$wM=l4%LGTM;SQRdq zxOZrw75?;W0Y)heh_UR+95D!-fOn*mT-tu2RSU58%P^Kv*HY+}1apK&Kvhl%RPYrZ z&B7BtOevQv{S{nJ-Tr4XM;J91+by4wP+oU;3DbIF2{(=cz%to&Ho*;6P@s44GZ zlQ%b^nqwOj)61jlQMg%BC_yG8L{wmzRE%t!|E}_G43tQD>b~`jb_K4XSEjVwHP#y5 zkq$Q2g#-^)95B@Kd8Vs3&VH$5uPvSJy%Qqo$aT025*T!~%rS=xHt{euaXjI6EfJTm z4sGj*LCFRd0JZQe7cluT?3vuTvWT7l?D+*QgUfJ46rz=Lr#d~426Yk`K^5yt-4&6f zOfiT;GVCxxM9gYH#w}f=QfBx_gAw2mjujL;A+lsgJzGW(ipPo`UO6RD0;paqaCq$Y zKFboJMni`)@!$=+Y+-fd-do*Lam1w3NEUP5zfkI2uT$$r|0N*?eSO4R4^|~NFxpi7 z769ZKs#lz~<6;Rjy-;}05sClT+H?f^V|D2M4T@);vvT==I$5RIKNld-I~VinH;o_e z2p3ublt)V|pIi8Rdr~->Jo|{4Lybb8EK;I`GyyNKYZ-wwn5m_zPBvO6rt>l3NAt>9 zTkgNIL#FvIAcy$r9VwuyyloF5+zb&%~{gb3}~e- z`HT~>9JF|cg7e^z9ql6L2vkLpeSQjBCD6bAjjC(Q0 z7IpOK-dvfCp+*2ws3l19!12AY732IbM!$t^KFi*8y^ZN=Mp4Hvf7P*Y+mYd zvNWFSr1>+?3yx`ZwGOTVlF@b5{j=>^F(V=&Upg35CQNW+Yq%h}<4&5Ero!BueVM8T zk#GP`9S?a3d3OL*ee3C-5sV?Ox&0mEdVK00CxtDI-3=+^rymm+w3ZxYQRyJV0iPTY3p#rf(beK$GVIRvoJ9;9} z)ztCiI8xu4D){AqdBcT7_7)FWSh60E}ho^E*_mOGI|hrD!%7g z*#c#fDL`lF<9$BB%Fwp5HR$Z^dUXxMKbKOA-e)VMjIT<(lOmy+}R@B)zZ)=mzKuHD`4! zE2Rh^kvw&vQT(WD2ny@{%{_~I-v=Ijc!2lHfT$c93v z5ADpI7Wso2n*@5-{_CUNf!`#)dj~FhIz=$0A!XrCf9rIC>#YJfvNWTQTZc^XoUW&5 zrdvl=g(6_p!u-edMu^x^U48?eD#WdV?lXX~+&FP|Mx_ff(mWAo?WtuoE(z8h9vy`S zQZp06zE^HoTurD}+S^W$eZS!4nu;egEN7XAT@{55#biAYkUv0N_v% zqm0%Gn@yq&>>0E-Y9OiVbMOo}e#h)Q3MQp%`jP8)%#lgJwhIu%yTm$UeESM~!ZPH> zRZC2))8AIHGATQ06m<*h<`d8SLaXG+q?eW_m#>SyP~YjTBb_J~}Yqh^2gJ;QX9_iW3?Z+3Qgk7zw;L}zNd+Cy?UFFcFkwj#;P;UnF1}o!GH2yjtNT4D z{c`7l2ZZqD`^?u~1xINvy5?A`>R9HFsAju{7t@y4c^3_5zwW8QOmCe4|UCDPZ-F)IhO;DpQ@cJ%svp4UL;F#x^K2JSJh79P8WrxuF2*#!AthWQh3S4jebg zYQk`|lX|e}{~AX(`j__!1WO%{%lT5o7490T!p$1O4pCiBS1{47S!yN{^nc3zg4r7> z%p!;qGt*lYw+;zPV?!SSkT3j3%B4yG)PCW@Fpf#sJHiwcAm01umnP4xk7&&i;!r-E zw&Hw~Ux*=m*jznTxL#>V(buR+c-grG{D|h|yX7MYs-~BeM!`Z2(vTfrnq*6bI>R6d z#Ho7|M~=6PIaQM)dIht0gGY0pN-4wuTVDP2PbBphy zRuV?G6N;)9xyk)r6&X|2eLUl;`sYFAHew%BDeo1syI#ocJ)&hukuC8G!a*H!C=YPD z&^_8ZtaaEBwx&=ww}4Q%5pS%3jVF!V$5gZHlZL8*eZfdQRkNT&Vo5c}G+|QAaf;k5 z3R3iH5~PKC9xOBWcpv!X;131v@5!7zwca)C`HC#X?5!~jnll&?NSED*_rE zv94Q92EQ94cmEMz8=Xsoyj|UHRE*V(lW%U*PH2qVfWaYrT@dgW+2D1C7o1#UI~IZS zbYgQ*OSWQ)5MOh2b-pAq>ToVfe%Fva>Jb;IOL}Z%I=nvQbqq4zXrJ_LVTjK7{ck}_ zP0M`i@r4Teum5!qUuj$AL+lifL({VsDD#x}!F7ML{C0j*UGF2SE!dANSi%@y&xheJ zA;g51P{p3SO}S-c9-k^wkHodApzpKZo7F}t%CA2ai((=KikO=}-PAg~hSkd?C$RV^ zIDPjF-V4wL&A#n!)Qs;z<%ev(Tz~i4T|V_^-w*m)prL;IoXp$YOY8lF50AZ?+{62< zE4uq}5DrGd?ukoLFYK z+K$I7Y%+A{Z~P&a7ka!!KMs?zbks9A*}w-Oh40!NBdC5WhSNhYFgUe@7U0RChqMxk?CCg44b zr%OO$v~TF321cZ$_-3P@@5dOqx2*GN!=i=#I;-o=?@WOjIxt03(`a$TE(hx|M(ceW z&7~rYUVBvzVv6R)gBP|W@xEx63$x^*NfetPjF9To8@K?bLOc=h9{wR>5T+Rc6DX)> zZB2vpnI>wG2^Q!Egf=Dp0lIhmAd;9Owxp3@S=yWVW8qnpIO0j{KsMp2+geP2xtx6* z$;Drnn%GgMX#wnMO%D0yZq;mIfC5nfFDRl?q12)5_UJ#iwEuNy5P#QFKASH?Mkehl z$q_`qc$nq6g?8gAPUV_KZIuc(OX>|!ZKRvwJx|{J7N@&Z4pQW{V06w4=~?H75!d;( zy~No#AkZj&;C=H~ zt)}vS=Y7Q&J)i{XbF@1`kcgah#Q1`O_+w+1CBA|Tm4BR?X%r>NcO{w}IOY3E_vM@i zGrfN?mm;=EgD9)OEjz_R(KL?9EjiNey8QaBemPo+N)?!I73mr@z=!UTuwjgYO!dir zcpsGJXK-{47B=`&jnyoJ$!4hMDA+*t9wq6Bz-z=Cqoy@`BpbB1j=;mbtfK+l2iueI zf<+_!A~smlfCXkmZs>nZ6WdaDMEXSwX8vB8bYV6{8GkW4pEXrDPN}@^(COBX%?Vgl zury9F-}+;3aB$e)frjxw;rD}!Zw@4zv7~GFlSJ0--yo~pNqIkWcl~3_eJris%M~ov zq4Uvp$>tR!C9U<25F7IPh9+sYTUdVHQx;i9YYJ2UsA6ura2n8xPhf%@f`dvc;3{tz z?l%pwoxuJ?aEd+Z+Pp*#{Mum!xhgi8q&vqn&;UD2ObVqCr%~K$0E$Cpi}Kf1zgx6M z(029T8wL+>qA!y)T}H@#l1SiHba?tVg1Hb3FHeOA>512Yn^~ESNa)aC^=cd7L+Be! z^K?3>4jP{gwaPjita`Jg%zl$(d-Ouf^HTXa!$1j!7v?|eroNLx2X*w|k;j(Hq9mSF zP7dAY3o#zREIpe5ivM`NMAq_-e;)F7GlN7D{aU4=*2l8FCGhU4Yrn|~Cj^to;zP(*6H0ok2tVXFsCpit{WM*(t<+{9Dba9&Iy11==J?GD zNwnRrfnP5r;pZ-fs-Bc%5Wx+`O+@cMB#0Q?ZekHf1bH$lrJos`Ok=ECYJ&_BFf!5c zC`&Bt9dbUz5M#ZHGWhVihU0DXIgbyFOr1B*zh4wTDK?Iy6@k`+2-mSy@}go7X$R>(jhGPw3%Yz7^5s%2%iY{p-Q__0o8Q6kS@KOkf*@e1qk`u<+@*;}sV zae~>4A5bPZysI@D-n>MzOm%kjipoyZR%uNd)r(!}r;y@w$qqEu@$vmaFE$M`T*ZFt z?UKa&&bIJe`Z&CRRn~5oKhOg12wcto-D!g>!Pp4PIqvKX%2VtvRa!-c+mx=B)L7Zk zjl`PSgX|*#T=Jp|UBx(~Ios4DCYg5Ax0p&R$Dz520!QmmhTr+S1Mk0{H>l9S<^B6H z+DB+Zewr6qYJ>pY!pAX8l8&;!VOKLO%WYtjzkR!Mk7gSONgphAfy-vaW9Pq{tA)3_I1W<;m zPt&E}rTi^$TGweR^=~Uwlb>J0RoR(Tw-0$8B2x1N^RU&NWSq9xAijzW*ICo*>)afL zdV-RG-PW>dhNoBWK-`o(C{h;FxkO8UB#^!Ej&f7pmKd^W6_cQw^6$aKxP7qgwpCO8 zMKEJp^DqS#oE5gj6?{47HwEgE(GVSssL0qThq;h%oXtN{rTG9Q-dsqOzKg)ow6(hsV)%eC&1gvSnwtTvV|o!+^1jJrbDlU66OA$7<~79w2)%zQ~h zOdlW`0zwos89=seL zTeoCYel>c}@`zJzZ({5FICkG@ga3S{-^9q%Xs_VDAZo{|*~*i5U+PrWp3eHTD$PA^ zOxD_`@y~uo%;CtRvQ4J){JMpx_!_q%}qH?nz6K2j%Mzi&_W$P@@C4a-ul zTGFpn->ZXn`5hG;TclIK^aqDS)4SkRgQ=#!IqV>QZS2bqX2|!nBHvw<+VWxz8smG| zIVQ$oGTvC(6#E^v01E=Oq_uFabdS!;QkV>*Fhkg|(@YuTqb&(F^w$E+z!=uO=Xzo( z6k#Qa?#^ss$lz8Rnbs|3I+|%f9e;r$;LA?r97~gzEB2HM(L+b9Pnx0YmP%S@DX*J z3$X04YB#`5LP9Zy@Z)Y1QaUKz>s6B`mQN-qkv#LVcL*|FQ)?USrakTA3=Z)&dI z*qYWrox+^=*kLPLJ%+(t3aXA^TaqY@i?m&*Y(v_mx?%8tOoYR6ikop9IBEpay3DdFMD2VY z#2h*d^Emk+TJ}f*dPSN$Tn-PmZ4lO+;5T05Jf!SW7@mJm;o35LXkwB|{$8MYA?>OG zr+A6lg(|vhF%Cq7vI>D?5ZAqOH2kEuS5HW4Da!E!*vAO#CZNs1;&Sy!%I@_3I>Z3A z)1!5d{mZ_nmdA}@%jvP?uy$C8*B0spSJ*=?MFb4*__|_tpLZAqCabHy$E<8fbc#w( z&8X<%7h?Mc`16_eR8=fT)Nrv_(gHAdO{<*Lm?bvMN8je45Z~HmCw)aTqJU5TED$05 zq=F;-go8msLl8w2 zM-s%Aw}o}%#^aT8HE-#;ht2+l^&PvaTdIYx3>`S+X;A5cWz@`McUud{GzotZHk4T$ zJYKmD#D=9+0dcM!c7X=xTva9Q&A+NE${6GAIU2{fQe_Z_L)bQ^)m2$XnxYvT zoJ4O9Uk2&TOAIAQscgYH&>>a`anl`$?q&7pe0s8-#OA*0tVe%vU!E3krJ9+~3}G;c z@7fGI{8LdjiEwi(IymFt3~ef%=3kQ^Sw?8JPDeQ@{Ky)h8{*5)d(-3Nr#MQ!{2ZaT z_P!^&xxv7={$+_pT=BQ1L-XN3Ds8tjP?fgz)qLtZ)#Ma{Fg>F(`f4K`jJ-jKs+ZS@ zlUmbSnZa7#!7n(0$-wTGH2iJAaPO6E)g;)UKoF*n87Y#q@HP^ifeE8lJAA?j^!CRH zTi2}yYfm0umrefImZ<-dWWXPR`i3(-DIDRBKvM7i>HRQy##(vHwcAxUk?P5|HXxi( z5?M0usf=*tpH)MtJJuRXR~+tynsyw-3Hw#y$WC%XW6%IJ}>(WeLCIki)QFeX;Jy%2l%3B9E~K7jfB#Ydfj^$({+;u>NIAcL zp`}74`5HWXQb9K3;vY1Xl6sAh;fQ*8yT}rAMr$AZX1jza&%{qzUV$x0X>cpwM#o5z zM9*c@=pTP1BRb~g_N-^=l4Xkjq;YC4MIQI2Ngr*>0(`# ztu&roye&BqLZWG5*xPxssFfPpd9{*Yiy{gE%&)|#mL({G_M`P_&n6Bu@#GNsmA}8M zOfd^RFqZDGPMOOSqzeFiIfB2C-D1daWSQr8N)qK0m_|!|Oo&P=#d|Cit+afV3d=mb z#JFD~UTwoN5mx%2)_2bHr}rSH0yWvFKT(RA1GpF*sPJA-8z}36irDAWh%EUK#T1%^ zrTH2(=-PO5O!Tn+Aqav?J2Z~Rs`A|ul?7Ls%FO=?n=FZ>EDMcocckPZ&So7a8VXRi2m`O1nxZtQX#3W>=DXACXLWF5fS zncaaQ9_8LvSk(yg2l-ZX-o%EMFYh6O7?SebskEjas}dlEZ`*Rm+dx5A9iq4x4UXY3@nSb*wBFjZ#9v0+5V zdzB>*37lebN<}Z+&Kk2ydYgmhQbT*|z0~mIsfBT`ev9TA-L~>uOm8=tA#+{@K9mhN zJf|W3S}H+i4OSiXc;qt)(vLv-0K9KUX+f1(Ad&vl?D4CP>`2xqwWX)`3#8nea)Y|% zC$4~(UsENDRq?guY|JV&$-82NFnw%p5)8Nt9Em=yK9y&gs#)A4zrABEI0p3dJt1Gt zsHkYJ^P4K^T7Dny@u7ElT9r_D@5+IN2;seEwo349oqxf96!1jNC#l8WF}+|WxmSZe z+j$?nWdd_~d;wD}R%KgAKHMqAl`4y!oe3vO(0X>Cj%*9-qEuG0)Kb(gW??2(Q|I0% zZ0+cdTsD+}dDK1M${?-(y7_ms^mzp z@UOSrh5Q<|8z)n|8^j;l44^cU44K0YvW9x?0tHwCbIp&6#987AEir@;9nfk6sj+vN-z)JeE=a+u)krFldS>7~=21EHn z^>MHjTYKsHetO+vN-{@V^SDOD_r0f-K2&1_!|@d$xFC#^KUX>(zc=H}Byo7}X}yTX z;heeax`&pFq68UG`&;wS_uh?iOmQ>$m^NG>Pneh}yUKJF638a#$1m}p;GWQ1HPX6q zN=776TTxf-&g0Cco;6O2->k)zQZYM{biot3yh!oNW}OW%IA9Nv#UoTIRgF{xDr6Es1jiG}oUBpzNY|*H^?vNLvFlLR$(3mnV?;6&A zJFtDD+uQCT^s4SLinos!cjPKij)#$KI|7`OJPTK{nZut?BxP|MBxnB`}Xeztycv;0c zQD#YIJ$nh+k317S3cM;G`j&wCw>@vP?&g?dPVq80pgSt~h*SGXN)x$W{M~DYj#|YD zwo18kOl)T9nw)qhk=VaUTKY3-&xnAg=M#h4|7FNcCCE3|lubIuGV`sZ0p_!nM|J;w zgan&+D>L+a7W<62bxkfj(3Kup5zZseQ>fT_^;+X=wdE2~{M{@+&LS00Cc`wicVhIn zaK?@iK{3B%V-jw*F>*12scb=Hsm&-wqm^TbGk%PVb#bUA7b&Q7d;aXMysV+XBwP*m z(cZPPuMnPhf8ttg+#)M^63_7L3E{jM4%SC(L$Q6}JpyK>!o`brw5=_YR7ov?c)-4` z5Kei;(sF<r!tUQ^Avrk;h36syUG7QrAs}zN)XXEGy z%e05J>T0{_ct8cv4<;Lt(Bk40pinwYa28;K_eGx5^77DSC6g=7NzI))>(WsCgr9k@ zjd|3pYQzfq%uF@}#VnAW#BMj;vufoFnS6H#B__&GSD8ojr|U#io+pR2@I#qK5PAc; zUYj}T7FjKxT{PE}`JE{n^IL;(#M^^u{B|X__x(NNI8~*cTS;)erTjf>cd0^IZbg+M zC7M&ip|Z_-1!GeApTCEtSfnlWJ*s#ZgY(QZSx1EFHGeV?be%1ow3V2_2&Z8q#o9jQ zLlm_SNB5YlJvpZC6Jv~{9B=+aXZA}JnjSime-X-rXxua{+_Q*<^laerd2KdODh2uP zy~Sp3l%f4|>@z4miDPi&uyb0|DQ0Q;x@Xry-6a^wvd4KLYJep|=Tsj(Vi?>sXbd`| zp>rtkmYvCBlk6Q=_<50Lg-}^V|LE^s@N&HRd-Dm4gQoo-SSuwED$f`&*Fb_1D$!UO z+?lzb4xFLzb@z*iZuj^aSXZk@c$u@xG5Ma$vj*#-2;>Sb7uz|+73ZimkRDW@wjAM0|>HP)@n%csRWy)_}hMHU+<0)u(+`{l9oX+l4 z^BI{jV_&pUo?x_jOzQ$}oaC_qnH3rTR+fC+ z%eysbMFsBYwul&0q=2tlTe^kgDSR~;a%xF|x@zMecbh4nBfRk^Jfq!s@8Bv+2>eHi znBuyH6Yg6tL;6E*Ae3F5lI|^3%p>L8jvTS{6n&P`a3+tzon?3B7c1N~Lsi zw+}1xn9Sx_FnmqKy(%&5@dICbnq)(PC4K!7Wo(74%KlyZBWd;-efa&@c@=`M6ACx6 zAZ`9dEUvZegd!8~c;`$Gvb9JT)9t4V)Vs<#0bBJ^gX!LWbA?0D;Uw-hq;PAz zlR?l93(lyOU(&C4{MO1{)*oOT1YZG2l!aNd@;QyTcWRM%z##1)dUHqf;LN0jK2Mlm5@fm1t>tOI#;#n<>>Dz+D9Pb(iBGHZhoc!ETvsA$=WecZTFlJW( z4KSSjzHiW~(m#Q9g`F`oqokm2>FJ2y^4W%UF9#DHfZ zJlVc-;dCuUOV6`o@F=zt&04F#V6R>IIR+nUI^^j-(pAgz98(fCm4zD{Xb-3+d<@UaDA5 zy@nEkVi_*}kEicBi09|uFe?>->MC;8eoQ01jG?JjX76=Af@?^EWeP5VZ9}!7Eul}w zc%=y9r5h~7MHbRq;!c zE~LvB;;U<7dm@SIqJ;Nx&Qt_PnTLgSveP#rJZStYBI@aAa9wG>pwy+MQFBsXndh|`ZvSl8dmgU6EQY!K38@mQSFY?=H8CZ$^|RnG->_TU#@S!99NG3geC?_rQ|0 z@OnT1$;DvHbXFuPZ(X=Sp(mWlYE3P_OlM{_Hab;hr_j1VNMFM4=@oUR)CXGxu@g@Z zgxTVdrXU)6{Y(kJnX3Q40IC30|9Id?%lkxOLG{+9h9GNvdX>2~2Y{!u%q^{Pdv1xDRfi=(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRb>he2;n5KHr}AneLc*bDnB0R261`AV`V?K~myiO0>d~Em>`M zhr`_+(GlGpVTZ#V(f--tKmE@kw^wK8s!V_qPDG&!nfIQv&)(}>!@J(~E@Q2|3iSBVYw1;06=|B{`#zrM z{pf}~##dRElx0a#6ae_XkK;IGS@y8^f8qh_K<7udb@}Bu4zBA`6vdAW`Z2t$wG>4` zS(X48V+g|#$8j*mkmotZ7+lwVn78#jp#0J8J=&cmMt3-v;N0s>sXpoT{ptTEz3b2Qtw2N!ckA5Y| zoYGb}jv<+5+SIG5Kj2C`^Q>1DWaMSrtHxaojvKVWwU>7Hf0Kck#EIHi8jh9HS> za+l)5K5-|)6drEo6P>nfz8K;dhbRgetPLKUHaE;rf zOpjXR<#}EoD`W6H?~(Fe{hn!>HU;COM2I9w{_QsCqRPqhoP%o%!r*n!P$)71(%KOK4B-M*Y6O8(IXqg2W|36mM|U7D2h7&OlKMUSEo#F6gYPx z=ChR2E$L6UVLc^!E~B^BVf#{_!DbKFcn@qeV#tzG$iF`bPoJjg0~L+;@b3S18gyRd z?A_jH|Mir~t(@s@MsR1qyf>ukCJffQ_?wn^%VXnYpWa#*V+=vy0;{AhW9 zk|a2e^KX+uTMqVzjE7UkS5x-CX((mlpgeWJMb6t3en9-t@+ zqA2?F2cOxBsw~NioYDS-{p%A(?`BNjbjYiWZoflk&8PoL$;k`bbbGx9KGTq!w4@(L zL7ArMBjwI==#nHM48wo(4Z5OaGMsYljXMm#X(?`oOx!yJLCD})*m^o9Z=qOv5rIMshrIhd^S$^=ytn!Zf(Sm z^E+o*2JpzD7(S1a%ho#&??}^@-k!p&WJ02G-CFxkgPYQchPd} z#h7DfH|ch}cUA9?Y7F!FoFEAP+;KZ}0|Z#fa%)4HH!k1e`Zp&`-U2fX2~QSmy%2Ef z+b&s3ho-qHOk2jC#erCq$kFK-1x$(#_<_F=OR}5kN z`8DXGEVzB`4%c7bXZVE>w*$S8&$;mN6Kt+;@VJ^D@25Tc#0ugCr$W53KyJpEN5+n4 z>69C9?Q;FgGbZm<^amZbKkahi6DJ6qhes!}ETgKb_XUIIdEFR`;}~NM*4jUR25qUB zCkac{|0!XX6z(^U+NF*_h4Nw3j&xFT{m-T(`voUI*<;+ zUgy`p@-{zveuL+(_sQPr5Ij5Q%#Zn;xpb1id$Reg>$=TDc@U$y`Sls!{2zCj-zk{x z=DhqjH*rFPv2_aYD5;C&#sVWsZu}(DpeT&F`1~2xwmV!tw#WXTxxDjRBaCY}bMeGI z3vkKn-w&2A9$pY9&-3to|IY`(zo>F{BEu`J5q&!%>11sFti$P7PO`DNfn%P09xL9j zs;UPInFhSb5cFOAj-j+ARc>qY{^C%`!4QL#f6Lz)19@T@UC!`&mT=SHxOHy)LGvme z74`JSPYOf$J!WqDDM^ zm{X3)bjp>l@3Q;7ImxaeK3%f&kq&2`+Ij4`@&}oAOztGS_a{Sa>T%}Nefp<;uoi0% zJ@LYo6{>AFjJfi30dmc$LCtT#s{Q?fFQTK3 zc;d1waa<4A^Qb1bna-!s-6nSf=JQF@`mU<#htosPW;4G3C)e2f(~962oce6UiHpaG z!?L(G1tt#vI@p!~WNQgT3GT|4Pf?O*vX zNQ#gm&*=C2{7`iUl61}+e{!8$U$6u_1(!az&Z#pemf*N-{~A@EV*HSDKA{-z{lKo* zb=|`pcZH|T^Bm9fj!aABXVNq!uQJ@g5O*S?C_41YcVXG!xgJ3fFi&PbuhBlFF>xH%2iG{vlPL$2 zJzUqN)9Db$ab2Gnm+9@x48QY-*doR8LW~!HaY)~LmFc_R#Bp7=x3}r{`#(G=$80v` zjX$};?w3kBXDcp#euI-|jxXVwWo3yjeUk9auaXaM5T5=J)%qFovch+rABaKcdA`zM zWlTxX5P_+*H?DJI2TH@OuVf70p0e>&$mvh_ISRa4bi{}|5qsCiy!+}tBrfY0Lk4Gq z$J)5jDUra1j&IocSciO8(LL$YKONFJ9x;8f;P!7h9K4Zp{OOcV)LFU*x|0du7?17E z9pWHvKBxBJF23hs9A_EhHV#x4#}*6*0|Kv(l0Os%Jx}L+|4**5`$Y&&mR$O|4Njcd zX{zM1u#{y%X-n2$`8?ed7n$CCm(HnYaW+mdos0>C;EA`Rb=sjnSBy0b!zO&npUdC5 zuDi&;9mcyk-~Go23@@i_JrlA0LWgMGJ=&nDs4}?z`x)>4-iRtUtX~Rw`9IiV{bKZi z8gcso>JFsiI2gxp^2bBgUvvn&KHZH7&v!ZV+;N8Qz03H!K5zfYZJzqfiN*nFy$(Ss z8js8&lvxx-og2FyoUQZl#+R^Vjxi3lNO3n#(L3`(W6VDk20c&beE*AAx&23$;B>*I zpWWc(nVqH6I2+C>ZOLG>Tjy10KZLvUT#duJ4xXDaPZF70_(0pe_j?7AM}_7{+a}cz z1x-Oiqye&O>ZK}5Y_XU_68-H@0-7i%{XDcp!ev=btm(vV@ zuyoA^X__`S=!2L>zTa!_wT$cEm_Xq$I32M4kr1z2Lvl%y zG{xJ!8X&D^=mB76`G&sH`TyyGsVhwHpPVoL@33MtU2!k9xx$ef0 z7buLtcD@_jbs*NZdaQkP$nGD(58Zu--S!-1Fwrmi430O5TAXK-mm`WWH-Lg ze6&w+>=NBmm+oqAc|Sp8j_Rh|Y)a`$SQ6+V$ieMj5oe?mD^u{;AGCF&u?(@><;%Lwz#ghRDcPPt_w0PQX)4k%Q9Tg zV|t}zwwn_UT-Gl}xW0KH&!zvZ|JxY2{oNV+?<6>$g9#v?TJC%&=h9x#0;<=~2;+wIn@!-YeVYmhXts!Fo7 z#_r=dZj9Mli!Dpi*_0p%@V!FTM2wKPEamgTPs6lFnG)xt1R{I+36`F>#-uy!^i|DMa}or06k7WiJc zBnuISVe@(W;~Aa<8w=?&aR}0&k^?A3V-N(*z43kj$s6?k-jLnzZ{XMZ9-GR?S` zQA&Ur z%!{1CIiLPXpW!<>wzN3DVQ|5t@Dg@+6R^-LO8^bWGX|_Dak!IHa3JG)X`|Q6v<@kwh(j;p$-Tp&+UULYmQ5}IB4RT#i*Z{L042q>ZE|pVPPFcF`ZGO(&`=f?vuxIAZD?eqD&X6Hf0rv? zoDdFNUiwe_Y&}!UWocM&@U+8)4R6uibMbsb7=&b5)^x_QEF(!0VT2Jy(OpBP`K)3- zDq-Lfc3sMnU&l?vOj* zNx(5gTZX4k^fA_HAjvx2D=4cHYb$~2#P*r({`1p6BfC?coPLaTGItr{ax&F(e)5#Opq1f2zyo z3;q&UBg-;ovl+&iX7XH%i3=~d{nBWJVUu%1&7JP`dQHBVq;vLe9`OBtlydtU8O8xyC8VQ*kDNM2Z`)bQp(WKY z#?b5amI|U(g{!`2K@c=J{i<|hl@O!k#2T(!KhfdRUv!DrXADkuIQLV1!Y(99?GVy5 z#W)7nae3=Er`-Hv-XLY-ey4c-9Ez$6a14tuH(_`^_DuRV5x4r&aLnKA(ipy zJpYrpr=KBM(N}1%40%F1wB`0Y2aMmcIM0kY_u(DF;Qf*FU9S$w2k$0~ucQQV$;MM5 zUe}T&wUOzZ^YB4CO%Wm9L^O%TQ*}C>#=8a|&KW!de(2-Jh9WO0Y|-T0qID;bmb`be z=vwyseH_POGMP}8Ws_!z(L_;%UnV4bH*nmV7f}^3y`6FA$^k{-LuDFI?Rnl(uAHVR zS(Y^sM$&~gLZkNpil>(M69*9lL1V-c0p*}baaf}!6&ufb44&!}Mj=ozpV!e+U^d_P z$YvFLZ_L^KPKrCIh(GM%ZCJ{2#yrU>@;+|pHM$yQSyGf0ZZhP?Kl^_&d+VzhKg8}| zVg1+sONMcNd$rXbjAdcfD6d(*kjI-brWO-vG^04(Vs-6uL?=Ly5 zcx!DSwbbpL**L=qEw%*f)M$$FEYoxX2M%EnHN}-YxF(&!g0WaCiYmtzH2fFc?9lD& zUa!~uofx$ku{1Lz(nv!{zE_Rw*HCCt=9rWvV!j+~-}f=yl9Qi_h}J!JJ{%LpC2qGO z*&Y%_8-!uBF_}!7>1H_$zVB1n3R^%rsz^qb=%h<$Gr;v-sd!#lk`N=mNRpUvGZi(+ZaEjd;S%?s9Q%J>{3c3_asS@CdYoP25oJ{WH=|qW&NC?Kj?m7 z?`<4&IELiZa95V59E=KVVeZ<#)F#pQdcEfFG;S*dr#3DvH?pcKCX>k$q$JISD2kd~ zGzbEw(`i!-&gb*SYl~4zF%X0ut7j>yl9$775! z3Z*FiyvD=ytn}gOTrC6pK!!=i;uQ4(Mx^6t6)$9v@UUXYy?a*H&zQ zD5lq~(+yj}jjv6(`Slr>etw<7*@sgRl8U~v6`L2j^iJ0&*7K{oR*XrLK^vtQpk{^X zJX=Co4d2ahJ-6mbxRx?2mxwrGFye(BcL6DyI{ZaZ)a0ph^W{Nm@0lb?ld4#oH2JFJ z?a~+#?_?{B*MZJ4m+AEi#{pYHwCz%ugx%dSRdKkvwcqbI-dNK+br%o=``0JrRmRqd z0dd@E#9O3!A-^j%$ZR%i3Ts_N3JxtpyiKZv2Z`G_Hc8Rs_sg=R+wC^dGS4z{MP6#R z?d96SFnj_+GZqRm*vMErw%y>)RcYCMJ>l)&8*%Kz(E}TF!=YFdRACU}SQiS1sw|nz zr^Ip9gwu9Wqw`=fE+NH8L8IAUolb`|OBmjmG5UV(3D=%=FmXwmW=r_5{Cp4w_}&~p zsu2_ky^>yt=hqCu_R@B(fE34Za~S0MYlAinPR2a*R~&BqX~Jwj#b0wc{$nojT7YBX zrDlobzmmIa+JK}Sd6v^%kHCq@^Mb0H5{6*|^9igc2T_b%a&+;MQozdlO1;zRbZVMI zRSRv3=asg$L?!XOK@co;G9~rX^j5k5av0JyeS8KzJ(x4j#<*K{2@iHX!^O`HIQF5K z;6%YZnG;9xeT_LulBQXrVK*@x@p=y;{GvG^a&t8NqjB85Z{@uGPg2~#;pET4;1hXW zr7v!-hU@0D+8euz99VL3fKI2gbZy$RRaMm#TjFujG;MewQcOw_DNMZH^ChQGKtA*7 zZFcBwh6H}Nbic&|il>+Md;8!EiK?=7_j5LzHIYX=sineVsZ2@W1^9tamS#(lQ<_;z zX-!$DMHq|qEUxF_y53R`Knm+ssf8GTxbaq!esnsWhTW!%NP(0_qY=G+T~uLdJe(dkl7}RbD9chD z$ECYS*Tmz^=kvqwz7f#b1lO(Q0;B+J(v!t^mh?leOBj2Cr%O5{h8~6?qtU3z+kM|- zI!qYfoKqGSciUlZ=Zr^V45o=vV$9+wBwebi5*#pog=0)3W8isSqw#z%CZN2hX7fph zQ0|@QJ|@`CT1%c*SRV$*<0E%YyN*Y<+hsPNF`LaOhaUTHq~z0zXx(G|l8@=}OMM|mAO*7?h>)M@bUGNvFr81ByO?%N~2_Yd~j{dP*3R`^|);~x!q>Q}pTkA+JB zyyyW-1us(?;&r6sCtjjGR;1xLDO`lhArIDZ96~?Bf4U;tF_cw7nx)KVa~$I|v`qQg zhL5Y-(-O){TQc2E*!yxpwp-9S;c)VkUA)LF5!dCteBWn2opW$~O0=GE?8FwGPNxa& zV%U0OLlbm#{;I#LqyX}Hl5%J|faLoEPdc7MHY#}QH|E^>N{(ad^kI5q%53QJvGd0n zsQ!YE3i2LBQ81q;l$4mbKB#(P=V26}Nla!Nv zm(5-X)C77z@VWi9jN9Kz>VePDp-3yP|7pVda~{Da2#RQW(~$# ze_4B1J6ODk0vro>Tdr`n=pF7Ds&DrR8@mwg&svhOZ62>kj;4sH=nxakfAHpC24CTQBHm*Wj;^vyhBEv zG-PB1N%Bv5$P%F>QixIM>GSrCq#O)sQZ&1~eV9}QWmcePF^qvCt;oj3kzQ09NX9W( z3+31)8h3FjnnNp$!FCPQ{zvD}LI{(?Sl@4#a_iheSD9Me$k5sJG3M}aNh+lWXR|cJ zR+fW z5^cEj&-g3n5#=7&=taQItG5~7nbF;G=&Y?%mWPo-!*%UzYD0Hg$Wjm=IXGqcn8-=v z{V9{%8BQlBh#%}DPJFn-&96-vU(KlU8oNC9Ld?!fJ&G*Bb-g8cPQsL&&>#pX63ctP znep!LCAHyr4rl*D!TDe4Kv-a_L+DF#Zt-mGVOWg|XIa)1VUqIn`~3#rmGuhZA$5V7 zW{Xbdr(CiuVDw&2=Zsp#(Hp6a%o-d%L5nBm*+XjB&Uc< z;$B5rR!h*O=66VALpaJ31=cTwT>RV`-~VSrvT=p2EJ4rV#HS;=7Y$jSHPKV9L8l#g zSungkp_m!sPZspoJ9zGD?Y?%uK%9(F7&KHW#kY<|kHw&Gy}3{K%}t6I$MiQIY@glM za}lrnM_XL^@`%};jQ)v;bDvqKbH-3+KDL!Vd9H`!I*n(+u}p3hT>kwr*{H&Jh9a%F z^2G`3A96YMN*~88-$X$}j)IG{;Yi`40sT0Rna^iSgQyz&l~C$=9)nX6XMeuLHC+mu zV@-i$TwL$4lPUSRkoV<5^?JRf*+4lof>}={lSAlg!7ULl8HOPg4rNs?{{FE0C!eY3 z{{-ikgIdq>d7SwR9pY`5+po_T1)kA<>y0S(XvSA)Ss-nxq5^Y*S8T zmSr4F?%;bq-Dq&=5z9KSlWA?og{m-wZj9#!D;q3Fi7je^jz&nzvcwO3iZaKV3deJB zeFx9?nnr|9Iplq-(h|fzQ5-RwRP689T!((Y-^>|G2o>+DXXV6e%g<^~bEng3B9^2X zGSy;CJv~w*3x|hM3|>B0r%Hlj%jf2Kj^i6neX_^q%l-l#s*C#hY`(-3m+u{^$!$Me zV9cg=5J$ndZ9~>$c9Jr+i%&T~0^>dwgWkTd#%pJ9QtoF=_9w(U4>qAv79!&3P?Z&F zl3|Rqgr~|RN|Mhh%YxZ#j_-R!orvCM#O5;*x4t>A6Zz88x!@73-MeFW)UK5F^oQfr zo-PbS=KBTj{^^kPj-`Lbu=C*zw^LEhtHz5qy2lG7CCloZSkfoKV*CAm)9et~PY?~c zM)CfFb!&)BQZB)=b!sL$8ZuoYeQy1U!8`MQdCe2Lr zeIHlG?ZOh{1V`@0(T1$s+>&?i!wo&2`lTLz*D$+N5cC|*{A3q1$eRbc%BYVrXt^H!GoI&?jZ5D8 zCsVF{ImH&>1Ucg?85e)0i{l=4>%@b|`*b=TdcEFKdeNjzuyg=~pFEq*nlwvt>7p!} z8Ah${q-D{Bp{F55onq+&B15-Qbn9m#9Z6#hWl=T;T$L4gEJ2k*EA4i>O|%LYC=U*p z$~3frRYT31^(awM7vU>eoeH*mtmGsI52u8Cs0`e7VQn1qC}9+NczP1Uaa__gAwF+; z_HT4ZMg^VqkikZeJj#VMW^{KB zH6mQstx4{S|JL%cnx{}>&vp7SOJ-OO5gp-RH1yGKgr&qf4vu%2dy63mmaT^lq=**y zQBa~ob)#_Q)VO$F@#05458wBh&1Q`(u2zJ~vU>QpEDFd)*r(S0(|UOA2ACYg`!!zV zcN^}<<7C@C%u9?%3`a(Nj`HU1|L^-AzF$vN&yzWY&B)3*v#BADYtJ~HPMfiLy*5qn z!fxl!ola+|5tEiFS(;HN=aqt|!Y4T_T&}vB1?UZXs(~R`il!L2N zdZ#_y&HCZ%fn3*f$!;2MetlMJLO<=%zvyCITjQ_`Pb^+kyq18yq~MMcM2D2lw{(j2A5rw_(acF^wFdXLMPO=)mT@18<1 zZ3B|xq&}6k2;os*L_B%>{ax23j$#aEL1IbB7pkRtoJm5uK16M8HhFl`Y{>H*<3iYX zS$o=H@70Pjvv{$?#lX%KBO^G@o<@JD9|IRM68zpNO0;0dw zW$j#W7`YrMXYl=BA93qzbrY(0#^LF|+F|R37|$H$q;SfwCl2L-C zx~G2KlJP90wvuwfx8D6jI$@XRPkw^Xi|;b%d%ZMQK~I0kLzzye&5jSxb??fJgz+|+ zOqPZ)13$p7Th9K)ko60OVg#KNE@wWqh99{Ud2yFexO{%6(^(?Siy>u2#%vd+S4;9) z#qgbsz4u1A+abwx!7p)2s@;I$+bPu|pv-PnR8x;A3URF07_8=Tw2=ahT*#lTGA8-H zVl?{abTKWFObk=hj|8ci&1OV#jfmLFEXI{Aj(hLCSmW;ZGH9KmJ~pvN*SHMM2kgCd z!2Xq-*$XqeaqqtAM$_8#1HN_j5BQ(H{9ofb9{<_T|7|X8y?9q;f3E^l8+(FO+v$*7$diKgevDl_goA^F1~Su>NMVTePI(-ECMF2$j-F#G%wk?nx_{yUgCJly z95x|Yi2luV&t#6X=F&UoGI|U8=REo+BYZEwhIL^S_&#>cqjSt-b~~$;pZX3?d{_($ zZ(M4FAPAVvW=jLPZG&k$20^yD*7*2?fCzdv^05|$#xcZMpK32BnWnI5S)~E3MF$&*9xZvDJUp4BlRQ<7L1YeOrcjz5RaN15U_6U0>|&g(=5VZ?jMzBmFq&AB zY)%mRO{ye??DmTugNxn*i=R=J1<5?YR(2^JYe-1OkmnhDZzSw}V@h|&=ftN&I&0BN zCYyM7oyXp_4@PxB#hdC@yBOu60H%Yn4z6))aU8`pX)jXJL$414BIvXV9;1SP5Cnv0 zO77g8bLUFI&dF^&&p#4&5lE>X^|3^Lmk*u#^wJlQFs8%YDi5vy|Eg|aLp#he2AzOk z`>{*Bb8Ey)CwsWYP&Syew?rkC>RzgS$yxP)f&83&o~&SyE?xnArJD!^<>Arx<}fe zwLwZFLvYo#ewUy7@PP4j24%6BD7Q_kSt|``?hHq zku!QP$8$ZlFI5D7*i4#h-97Piola-5EXY!oRg;HnVRGSSx4o(B)YsoX@3Zwn$mTO4 z@p^EV$JLv=w0CZ&C1S*m3tYU8%ty1B>j<{bBA!S?xMHLtwPmiFan z3|gM;y;gbXYtxOf$I6H9bYr4H$z-==cxOz%*I${3wMpkkK{;YfVxUr79rd%ic_JP} zLZa{cOUq^=-@^nxm0e!TCch)H0($mQFT2t3k>*24x)MbZd68i}OSJ7!Sr5~xNA-O- zXj<3v`Fttg7wItZoI*U30#mL>M!?#|o-w9YQvFoKu~$O8z$NUvD^m?ku9AqU@2wsn zo=&GrBz`T+rM#Ks>;LN7>kFmjd9gRCryH{M|`f^_WKt$f#YnOAeVn=uAw$q9%<(M6b+2WV3`_3v~#ou$JgQLl|1 zJC0Mc?Tmx5b$t~@Q4?h}Uq$EtQZ$Nvv|HV)YN*G$cGYz}dK+Cj#em7xnn<*K(h4x# zl?!R3US*(Ky0-mbHMA$Gg@*A~8MDr{wFY`QBf~B;stZU^-DA3+FuF5t{(N#h*rqNvwZ|73 z1(B`NOLW8=$qkpGT}^V=V^ad*xsF#aAX*?3olb{-zh7T_ku#glNt1j@!a?KU`XOqe z^7h88qww0Lna39KM@JNiY}4tqDK^Dh>Xb|mFt;OWUSte!Oes_F!uqgjq@(@0t9T+h z-I59Tb`)=ZjjU+%?bCk=fU_2Q$Qej~jf~{NA(lYM% z`>d@ED3gk7f0XdXua6kroa1^9{eHiJ?Q}HIpReR0i6O^6+#w3%dbCV+8U>@*(!On*kS?cC33M^8o!ny|lC@Y| z>l4g0;M(MUyGtyrw=+^(!7s`e6`?VYjj7vwbTTf zge1L#qY$UEtf*!#Q4rGUhxndf6TDi|UJVUEEjU{Bl3GI=GVOZdv3qC-m#t?yWT)|LSos1f$6s<0(YZstsHWfa*$bw1B=U60qUkN6+|;QRdl z{^T7-ISr(wJ*@V`tGFa>=u1y;=n7otubM~P%(nUU@7#Gk*#B15un;}p zYYciR=M76ve%|5PztO?puI|b?rRdb(NnUM5PR***R9PunHEAhHl1A5Aa&$3fJJNy_24&Kgq?e88?q!lm!M;oj??cq8BzVA_4!)TTg`wo5(;JO}Q zmIP#u+UlweQi@b5_t|C5O z^MqaJkQ*Y{YM!UWCt+iAfaiG3rn4o2zBYzcg^@@W=zLaRr-tMteL0K}hfzb`zfw&m z8S~QK+quttU^>rmMlnGgGzNVyB&!YMX>>yugBr7zzQhw<>*kjs&d6iBpI}ea>^sM} zIL;v_pq(GLQ;w>t$VMgUK}B*`_)>&6vAHxnEc_&l>Zy))!Dg)m3-OxA z)4#A$!#BQZXw3DZdIzxedaxBaod~Gt(I4$~bcE2eY`RFa)-s(=o5D$Mx`b}=6nU0Y zQgHTj5&cUJksos6xpkaQMV=K)`KVqrBu1;@Kk1+eA4Kw7tyrp&7VXu)o}hP|NxX7B7cZW6|>erA`RLu!$^3LISBnoDOhtmZF?IA3;xas@KM%1-fiA@Y<-? z6HGbk6%=vO$Ij=qw5lrpbVJ}?#f6YlG2nQI1)Qdbf?2FPGe;8t#Yn{K>5iZt2GHKQ z-96Op@h}RTLQT4P-eR)bi#^=u4W8@b_YIDz_n+udC~5X&S=JyKG6SiHT4f_ZgQz(5 z@Tpy_8xH(nNytzzTk*J3OlhK*MoF|W>nNc|rB*d#j+)7wPZNqgm#~NyhrL`0?@1aZ zxqln7)6x*St*%?%PYmTa{3L_#y5t9j$#Awr?-VbsWpCSt+&+!2ThG!N&r(s=`#2U~ zJe%fJ`RbdjAFw9%=;cDfBWQ;~dH78jE)UU(Fb=R(9PHPF0a08d1%_G|!*N`)?2yfR{P#V(xlJt%xo0Oz!g00RT5YSRB~}@9L+r<4bR}oLo8$E@;e}2;cv%#rlM>ey zgmJJEq(9U`E0+XOF`rA+fQ+li2enaFb=V$JrWU-&u!<^I)xHsMusF- zO)fn#gZ6!&!KsLwU&%4PZ~qSm-1%O@`lXPU{zH$!`Fav! z^K`!n|3`TQ5hc{`t93ABHcmrS^6-kXz_%XPzc}OD|MNaoW^rS<@M{65e=GtHJ)~yg z=^Z3`qpXB+NjI8Z;A&^M<2i1_&Ay*e>mlA%URdk?-IY@E1AfWPlp8M9xhD6t z(+z;`j?enVko~t3Hl7OEzSPHeJv?Cfym)X@h0~}(2s_s${1YNV=}tKZ1)P0e~v1O30je?y>4yQQlECpu~ZO_Q;Lb9^AxNf z@2#9xx|dN4C*~+|8!3F-t@TY9t$}3F&{rNHIr^({K6TQ z?NdS*)x@B(EEx<2OKT-Gx}gg%xfUB#T=>P9-g$$Q`}8ij1gCSdv}huMpeJ%Dq@XIx zlB_5RHcsJ$9sDCm^m4D-(=4kT(yGGHlpcZW5k}!dJGmeTm`o-|E|b!f1U*IbL=Czs zEn(Jybc(ghyp1Ksl=9O0CTbBtEUcgI&_7u+nM}yDf-rQCJn@=4Ah2DV7pzJ7nuH_c zQBp+7#CEVYBhfkzqON`nq7aO^#|TivsN zagU+d_7+^3^m(E=wCB6Hu3@%YGM&tp3{~gR?d3Z<<pEkmeS zNYjiWFPiSFG&`i_F9aT`FZ3#lRq2A{&SKE3WDMH(_ilr>Dk4ApOY>LskVYHMmHMVh zC!eH2A3wW=^YQ_+amw)acnm(*%9-o`S(@q(BeYYA>i2`;DnZ^`a;y48ps# zou|_&lgXsn5YX@UiK2+nXtdP6zl-gsXb7w33Xk&8?dD2FRf{v04{u_U7HPSNcJz`0 zU+a&=ar|TrItoL&8!=86QlwRLidUU*V+@|}Q|1{(I;SdgvMk4I5m|JavWgSZ4pVww z%`t{Fos*<ukaO`vcTLu?iKC&$?;pr%^qQ~uvyx`X4D!=vG z-{alA*SWa;0>Apv|Ae)8`z{`dHfTXY#2_RTon=&;-4aH>3Q*kLTio5)qDnRhN1J>!z^2zJNQ_T1_{;ps~o)& zfB2~JEV$ElXq;>SbJvl>IC&Lq!qXT^Tg>P%(O}=&<3GA<$NB{Ajhw)=R>QE%Hncw* z@?0E5x3N(`w;}9SFCL7+AXAcW%!s? zz))r_$yL?%IDz%9Ia-ehVLvR;nK6{;e*n#4LFb3hD!N|dLbL*a{92q`UnJWx&AQx` zWx4PUJJ6t>lSv47tiECP=#jw;6X+knaSFZCkDO3%kENXur=_=g_+b~0Jt)JEdst(M zPJF@V~133lIoZ)HT-%YA9kQk(3&u4)7WZfIqG!mz$WuaSgefr z#QmA!+FScN9y|F*Az47$7b*IsrlvaGMU(s6pz}9W_TddyKtO>Wa3(C%q6S7r>HRLbHv-h{6ax> zfR^PRa@HuUXd$q7z4IHa75dn+KTYNnp9)^`j%O#F+H5DMUd-8^T>#ytP)TMae3Wow zYgU&C{G)#Xj%{Wq9}!li4;P!*T2S5Tr%RLyhVrz^+}_WCF!XCb+q|GtUa0St~25c4O7tag~@s+r?pB z8z33oQ2~SZu^?lo+-8tajYr*$c&%OHs@An)5Et1Fjh`g@LHPc3%{~SXd1Duj+YCvE zO;O*1mg39b_lWIHDqAyTzf(N_eHDTXF6Wg>D{S)U-Ih|utFO?1iKJWab$5E#3(brF zj&e4Q-!UZ9nc+DsZ$xWN<7%`z)1qBBw`+%QU;*rhE6ldFbMQ1;_V15UF?O&?bxf- zjHviUmBQATWB?yS8BmQLt%#lXzvC7$%CCiAj+Dmk`X;fEd^`rVn^tJ7Hdlbgg{l~4aEaw z1Vr8dcPIsf@{IZ;FiB(od9e0a!A03R%i8ud3G_&^A{YKVQ~&+aDde`E)^JzfCs(-e z4AZ=iO%j#kVogs8A1{xp-&XUygS?FQ$u`_2qElYG@W0!4IGyCBih!{pJprD_+0zel z_}kWb?OzKUC?&PFpVwy<=I2m>9_cQ=1NGPO*-m>++Ls#xZO*|JXChu}lyGuxZDJtM zm~x8%|AdkaC7C0H@g1pir84v}BGw5oV(5F+uy1A3kM4`+`(ffxrdhkZBerxY5Zge< zg5sXDvhx}pl}4&hg?|3_ly=#f{D4B0%9tG;c7R7Qdc{Pb03QbiAN}OwXFD4Nu5=Y& zO8qB@=;I8=6ob;NRZ&U2kEVQyIf0c|VHHR9PEW-0JZjXqgT2+C6ZIJGvM*o#ibZSt zxtqn}+#%V_N1~G)3JyN0hL#@pZubtv1MRt*pU&g*dghz#iLFhOrS)(Euuv%zE7ZOJMxcJ9eg%_d1hPb$UM0ipX1-y7LpE*|*_Bi^fQ)MUrjF zT?lBBp2yv1ifFq>X(3bj(H1j$_ZM&mrv2=XNOBfOWsPK?J`qOFKKgVUgxs+`se>6n zzcQFhJV)q!J`Qi**gn`;O|TfBdFny3@MHDiENb!X?1Si{2~;d}!t6M@!T_y?fdZ!8 zyj5@L+Umt!?Tvw3R~(WdP#E164^MM^zR-EFc^>56Bkfj5b;uvXqzEF)Dn12kPn5SS zX`-wvv|R>wI5Q_c|jiovogllVe@<$X5=gW}S{LKTJ4_dO_AHRJGpgzy9toVwm+S20vk=dOr zVO*D3qL|2!gYqx=ne+oOE_Kk@MEZmrc;9wGGt((wk}TMmc`T>HV$Qb9yxa72hC^73 z!lSxb!D`t>w`72JSOiNNc}6aR)F8{^cBaKGrKy~O4yDJW{i>7GEI4m_l^NDOC-Ru7 zEN`K~m1__gBSI_q@|XJbzbkmy&_Xq3EXE0ZOEopxZI@J)QZ>nVBQVHh%=2c9KWXhR zL=7c;o|^3o!$x_wYm@&c-Bf`Vg@${U5x$dW+F``lozD#WGkZ*SOF7?#Dl(g2y$568 zajDa&ojRzG?5(p4W{Rdga#zg-*_aasfCX6bM0J=lW(2b+KyXJvxeg!$V1JG4unlee2dQe6z zOv%uFLF>BNanRY{qA~hw^eWASe1$}aYuH~z0kUF5+foRV7tLHQkCr)KNy+Nyt}kC} zu<^pWob}|)I=R9$m#d7Fo1w9YP#66>&d|&fh2?$g!+zrZwLfyPylVFWL@Y41d7%8> zZw86xy~Q=0e3Qt1%{1!o5w~M6LdFM0ly(lW!A(I_S7e**C4rMqS z1KN#2a~dX+7EVu@x{ixB6zEqBy;juuikCb8jrzn7P=5Lh&|h9cuhArZ%O8fkJ`6;v zx=z}u?!f%NqrTmIHWJ8yplw2LQ|RiuB;ed>v}7yZ+AHD(ds%kBcuam1h%HmeXvmb@ zd52)b>hPM*r>0%}MDf@>{9|`2D1~mBa8?qIepeuWH?3DMxN*06DPlX8{dfv=qp=@-Boqy*rVso`k^uk0pl`0gI4i=mTA=R zP+P(lrna+37%Z-CI<=WkA3QfzNlq$~F;$v=FQw>D&(h3@F`XWDo>~N<&K%xd1O$^b zIp7dFy;6!})H1>t0aPzQ^r>=r7Qh|dP7dS22KJFpt}b&f3AuabD3>y6mxv&_CJ&?o z)q=7lEH)7SNaO?fo2PD}ntf$Y-nJIyQ#&Vx!4EP6JCLBV!g-_Af>BIvNNJIy6H+C0 z*vc@i!6}Vn)Ln#)4~K5P6@!+eu18%1RD3{k)@B|tlp@!9j@^Y{cfbN5xuy2o+^+@C zUe@2mSi59zwx?L!&qi1+8^B8KgAS_#&i_z_01!grpGo(cK8raLX!#_=w44&DX)?q+ zmjx;F9;2ujITGQHo~N+~w*5Wf90bv;l!i(A8#Kz8dTBn3wPa)4Mkd_RUBlmS>I{WQ zy-FZ^auBh5v<`+N6!@+Q@QjIDom~ZX-5hx7z-g^Z+eKK0y;*kGHVxiBH>G}&y`%{# z=+0oe%eb{&!1ydQSNo3stoPuRlqguhe?G&1Pd=vTHd+b#CXH#!m#v7Y7BnZ2E?-tr z!D<>U33~J4$@kUtI~bDMCj0D!Yl9X|HtLpa6@N~%Q^6CHdWU#aw%@^Y%fQG z@%%gvuEq?8Gf^?>`>{z=q%bSaDE95=@UZ!&==%7k0*DWILTc&jC!@M+cs1qk$!_No z@%OlPH0|YNpMbzSGX6wnN|HoZBRG*sQv+E@Mh8Ow7Rin_#dv(Z<2&YE02cQOPZWqf z%M)*de-!&P?bIE@%|t8ZmGWaw3g$UQ4c{Yv!|h-bXa|m^$fNAZ7er;V10pUVjFh>R zWRjA+d9j@iwE27uu>ve5Wh`PG8-)2qB+iK~bKKDF`UDCCA0HoDV=fZrF9+Q>bAN30 zO7PYUUZH;Qn76c%-n6ZM%>%r1pE|tvuC<^h%_KQkO`aK2NE#^NL;|uf%f}27cbl7= zKY`|x1cP84S#Skj5{<$dG5B=m&EA9x50ZZm%;{MFYd>ck@9ORu2%@@wS3^*b0>-^X{cbd!fyEO; zJ&&KcFB6ohgg5QkulMa3xKJV<)^khG%H#;(`xtrTT&uNu=!JJ27cFNE)2E;RedYE- zU?6)dtnwND_!Y&h#nXMPEjLV5&(A8Auvg8%DVANhzV9wvp{d`OFlJ^t`{l8lifZ}$ zLdBy*H=c@ZiGImxxwXM!bEoU+UaUL%==;sA+vVn(ty}#1kD$QQ;C<%u3L+ zVGRYtCyK|UTD`Y#!-?oq#Lu6P*XDi-{@~KZOM#r`4bAU9*L3*JexD^#=?UB!fnK^( zDt1+D&6>&(K&LlOwr}=#WZNlD3Y~n{{23w&)@>f7`gD3(^XVA&g*FVJ95;sUTBx3?>CJCE{4Q7TvtoTe4}Pyzt^9J^Cr(`NVs}@!RIjdiYGdnHx>DR zy(B-aeMU#q>#~Q;!$Q4685n81oWG=eES)=C#V+71R;&BrKeeL`^C9lbcWD1+n&*L< zk|Cm4o#n;`Ava{V7kJts7$Nx`tG;u`ROb#lOw5vCu!`_D5n#_6(~5dZ1gQvEHS#<7 z(;jy{LuQnfnhwhH4-pOU^jk2fph3n21AO$H$IcPTIFtabxp$OGrO!CyFtFSx$bzj2 zQrD!i5Y0+4mXu8RLpyeK>2<&X@^}Wd;`gG=Ai`yNJR-dzsLWPm79%!4m){*^GD$I< znx0l$!m~yOg0!%CVzjjBt5D7-VDsi(6f#Syqt_|G_Mj6?^{)`oF4m>6>+}K)G ze|3w|5qu-2e{MzPd1w&dgvok!kG+k)eI_X8D!XHQel8|5#M<5hj0&#jyfOIGAH$C|YT>vGz2cuhtq zLsZ>Avq8rv-5ulWIxvgtJwub}i~-NT>_&u%Fl=owB*|arK6s>a9w<@&oDy)VLQj}d zqrR{2b1mFTqt_#5lM6)>ig&ttxlDEnl5TEZX}?hRj^XlAej;ZRv<Yk#>{5igeN-dSZq`+_b;c+u$8TgKwLM3QM;5a}C39Mf6y<{^NL z)63QPLQ$@3UGc$=Jnv(dUV9Uj%PTfE2hXDJrzy1pX*@B6O1peawqJa$FAU*8fAJC~ z`EU2iTl9KAV(wl8 zQR#dRnDa)E4dvL7RH2%Q#B7qTY^d>^sL|`Pv5nvG09f7W1^H+5n z(@LQL`N=rkN5NbZwS|@bBkyS}9I2j}kI!q5 zd}m=4xb%}WelwPyp@b)2QF_%R=mmKoSnr_0b=~YWJx+hlkSB`^2ep=vZ5C%SN6U+) z+fVVMJUNgQ`@&(<~BkYbxY+3p6U;eO2 z*me(T%!NRMd+YlSmE34)QQYh*BXqCy7@aBw%R(MG-~j03*0cGk+ln+Z8D|PLV>k@2 zmI==!O=SOCC5_XH6$@2tf6a3sl?WxzjM%pf6pO54Bhv{=8cspIn0>W%}YA6^EI&pd3iE7vCU{m`KV4!#@n!?0G4K*IvY z!-v2~l-Azw4bR&B!hO{0Sn^oxdcaWNBJX#tX{P#Sib$2u`pG&s3aMv zYj2G$UmoaI+u_@>@HQ}D$$`MaYxY?I@37WYlMNLlGh-P^pROikFEZ>y1nykYbVUVC zHRW38_n%7MNk&m8*5DHwq^Q#ACAcM)X>dHYVDgUjJL<{}b(! zP5wKoh{xt^%!u0@G<3>6EMKcWsI*Tc+}RiS2esh~^`ksrC4#{_c3XzKiqEv9#sbxe8c?zlhbPSZdED{GlpO^Hg* z3`}&;k+IOot-$I8yD=dyi?0kGL+O`-6^3)h_mmGmSetBH$CsD2p{&KKWu=zOYwC=_ z(>V~_DVic`QQ4-eUJ>hrVVR?P%eU|AN(G7F&?0Qufu{w6wMLZ3B@<_sVunc5O#dRi zrzesixL1FI8+Q(XeNSMM;kgqFRV;n>cYg(bn2V8g$RYOQeW#icg8|Kh{3ykY88$kV zJYP-?z}=bOk5}Niq2B}U;^hAx-)5|~M2E{6aO>gi^sN)qIC*w60WjI&1w0o6oR}$m z=zu{Y-4~M|Q|E`PPJG!+9*&QS9c1&zJU4h5XIPf#cOie0nVNWTysbouoyFy%G-nyZ zy&dCjL=gjizG=m3y>k`btGK$|Uj!1|+wPCvJG#eG?v`1PMz`L{Fh4u%(Jb+{wl{op zZ~7bHfFup*IQaP(`wnkKTy&G`UXz-UmyN_G%{SAb)P9@DTOjdPb{`*GBbA8eV+4Va0w z$0v`5qp+fFp3IOVJ@mJhHK6w1B-V4h`Jwv{3EsyFjg} zD&2GBK0><>ll952*JMsXq-CP9(nctd<|NUv`qb^vv1}WY^z}cZdoX>EXd^nO#VY_1 zNUlYexX(*SNJ#W7@i|vhKeL4l2!52|kmpC591Kl5raEIk2IqJ=yxWvrP)=QC~BT2{kuQT1cO@n_Hnnjf;=y0Tq$ zc+n`0AMYafPk{K@_I83*B>A}i9Gy7dD==YKh*?LO>%d&zV;(0@n8HM9#cSR<4B$G5 zDZ)wt`1;Yv@#hcjx}f*2{NKb499E_XE{(F>Ivl>taR0K3SrxWKzr3!b3LBEs18g&psTP^Mkx9d>}6Qw87 zh(2&77*TR?d7rLi4&FqI^PxWPvrR|oLQ)DQvt&MA*;&eAY7xGteq;3}bCzj1k(wH3 zc_h&n@i1iM+14Ij|8Sk&t#IhM7GG0haZ04K`?+P>*Msg*2S^?8aYa! zsfwtrW9i%nqjpb|-#14|6)ZeVSeSS{$*hk%pBEi)JC!T;@-1eZqAkOuXTT;Nzt?PA zm1Sn>NtWqpjP*ro1s1XpF27&pnQ(wmfWw`@0FNtQld#TqCrldqvnXyjL7<&d-0$b` z4;IRDy7Ce6qxt{G%vFA6FgM6$snjS4IMps1aS(8x*CHOPJ=Qj-6fhhItX2Oi*MxBr zta9@;4rHnfIP~r3A#&KRk|vUlg?&`R2Exd$RjUk(ZWm&>i|m>@oCp~)$McbNj6a6R z-!)VTk4M9U^I9+t7idETzF&Uln@VzR5XdTVIT3*vW2tp7izbB@@sgve{TBGjOoi8M zdfv=mpdG4>+DbyX;`O7x2)Ae4ZRUAi@?Kkoj_v3t(D3@jt#N()@v-HkI3<+20sTYTEF zUPe4M_L@y>Byc19Oi-qqAvaO!buoY#^c`5#v^=u9ZR&}vRR_w)I3r$x5iUV)ft@PWGiS|ZB$Ug2>RFE2v|4l5G-2quQTSUf zKsE}O{|7yRKI+%k+aBbODg@hZAp_q|!_z{N%#lS>4>S=~hV!otSTM?XK&E)=H8~C# zbe=%g%wD^uE>n+rTWL->$^+a*S(dyfFK&fR@6K9TMCETzVxiXA)ak@1PG@Il>y(CN zxB_z0RZLfGM8^&Hrvc-Bacpah7yL}S(yFdPHUQSEsxNo1_>IJ-oBz~h+0%Es`&KkA zKmjebg>0fCHAM>3T-h!)p-G0Di6i6d5|EM9jrfsaQ`){60|ne#1fy*66Uok?jeUY2 zbtk&S@hK_IMwfCFPy_TBX|{vFZgQ_$Gk4ukOlFiXfznFc%Ucoy2HJR(-1vc|NOx(G z$4L_xB_VYLO6Q*P>kk+M8;^FQw!MK4pH40aUUT1t(T9k^`}Y1NAsG}?STP|N1mH!O z*01d_b}zMPl4fp$EY}*|W`9njZfJ}@ z$0KzV?A%$Yp8RFXR#IFNYQMC%Iin0@N)@YY3WxbPS1yAVL?PR;xwLFb8j7;QSITf- z6NhSN5Cx|u>v^r+ZjC8=ttZ=fJ-R8l!yUCw&i0rjg!u|aZ;~{4%KnpI^ zmW}O-2C5y?sw*@cb6PxgG`U$Oy8J~WE)uR;P(t`N8 z9&vm(w!Wgg7QgRyd|rn)#@gDn;Q>t&4el#lG`%rbE1b|9EJw{akxVAgZp&Aahj`b^tnDtVTFx`2d(oGp=6?@z36`9M}x_Fk@!`v z0lq5w%FLG4RxpQr*`;rhrdslw!7gs;KjRpS2z14DIX&nDFhC4pAbi-uQS*OdZxBDfB!=t@hSB!Z@jM> zew2cGeH7ms^@4v=_i!&zv0NZQln~Ce@3UW}CI-FVk_O99vv)btQY04T4-lBujlA2k z&OO~Q+ype*AW}h%eK?`HnGaf<2|F;FPPn+@QzwUT)Tlg2;=qmp+*?ai9SfjZ{4FO{ zQ^bQ&(*h1%=QF7`5g=hFLLqFcjS&kC(cO{kK5`#&o6XlmiB8dM1O0)u9}9SFeWNVY z@QZCX`oiV9^m5Y+vVRH=30X;jpI#eMYet^F`LAiZQvo#V-1A_}$za8}pq`{Qx+4{$ z;e62Z9dP8XbJHH?BLUZA$oYh91pcd0pRVC9sv4FljPDMhr8j9`g2QM>9rUn4>R|X) ze(^Dtj!|~*Gr+xaHL52USIH%~^$f3{zxm;}qpZaO|0l?cY?Q;7kG1$78S+%oTkzPb zNM=SxMzp=B%i_SA-|;dmB{zZK4g|b3ksj4X^a?_@;GpL?L$}8tqaO67#E;`Qc1|d3pwh zA5jRW)K;ICyQDaX#NUHL{n(&;x2$t(Su9bPA3f-rRJUD2Tb61_p; z1&uV0iG=sE7JA1ofb@e4M=)#Y_Vj<-0SH`cf)W5g z;0jj)`+L=ySdy~y$bcK-u<3gRXjg?XKayQnAlYOTxcJ!=S&A(BFIIY$TIKc2DW4V-4B`7hIn7N6)_c;ti6?PS1aN*H1~hbL9_i zwx#bTJK|MaYz%1R6P4|$kl}%UOg`5nGNA#S1(g;6hw1B=5KbWa& z+UtM=aba;4F;)^NPlzITYP(oA;2f5xMx3pd^zG@1F9ymH>1=E%={8c7%rI13MBaZq z?TH7xA7qsWX^bW0672!&6EF)cZ!Arhcf2api%+Tlc!akQuGFpWqpfr}oXU7|B@59-A zfE{69npH7zxh0j(rsPpxZ(Zh_TAq5Lc3E-**QNOO0y1&=QdQH$pnsVtg{>-2Q`(-X zNXkUSLU{t;5DLY&MqmmGuGKEVd?qs;ZV7>IeA!ZIQjV(Rx0+VGJUr%2ho5Jrq1s}@ z2{IIq9eAm~0H@XGNS5{2(cVd0KGVCq#X1o@w?p3t=B*O}I1?1xx~6?F>XT>A;z3AL zG$bbzt7cXdJT#3s5a*m>Bp7?9UW${^#ME=nfnH1FxOa{J4NUb+I|7GpMI2i|lS+{| zlyVk;eI99x7l_QD#W8}|5u0YKNvE^bz8;@TPX6TEpp>nUYd-+MZ5XzaYn0ogb{-uD!V8@N)q!jy&k`ePn1L-?AKZjy1didsQD9_vYyTly z*BcTa<&;(Tm8k9Bx>=6BAUkCqwfOD)%pv!>7i-(EKH!hpX~OuV*^8&0oHDMYHmzQN z{yAgM!&hq(BBJjpl$kn&JDRZjABVZw7MPxHtG=d;+7AOV^Mu!gzBv+ujm1wSjA zj7PC_Ch!$Y-D^P9F&6^|HCvw)1gE!SPfuYy1w;Qxkr40@oy5p)L>%Un!M{E>^&bmbXRTV_HZWLtAJnB^?+E)O#h%C7ers9BvnVm(b>&;XKge!+2$8ttTB z9A!01hgI_Q#ehwq*tKvdLW(&miLe*o5F;-SIDn2eA5uyLf-X*_kuVSiyn~i8?Uakfr`N`;{yoG?w?1 zj3*&PLb<7kywn5O-qP69(^K>x9U+)@x;urU~!7dO7#W_aAZyZQ4r99 z0`VxgfMsy?iHY0q`F-f6`+POqk*OzDLMb{LWIUaTxLjTYC9u_9GkGzUY%}_|q;2$~ z8(Qhdw>x>CH~^cLVIN)?2HC-UBJqH5EWLM|*NUPE{AX=O7H(>7*Fi6RczzqPK*aR= zLSVK3u|=5Z`w!k8=*D&bGU#CC!786WP*QTUGx{F=MeDeCG%%%FQ5lOB4=H7yX~@1K zn*`bwvQV*F7=g+3=7L&#O_)r&h<^>^ihIW z^K>n;UqA6HbqrLhTy}XqAw))685K1wUbcq;qIf($dj5ME@p3hxG%%lm9(Yw;e_kBBVITatmUW_&W4wQ^DojLAtIl%%x0Ns^Jh5kN(KBd_c}_`gJFP=~Q$Y1zMF-js8o7*>1QxAiy%@`P z?J-eV${UdZvPD)BU~LKfHz!Xv1*S*qM5`6gu=z{k4$)MS(6wQJG{Q6UQZ~~{x$*2a zJ&zcEFRlYz&3RmhVjVGkIJ`exCI!>wfyF%02&$d8OouT7iE8%N$~fTXGhoe{YTaAb zKymK6fsK(!M$tpQl3gK?hNq55sns|Ob+_!h;M}W5UB%=)XmJ2_kiiTpU)zJmiL#fC z2vJ%K5!{)(zId?A7H24!{V9d7Ij?JJS#U>W;2EaOT%6lV07dkT0Thy}t1E%vj%imp z!=d$)!29B-Sp!8g{$K7XGc1x5c+al0~JtqymQDro3>AB_{&S{th@^y@IH4vD|OF9{`%h=y@p2 z%-11052~``@&Ig7AX;r#z#7pU$2jkIu=L?xbUL*5aOU!^W67mNmZuEPuEJQ5lbHP( zA4eNexLrNKl9$oZb%*MP-=l_B(=PC8CD;OSzzwb)+1uMom`xCI-5%;^u`YrEIDl%S zY^gA#nSrW?6*Nm1Wqj&Hs)&WW6!hlg>uAk0Fku2oQdMtSgO8!v;Xk>G?G7f{3?_j( zEnYj?4OJz4*`h?}8s5(@KOv_#P@1*SK)Y9=f!cS(tY%DSp(~KP6~BbCOv{7VX#t4D za5YwwU(KsmppyQA>?Zxp6#N>95A4!tcnwO-l?hYAOVILR1l-w63BLrZvM7rpS{-$9 ztH{%fqeJHpW2Yr{y&`79{SOM1f~KrIO=S6K@p`fomFUI_4107ifX2*_d%C+`xIS?A z(6%Pkd$a<#f^p8@drB8-tc+2{vM!sW%$p?LsL3O? zlf%^UB%?x~<^Hov_h&2T;~+y+aOlcoWe<=>+`w~6IsUTE#B6H3p+y#p+N zTJ&6%&q=B*4!2e<#ay)>JjeixXuXYvVge^Z`V-3s_fNlVLb5fM5=#7mfecQ__qcu2 zVzM0!150uj`agmmr13g&Kd1n6xpibbmgLM%Fp#n0OM&KoX}e91>N|{6B_-iF^{&2U zfV2Z{X0L9^AG);$3)#|_mRD{npKDeA;SL-DEf_X4415^b*@QkvW`QZAHeqAuZ+(KW znbce{pa0{_PTR_T<*6%ZGJKn-23?I7wsMJIK$ z_ezA%#+j6ZiinS0Ti6NLmYf zwVid4_W(m!t5OCH01^9b(IZkjQc8Pxpmygv9d@ zN_)~s<>S|XHOGej1vFak^}Pr>xMcw(*^SK54isf9E|>)G89@4ODw{xI>=AN|Pp890 z%;UemFeTlVx+>{!dR*ZZ-xAhTgVcd=F6MS@+%MS`m@_|lo%PRKY7=fpe0;r<-P)k6 zKWd`XFu{7#oy`^{PbNXuh-#c|RdHyuDE9oxZ30K`vn96>z=p+Pi_#V?%`v)Xt0KDE zRok#!s?p|s=>r4+R|0mLVFaehVQN?~bB{?|e?OO=OzYm$MkZu=AMWqIHZqu9Twx}8guVQg&Or6Z5dt8dnzgnC~PfQ z82X9i>^s9+;W_=DNzSAR&AY@=lNAcu`Q@LT;685E_QwEkHoWse)TgkKVc`CSYQzS$ zGe)YgIK&?hLNublt!NdDCFy_MiN!wd_1>^KMyf=E8QJ>**SF99%#1%t@o(K6MG&FU z??y@geHersCOtgSyIdCWQf%26Glq`_FqP=_%hi@P124&M2IaqeOdjF+O4c&M2}`{0vj3ub+6Yewp=pNu2fiV zPnb)=0=9ZY_2|^r|GonjDASGr1(-)}mB<{Of=4{3*MCDY65}4_R)0@7`D{Nufn10B5$Co`r~vI{I)k(4lzxv*B6dAU0ln!KwOecch-6~>^Hj;z{1QQBxA zv&ZR3)?O5(WIhOT;c&3#4&$WE?1kf7*~ZQ<8eQR-P29%NL!6G)(|Mu^tcrA9y`Pp@t!~^ z$CpQmcScE4NDVI1O!?>_K*AkdL?QvWgFXV%^!nc3-gy;Vv#$q0(G|HnnM^*a0CMZh zTRE-$b5A^yzj4l7oCdIh18F3`bejk2EC%-Lo^P|(7WafTmumhnF1|VUzh%;PH=<ep(wqSViI11ZJOB{xjwO90`+NdEMk}TlJcWdF z7guK#MUHRgy{~ubxX(|!kd*aQPhuuybpcp+uL%PaUVj$S<9F6hXz^>*Um}4zCLHs? ziza-Tvx1mcC(L#i>!hf%(!j0?Kxx|{KJ6l#*mSrpt6D}Z2ZS_MwVgy#j)H^T=4Q1L zpkqGq;?&vl$h+b32pxsE_8|sK@(bpu%y9p=`9HZj0IFDp_Qxl@v9#t`E!gAN;??*Q7oX|n&(Aa3dr_&npJSWYBul6ZYOyuOU2m~>czRRe ztwfN25Hlz~pkEeP9B?6~vQub({fm@2u>3Czlk`;O-@qvH7G@ZCHnN#>3m^Dph>6;d zF3%Bxs8?U8S%F#sl1NXP>Ss50qkcMiHJa3zOR_1U7#KAVH*O##`|q`3cWqTYKsFbC)tRT*uRsN&KE>}|eWedlb4 z5SGt>Je76mi!(`*C!i*PCi986eNBi&tO4rUlm!uLS+Rr?r1L1CTyf3`P*uv-(~kAQ zTGX8rc6ll(|I+Ut-{R{<4sfF2ht;2$xiKVz;yQq(SLs`VgP3Ia0NkgwU1)@{rpj)L zw`G3WK!NyL{CH&68Gh<5=)=FJJhuhPh=F2a>Wt~xomoj)t>T*)7yGQVHJwi6ulah1 z6s3RYh^F)ziUtBk%@I6e`YiedhS_p=c;3DSNq@+;g`;jVj%l42}^=8Ty$OU*_oXW)JfE?xLDEk!{*0t});#OQ5o1TjiA zWVug|hP=3G<#Jes(tZi#-GgOnH?#tXI0d)L$StdNX;44~)3d)s5a+mtHy@dN_diJ0 zfk%v9RerDQz!8C~WgzkggXey!twXcCM!^0eLBPqR)w?q%2xZHbC+zRp_sV*6&yAiV zPSA?@S9aY&6Gc-YPL<+(-jq{s1Rm=uU~4&ifd~H}O+hmIR_e8!?>S;9FffcrlB_cw z&3}9M6NV#=0^T;R@fu3P&wMs5cm@qtL`G#I>A+$#(Soi&KR-t+1~VdOmx;&YE{$<@ zcmoLUmcqe&VKs<4IAL?Oqp^b3+J?o(vfA`_bFufzz<*+(*JFW`qnQ$F105 zccp)Wc0xCR2~F%*#&XuP^=2sNzq(Qj) zI&w=S?-z1gEN#yN<0l**@mwu}GqrZ=nkh~dQ-wq3SWe|eQbp4QyWJ$s)dc)Y2nl1q z|A&*(y@*-T%KoIpE1{#vID4QmI06Qb46u%)Ue;wWr#c@1tRj1lp0WX0rol6Vz=|MT zx0|Hx56Cst>xR2SffZj8oiLMRsMs(c2AzbwSKl7j=&jLWHqNoBZmR;P+SUP4OV(HE z+#o)#B3S*5@_Wr~?m2Zdz3w0vM=9~oz2e^zQ43osUd8W_u9hNR|6A6DK824JUEBKZ zBAYNl)%h!hHOeR_fvzc>)mXnAd>U5H1=2*NMJ1ej3?C-&-I%C}ggs7VWCIEzbH}_J zFZ`V+y`1~$y|ep|y&d7lZJ+Ps7~?W2)!JB=Q&{FK`feg9kxiXjz@Eq1#heIiCfl7K z3bn-kF#|MI=+%FRThsfxyl>kf;UC6@#KQmU7lrKF?A%i-{cTLpZU7OM7hx8x&8(9Z z!^sXEFAgWi6~l~Hd&WXH!6Hj;=Lq{9VF})vDjx;ssOz+qv7)5DH82?cFR3k7(l{J8 zlOvMD>p_jGsz~+<+}i`pxw^d{2c2e*UOY4cW{W12o%+{&C6;@n_7&yts~uDn5m1>wzrXVM3d?@rYmWN z&JShkL_BsoT4`>!Tt^f~46h7%^MAR+-Ct==M0C#hFC8m@#3kclNtM0XOx>6r_Qf)Y-^Kbo-}-GttZ_!>_^qH(_HDQEO6FO zJ~$2?cVnV{$!ND=cxObf^Khaw-JO7s{KvfF_p`Fw`6)NXFkjp@SO__@%Q@~hD0?PJ`e~{oWk1L z8flucx3|~S1;T01^Q`8c?74KdJvPq_YCUbwZ@AX-o|;~u@86@WpJ;QXjq5+SL9cJE z5x=y@==VbQ-kq{@s%VBnA8b;k7K!N|fAHU_8LO78$d>r9*4nyjm)p9tY~*a!^0{f2 zQI>}?0FpyCB94oRYn_vckx8*3Q_>QyWg=Tboh&(OZyL~(AMHJW^5>rC)lvuxs%ib% z1z{8dwFK{YJYMqtdh6G!UP13X2A zK36YYCB5u(>+&A`m-czDsW_BFoZ-UAU?s zlT<^$r$jP+y<%{3KV`}0{{BAm{T#RBFgPFG1sKSo5Tcj%%rYOTc`JId|6x7#Lm6~` z(B=3`UEaH#v-|CooeNX?z5Zh{=-$bI(?8ayNGdij*7+C~N?R_$R&LjF;*}mnSumT< zDT=c3EK-ofaolhtYOh(=i$9&Z!6Ue|RR3BgL8}32PcLbMATE-IXv9P_%;bIbgYtc! zJjo~~hS3|AbW~6ku=ib$OFy?k*fCT^)#Tq=URQABdok_~r_7Ir_S(dM%|%}|k|piw zM)2KTbay=mKQ_##Gm`n7s5OWn_ell{^!f|E`9K;q+9^B~`teXF0EeBY*VsLKi{#ya zTkqYW_d@rvcfcuHZUHQQ$A^QBx-kNY>;7b{k;8Dnq*L%8NLy>2j0-C*)V z5B!RGo-7GMN}(yul{N+SUgZB(82c*C?p3=ISFz@dF@!-#)wPg&Fssv-gW-@UP3iah zOYb2@tv$6saN=+z1(CEwcqtF+u^&1U@AZ0YzkI-zYX!Hyma=_%%-UnhrQ2$yt9BQ< zi}2)S(90xs+97$QVB~=x zF3sr4M7Q9|;_XC7;&A*Z!*_kwPWW8>ip8}}Skj)*`&YC#ls4?%{vCG5*Xa0tw$_g? zjZ__yl`66##mx>$_3|B}Fa%@R{E)}mvvpe+r~VzS^(J0S4v60IB8?lth1&xFN2MC8 z6p!S--f!oP9AM$)2-*^bA!~!R2C^Fths@`*hUw@yZbM5DA)BMNItaZ$du}<*N1-B* zgq8IBeNO#k#&~v{-LJvg@!On#_6(1@d*xx0eyyjbb5iYb^pf?vaZ3j;FwLbpK9p5X zl87?=VH4y~{%g5wC&ghD#(ekApYnyb|0$QYKg2I?{6~bQhRhDvPC%7A6bCNmSV*|; zQ09lr;4{(ivyf&fuIEw}6?ryk(iSP2Wa3(P3w7sAQYJZ&T9mwP%#y>eGSquv!t%TK z%57x;!1Fwkq^@h;ytaoiaOT(=9i{4|C5Tr!Fo}55s@Fs`EvxXp4B8lnowHl)y*Os? zU&LJh%9!;NL)HfCkKIcfV`_sb55uBf+M{*q+8(MbOR_TK%#U};4l43_#p%!V*u2mK zuO>s~dD<9=7O@fUB}G(KR$$?s{a5+Utv@EICj9vHmxpcF_kJhg z*oQKn`|AVn%B6)n`u#O}a5&agEm1Ia<3l=;`oKv8Mo+g$Z6WtTa{cxW!uCqIwlT}- znk+TCSDr0K`}^O%!f$--Dp2tg&mQA*FP^{;4mDHe$($eza2IQ_yF)2p{Qcsu8vZ`|O8&%^{?_*f0v^%uCWu}iR+?%%}TcNc4!uM`Y`I#4CKAVAbLbHl=e22B|-V%l2s3KQr1#e?UbMfROuT8#x=g_kETFUTR!p74f{ZpnfGTj&v zL(nVEq)3#9<%Q-*7MmDBd&`vM)%A9%T59;i=RV8X{_|iBwsgozF~&LERApRFex}0j zx@=zR(AjWsyhCrK=jh}RNH~>4D8-j}aPh#pb*`aBecf4})s$H!1S9#j7;hsGvp{g# z1}(;;mlNqloVK!<#3RT;%9fG)p3CX29v$Dq8aT7vV=x$y=NYrvd=XhgYyrtUA&L*R z>h4+mHA{wyrJd~Wd!}%6d!7B4=3M)OjLToXLvN$Q=A-aSAKvCg>7%4Ky7Cqykq0@O&1&^hKc*~ed^-pZhjGPdx@R5MFZBrm zpCT&=RRP`JYpuD_qM4^zWs}K->2%uYdWg4`L%Y0i-eOHflK42DLseGIq1K^W;736r zbh}<}AJB%bC&9-DQ;MM>^xV66BfjhK^B+FTh3!6hQE>5CPZf54t<~*1izbpelvdf8O6L}_*PCaI{Ie? zO*m?m+@qo_+Cw#(#KCQU%^_1a_oZj&{r$4$z6d%?E0-=fShZwkg51nu8-HL~TF&ULD*}pz! zYR9a7%(A|5{I2^phyy+>R-bp$3N<_4EHw{rwe(15Ghh3-fpe!$oC5%D> zKVUc`@Aem*4EY@Dzd(>qOkosdEpr8&t2on@8-Ps+ZLRwT>Q|PhhpU2*PzdZeB?hq zPBJQpHXXcPz5h@Y`?U^*)@0W7&kwdhttAQE#X}Jxc!}3y*e#2}{4B;Du2 zE2lBeH7@_=ocDe^1$&i?FQ3M9J{Y4m4)jj?^iJ0ASCj?mEUP!mhTPTJYwz#-pba{? zZF%>Pr#Oz`{AYaP;}N6bXi0lQ9;|f5q&Sm5*Ch44$d~eVdGLCNw+^u)R49fcP+X1w zrUac7Y(Z7khsEnao@W%(6skibn+|7$-Ec{WTvDGl>Z6-BK^%aw*s()!(1$8p+615r zQJr2%QK~oV>c0!akgcsPMxzl22M5hS!Gn0~4^(KzGalz(JPGDH@BQ|itG}CK?Nu(m zbm{|7KL9+}qoiU!&ln6kOX!LijC9#_PWnN;uK($T@BPCO#xXdR$Me6o+3ZTut!W`g z=@72fOEHkm%i3$kZgUuQ!$?pM&3}-;(_Ov8Nt2M%Kha@6%BZFe{Sz^lerApSnoCt3 zZp&b6T7HSX$TQS?q810Rj+|CF#5(b<7r8;93;YqKvkX&7-Tk`ud z1}6K}MPOZU_a|b|wUPN;_|Pe^*SP%KGp_tjf^n{K@ud&WQ!nv7x&dL=zY7BuPp2CN z?T7yXba@tVT`f|WS1FF`G`!);R!dD9i4=Masgd{cYm&bhloXXRjiL97=#8>ks7AV& zau7B?SY+Nj$TL~<|Wd+I%ttDMtgkpgp#$AyZ;z*Xe_pIcZ6#=-TAdxYpmyV>t$XH{{&w>0#AjIJ97`W(&95 zCtJ)P;fQq&gx+|$;?s689S?|jxmZgniPb~gqchTnbN%}Ge!$X;1^Rs_%LD9gE!gBu3C1sw9BlqL~b$Rr5pCH)eg;$=B`!SAY6A%giD*oZAusda&7yqbqbaGRA zxG;@_1H4v`)KcZh{lqE%M1A9@ZCU;iHKwRKl5o#Dizn`i>ki1IGZ+|{p+)FJv)dfC zMaibtLo;=KvbK^slQ}$H3@Vo_vgf-rH(kuKk5fF<+xA>c^JsyT&Rps~LOHp_H;)cB z(i=kNy+{+WoE#E_3*+-##TsoZ!R4E4gux~cf868ITRpHgxqRas$%ON{fLhP=6JPqY z8ILG99mg3)`y~UzI_lSp<(bB@YH$l+_2>sVc41gL+aL58cmoE9BQx{}J^B686f71{ zCrzTKhIR$CWgq?ygUrQ%@|!NfKiXtp@L0W4A(zYHxlfCT^oG|qHWtGQ^Ocy=ffs@8(r*lNabaRM505x)frh< z-Sr}Tw$OmHB$ISXz1glY@cX1Lge<+9BzvfvZKa+nISHtBdS4PC;!?>bm8`3_=25v} zJ)EiCZj;SsM-#t9v*mM<)3r^TOE0ex29K%!6sqq8w6}I?zTRc^O663v@}_}HTOvIU z`FWlUS|~l5mVcJd)byF>dH4*QEk69K2EDpJWKH&L@_%NMNG1q_aO8iA->r}Dd7q^p zdepXBbnc|cuUnKa<_Y|Op4&UZQs|_NSZZ-&#AlbyD*1vq%2l6&5)AvkPpj1$NrTC{ zes22Eww2)Wt#jm;YixbcrTMcgk9It2uifX$Yv))fEj(8%EzOwnuuq-wP?w%C&>szz zd}{HcV}@q|k_2X&fzaLM_4^GvPlkPxfge)ea0%NssY*!b9j%iV0Y_~$=jpa?Hk$0; z>0^00N;gAFrG-&)OV?uSM2ciNwOYRfxMH=n7NI^7^nWEF7Kz_ltu_)vpJ8awX=4sV=L?d`fC2LLNs0%dD zcMG89{$+AOI-SO}ObiPMLqgvm^h3;~fte7+eCycoA>o>(h)PbcX)R8!J7D{>Duahf za+f{MU0oUR|GEQ4``*Gd>6E^-WeJ5CrTE14hXVMw2{NWmvuQj;$ z(<<$E9PU;d?0>t-`b#V1vbj_JJ~`?&2dp)ipO=LezF5-Knt7QQ&^lYFrNk`D0yAXg z)eNl%KJ^DZ66pl%Z)ULz0sX#@ok|?3A(7O%p6jUVL$n57)Ga$WIAH&_ixuRk+_c87 z)i~c<&uQ1Gdreo?>-CYxIT_Z19=!IcDrBjj1_=|atY@@B-nkl&*obO ztzS5Nu)WRs*W0XLTRydbQ7ofYP0~q;)3(l|`sP%E-S;}&-`HdATSXRcI7e!U=LNL* znX)OR*ARwcn9KPzPQn=i%}kCa$I8T52`aVa)2E5JWpbj4W$pEQ)av`xJ|1A0DVA#zyEy-Et)Xq#j2R2kI{z&;aRFmP;>YNIO+_?i{f9Tbu3wZP0k- z5$mrPSz1|qX5V@gp(`K>AWoC<&|1qFA#N*V>nD94{=7xM4vROOBaOZD)ck5m0{Nb3 zjY!~z1XhS?8b=ZoTJkF{6&=US=tN7e-=qGxMgOry_G&=sf`jk*KrmLxY25P}XT5du zNN+B!J1D)8TFzmFqc76sh)Z8DpI@YWuE_n$Hcx);Q~xlaySq>G4|<$?u|h8UY${E0 zoU|lc<|$E}W}!zG6|iiB%!*Cne3JB%fggC7hBdN)^8#A#U96T&qLRq~`jTKw>N6w& zoCH8gdF#npLo45=w&7uP9ZFv_$>)oBo`0;UXjaC=95bL^XB71mTsbX-LD7QqV(p)6 z>iguJb%M*UtWjLAvGu-7{cVS>9gpg@hb+IEW$n^3j*~tWw?nMbY5LMfg1r#zw87Os zDRA-40;#fzJMb_J{|NZ!WjZ8)((?zq-R_Z^1}W0lO$5nga@3tNZR6{{LyVB>;{!Uo z9)%YI)?Qp04%AE>XEP)nFFtP+xKR=JNoys6uZYIWcWKQ+QLGxNV(~k8S*FEeWs&T+ zvux(~sD9|v{W!zD%?6EEdaS>?$iiX?>jXigRv^-y(Wl`{NBaX|C<&Y_SY*qI(Sqto ze_lRXz@sbn#OLh0JrcZVgB^%M{-5$VGT{ z&1M`=lbgqCzjdNyS|UlPMcKUiyCg7{x{lu&A9}2BolbM*TWc&`X|wxTjqP_V8vm4G zVg?@?OM zu&|uRane)EQ{|!S07<8jpB2z?$86jYFPS^f^Nuvv&T<08-J=oOZ2yzTqhB`p_Ww$g zyJ?QBq_&>&UTvwhKzsE2yufGB@#!@@^4A-bFD%a$gzLrt-P9n;uG94DqH)f+*Nuv~ z_!3>qYl~$6lSB1>lid&6xc74GKlIrt?vY>UkX{d2xR9ez&XCDw#+Io{#!Mggy7Ty? zppIipCJmO?NsK775ck=W5<#YAP`Hq!Tu+kBo5$Rl=;>zhRQfgvXSP*1*oBvs}8F1p?|XH)-rQX>K`m-*;#{8PL0HQ%!eBT&z-D zOXDoq1AcBxdPR4U?LbZOmc(P@|*-1ceJdh{QsX>MfM&hKMq8{`(6B+4Pqf<=BQL#bRK zopvw{>xh3n??R26{;B~T2P9oi8V%S4kWs5Wj_wPBaH!W8N%QM*7SmV-*;KCUlF6j$ zb$c9ab?H^QT)0}nvh0x-_c+1yc{hD@lSehZwP?JSb&ESizXE_(5wV?Mp|rq436|Fe zxSq@2rwv-WeR5Wk&W1^FCrdS3BM5tB3OW-<@mUidQqST0KHYW?_lZTiY_PDNJ5pH(9817Vb2;X5 z<)Rrx`P~xh=t8qmr#WBID`6)|*hwzl$ij``X!Yu~I*t7{OJ;_H4+92UHV1dRbbbY! zOM7H5@38VxiG}3?Nh8TTG4r(Hk>lJ10d8EtrYrNb_VuKMjF!|5LLaOU)8g3t@=5QP z?(&e3W}`*oAWOosu=#;j$_|j3L zWyN%$IZkd?z}DM?ou4&WxR~YKE2)`J8nN=devkcoUHaG*uiB(y$^#@*IgTlr#sZz> zl4f8DrnOu0djja=S2mj=o6V3fqzLsO@e0gHk zU$nw54%Cwd(QCFtKq-uame3M6LKb!0=8;w}94uw`rK9@+pdcn5TBF!S>xM z2fsqU(toqppkM=Ne7QPkVaIVVH#Ko zlUZC>3AilFV&L`J{^)?Po+AG}pVieBJkO7%6-UqVkoJtSG~*bKXSw2(qkboglRkHj zM{$J;;8xHNV(_)z)mX4(Z{A9 zgc{(n7DJ)ASlh0Y@*>)FlP1Vcvd-OJhwb+p zcnyQams6CMies&#_^#u!mr|oFk_FE#4mxzfey>@MxMMsHP=;Y(Tf;;}AzvVWD^L4! zi_JSweaoWuFD?i7tJJQyxNu{ce6BDzbvJId_OuP6|E{O#YOT0wG})+TBbmexJsxfB z(tbBhy5v*2>5!P97^__nsThp@22JbDt4A`AK^hHPI)n4mhcZt0POE$-5(#p-JXgN% zkk0S2eY;10Bg><$7OkyETzIX*(z&C@^tj>jn$>u!razsl9XD81wBp1UpXIYgYDGrK z!#i6%daH+NCa8Sdrd%n{w7G=!&^~hTMWgc~*tgM^*n z!b|5UEN3{l*<$pq66wyNMG^9&1f$>82lN&9#X7sWKmDFg|W&;vTesM9&S;LF7WY z#PuJX=h}Z1>rE-z_^#+?CxE%Z>#cs``eszc3>OQ5lEct~D z`FtVP2cE@33w1ZnH;$HS>cGtlTpr%t;qgDagr3Rz4^q7F%6Ss@>5dB#(6-y{*uF)f z^|aRANw1MA=^2cVyB*TC5|=C)4y3m@c-+CVOp=S^`W9^}i)FHJWO$g{;mPeD;im<5 zHahHFa0F0lM!lii0k+I5f4$7!1XX0q{Ni^7ctD_<+HczyvVl^#iWO;ab0N`uAm+R^{- z1uhToJZAG}J?LAkeLum48%xg(%$j?bG0c)#)W1z@fCvLJ52$so;u)aF9F>!-WP8`8 z^~fhQJX+Nr*;NyR3E;z|SSn&Che2iUTA%7CZL06PH2*C{Yoo>XwF6df7OAY3Fievm z46v92XcI8PSV}Ki3^Z{2Jh;8h<}ccW9<0Ba=F-h`7=}5L`+Xi04dfoRs*}*4+Qkr1 zOIA@T3un1>1MnH3#{hZ~CtSJiaOsaSq|yoU=MwY>145r8EkSWs#P>Xs$rOdv0_Eie zmcMqu_D2o&KZNGLW@+ASuyd_J`K2_4a&|cDdIIC%wgYf|oSYTQQ4jAuWPiWL{dae1 z{wjr$u{i(TBrm)?9I+>vLMb+ySIvK-b@oHL4Uc}$Be@KQ^^{5KbvtzSw{c3#$G%U- zO$b{u?S90S34#D448sPHKZEhnOKK0|YK~pk#dCceCxu}eM??h0+GrJe`8=r#(+r9q zy40UEd3=8H+u{2@$&`KA=KnP5B1JMn zS4C6WQbu_scr+4JmdlhD3+%siz>|#zox2Iz%^vlCPExabSnE~t=NyV_Y0Aq5(pd-3 z4e)y4^#goAzz72Zf0$aX?$)Vp)j7EDk+`>n;TNd9(Pr@_SUR^7n*o#~J5EO7L^PTg z^7z+ns&{)Bz}7o07Op2q6^32osZP)dZ{GSRtLwkhCYy0+i}FaY0VXI)p|* zB5z=&3_=ewr6ifWgK5v#^&OS=jiV=JeGJ1mb2%nmdW?fyGT>&G4rg&Sgt6%LdW2y} zCXCoDAF+M5LO*QE!TI7>CtZYcH?bCHTB>f!eK^Akd z4{Kf4Z!A(-FJPHAp6ipa6Ej!zozw-9zQlllK^1o2>*4nU&cBf-w{kL`Sx!B9?m8G0 z@yf%sXr2Lj%7fJ15F#=tZBVmp2+?tt4i1^wt;Y?=flL536k-nv2x!&Y)OTB8gfzB# z^gc`ttN4o^x$7ahQU-6}V7KM`)0BAo^cX>;&X;~H~7KKuQLTOlU zJ-9TW`ErvWfDoTTv4E2rg1=U;;dwrW8US<>_9CvBXq-x^=+cdwf%44spBnWnTy|XR z+Zmu|0Cf-qgoI<|a>pIJal(Q^t7%_bk2DjDE#M!Q;7KNvR2D0T-xtv9^$#~vi03|4 zancj7p5+;cOo4FLy4+S=6PXqGysl^?LtF#H8K7riJNo_JAus~$8R{K$jdL8BHPfMI zlL)wVA6~S!c+66dTpCdhm4!Y@=51V%tabOKjzmwc`aCXesU`5%oAnIPGc07_LhW$} zr(}~VTT@*PaZ$zzH;!8<-OVk)?)UpgN;2a{6~W|k9BHo3$qk{LY%^ptDR45)uH zpuOp18a)oSyCj!Fg2C}BH=+3)$2pQU9C4&mdJE%D2LXy6KCeZ=HDeMq_c*xwOIn*7 z42mlxZ+(~4%B53de8g9d^PweiblSmS+@{iXD$&-jGeA$dQU!~}R~&i`kL6n#isv0H z!^W_J(E}FCB~gB~OG9f?#7)1_VAshPUGP7eA#&I?BS3Opmqao}(5g~>>o2MO>)#T3 zeY$oE|Fd6n{)c}~a`ECbTV-KNq6~&?sJMXfdAS?W4taeKXFT+@2N(vl>wSWjL3$xU zG8eyC;_GVRKn-}!euzF?wAnTKTGxHg69>o=DC0yM1x=(*gdqN#MDcP?KT!&t=2_fMw=-N!>uJ#0>-9#nO%ll@p6g=tn{=y>!O4+dx`1_f+>7-U zzgU1PjR(40B|0PUw76s8=uZ+b%KIl77|x25#{15~Cy%q3&mw1a61T&)ZG6wiwrqUg zquuTRkj-XCz_e`}+gXB48Q=HtRi~o>NqpOGw>z?$lI_#8N}}C2v(&ImyMLk9Brcif z^F~ElQ{Hn1=rPtH+WMo9K5fxX>SNA(+}7^6?EI!h{(Oq!bpxlEz)3krG%)m&^O*H)(c7eBda!XHhnt6fo+kwX?Wf(?sPppsh0qAGglqT#ZQz zoAUsA9$mN26OWC*tF!lhmqf13t^Zc0{GH5^(?Tz{Sl*~^hrCwCwu!}*t{O?%>(spl zxVGGS)Y>dVJ);4mR#lot3+mBr)Ao!F)B*1d%1@b%aYvgh>a(VJC#f^V0{UP;@4zDr z!EJ}Ms$E)b6U#~v_`$K$LVzaaqw;;CrKjh&q*AF-|D>MrB0Z8i#jJ;5j&o1sWSjPU p^l(wBZyt9din}qxGjIL>0RSjXZR33nm{I@$002ovPDHLkV1g09D0lz> literal 0 HcmV?d00001 diff --git a/Patent2Net/media/graph-recipes/app/assets/doc/fuzzyclusters_language.png b/Patent2Net/media/graph-recipes/app/assets/doc/fuzzyclusters_language.png new file mode 100644 index 0000000000000000000000000000000000000000..8515d0eb96f529c6fcbc1d2fab2ea60882b905cc GIT binary patch literal 85755 zcmV+GKoq};P)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRd$fk{L`RCwC#{durld3N6ie(rv6Zg1c4ume>}EGbc2gupN~YG4 zWm&RiThe%m@n2)dgeU9>J7!`=w#Tx^ zn+M*l*E9`H(@5fE^tkR*02u+tXpPo`x$X;INY`|dWCS3iHCm%JS_f&F_rpaRhCz}f zBX9OTjX*|gv~F#sWNF6I>IThrfMEI`)OZ!pdVfZ11R#)C@1$vpVT>xV z?zc4p{n6UXilUGYuP*cMjShruK3MZEKZa$ZHIGpHlu zJG!ZN>TDnMB)Y6H3<0ohd-T-qqZP+7Ns{0=&gf>0*0w8&BQ9K9=B4w?ytmXsGc9JU zh=mD{h3Rn|ONT)Ltp@EN=JL`yOO2R~NTZBTXpb{r)p_>V1Sby7U|JSvqiW85T$}d| zfFwym7>0PBH+pO%02!?ZD&mN^bbW=F&fnmJ?-K_2 ze!zOY$(5B&ZnP3Et~80FnE7#!*~uDD9GzrlY65KpBp)pR$+C5U zSmTM_XE17R{b&FPKoA6Inl_@b?xPikAz7A<0A#cVg2y*sd5`a(U+3|~F`hqjs2d&V z`<&;@G6LV{^71M#f3U>6%Ra8D^Z1c*o;W_o%+&aZ+WIH}NRlK(QPgcJ93^J&8vub( z?rOADgP!uvrR%)({&g-b*ZJ7VSzdVjB(`(slig7maPitQuU=T;{Toee%jDdlF&;lY z!_3qKx;`q>d0+t~%QAf5AL%OHX8@vU8kS{^ZpLT<8Sj30iQj(dDwYPHJw3sbXHH;R zTMkB=WwiVl%hYkLn+%?(9dUW^68c~g-l{FhC#;9KXrnI`PrLZ z}rH`G!wQr4jvTTP_ z#}0G!&Ssb1$Q7M;65ly_9V^d{3+aO9( zPRv%Z%-g54Ez9BT$s^27RCwk6tGs%7lYjZ63!I!?;|q@+W_oIJ^b7|%i1!*pV={wU;gA-+->@~RyP{FePM}-u`-7y${2=@=Xu0&OdLhj zTWvnL(I!gaq4^pM(_`rSxWBS2Wp!BpWURaZ*2^TJ3=UZ=F8+*aMLJl3Oqg zgD8qf({xmgbw7l;qddq*dcAdVnXBtH0|GeY8gFz(=7;%=sI2YOcwdBh&1plAFX4j$`K~`&pWi*%80<`hUl7 zzxIzubb-!1oQsL82o#EF$agtd#N45 z=&buTyJ;8(aU75GAP3!mjO5%u(raa-&b74$C#O6r<;u|4)!QNOUEf4Y0?rg^Ul(XeB<5UB1vNwYY#JDJ4UC|p;Rj2I5tTf^~(A)qA0|&?0t`Vb;IPukp*VP zEByGK%e;7gg@69t79Tq`%f}u*f^L2^?a+M-AX1GrqOnE*GFk^U`bc=?{4(uWnEx=HpFvn)9{Mp;f{OM1xaDA=G)2A0WGNiI>1Rw_# zKy+On0myv-9-|z{M{{-j4)3pYSR8jaGCw`^bxl9w&C6?a!kA8&@WG7+=jNQQgGfTn znc`Q^{e28w$22S~+a!u2k~rc!KV9MvUteOg74rD;Y5vCN&QP(nJSTD|mZlq=IC_}b z$#GtM>qEYCp~OCmsZ{FbHlmO$g(!@P<2cWCn1;bi7dN=L(xx3Iy!62` z*VfyZmQ9i*cic9VD-}NT%p?58j~&4#;kUp4E?BZ7WWgBneR*Gg&J!UUq;K-LPo4Th#0IE?|(6 z#u2Vp%E6=4>5!!fKl|t*GEHZ-;q%Di81proG)>TT1Ix0Aq6l5r@3@0GGc(OEJzr(v zt@C{E?dx2t2Ym9Od7eDI2-<_&19jh9UBfU&0CIoyCq!~ZG+F-L2v(^lG<4PUJ^)O76EX!`{1G8RKM44(@4Ur#UVD$g_eTJ7&^GI+8f&yh>tHP_3o*5XK|!b( z@?x2-3LqJvYZ}L=%eaA zqm!gTIF2KJ{)t1()od!|GUpD}2>gJ^h|zU@;CtA%O{dez$2}N^fu?CWXvJ~djgan^ zxTmIZ_|O8sI$q=3ubt;dAFPnXG0#4Hl&Q(F`(BjsfdCLyTydoOdhjB|(fVkurHvNt z%;xCq1e!8qJV_GbI3AkN7B)d51x?ebxHg|TyMXO_IRI>KZsIu3Ks9d5vhw_g*OQFb zbsfiX2*Z#xO$o#Bu8+lbOJzRy)I*ePogcin%9|_i^9zs7apuHfcG3qs(9ZjVvT0@G zjn=`6Kt}7Mw=4}Rgt(5~w-<^@^I>~N@)q4D!iZEcu$rdjz|iS*ZrWp-reRrD9_bXL z6U(wl(-i+6n zKqEy>fXG~!?aJ*X@(}7ts4QU>1cY4IrCcs=^@9{ZL}cBik+6?)G0h$TWn5fZ=ki*U z^e#F&x@mIy_+fta<0lw%O}_f#hrIjYl@Wj(ga|}7;b#g!yUU%!TotoQLpp* za?JG9IODZSZosz_HjLvq&yAS95?wjVqBbD_Py`{@b+IgqX0w?W(ufU+qKH$=^~GEAO2F~iS2aTv?c38RoJD|LSBd++hehbwn65}D*HA3x1x$>#T7y3nJu z?jI0&pa4YWO-JkAM<1gITg7f$l@v59+f?`CGE`TUt_n$0HPed`L*ebBM~z)9GO-1De}^j;g15qJ2C>0yA2?t86l%6WVG&_V<36PT(_zR z5OEx1nFc4uO>V4i(rC7soSe*mPp!1t)+p&3x|X7ATNKl+EYI^u(fDV7_Aaht@s+0* zDSK|7U68#g^p-FeB7Kr1NnSms>l*J}+vInDbe_Xg6@K}-leqT&t6mtU%_kpTWNGa! zzW(MC)oPWQ$?=10Zy&@>J}T!OMIfWKKOi9^WPRVyJ$j*>y5+E1AFVVoG0DPYl}3;f zr&;ddOBK~l;Ngb}-+ym~Z@#(0l@0&4=bGELO{VE|I)2`Ws8VWb$*-vQs>yrb_lcs2 zC=7Y)(kkD2;~IbV)^*lecdnCtYHE^CoLS_0J?547ufYK>3VI-2^lmsBk7%sX8m(>C zYZq5}^};HjIXlmhsWMTVPLluLet!q+9aqID}D% zrgif&j~<)mGiNtBGE-r?;@;6`bLQAQ=Ps}E`jt9QoLFae`e4oyd0-=u(TtFT5rK>V z{NS$dy>*S>{PsJ%d3mibnlMch+qUsMFRyeG>PdPr)Fqwf0uZKY;Ac83YYn2_P^aC1 zN1UX*b9Iw;n4oDIA1*goskeYF%51MIO%hzoU~+scujndPWXboDhQ~BbNwbU;4a>6g zXyy1!m4Ek(XZe+9k78SQR;_PhUe~!K?gd2D-<84}(cRKC_{OW3_@Dmd4c@xCf#W#DaZC_~ zSe60W-H}W>GC$4f8IRYmY;t3DV?<%y?I>h4BjnyjAfx+!u$F)00?Xg{r#NRm%h+R| z` zs7jtlLcB;zsjrdi({&xs^Jur*gi(xTB@njJ3=6|_h{Av*i6M!2?$itw&*AZ-lf+>_ zlBteSH?p}K#`Ey}6o)64c<+YK^Q|`3Ubp>0Sz4B58^G9ucz}W+K-08swRlGB&Mc|r zA2jsmL0d~3ZK5P)ajJ44MgtX9XeB?P>l$%$gVeBb%hg+ce;LYD)UT4Mf3|IN;qq1f z`42Ag=~Lr;>ZvnqH#A8i0?EGwz1|JGw|68-U(C}KBV4ttSguh8If+i%9iPN+QUBKe zjQ{R;(Va3=U-;W_%JnZ(iBp`|mCD#PJzkIJ3Z= z4YV_U`06`+=iOy~;n@?MJ-&F5w*IF6ARlazNf@nrR1KnvS8(g|yN9*1J$o-fTDK^X%i!wAIO%uwlg=MB>X+ju; z`G6wvcvYT$zm`-6sntm$|FP5On7uOhK^0ZIi7Yiu%lkRRn2Q97tV*TA(?`eo+UwVN z_u>*ypSwBYiQ^dG_isM_-6Dvnw6sK8Dy>y~cJedz=Qhx>E!N`z-LT109pZpA zjr(#Nre)>xNaWv>B;nlR7}qyiJb82+OUnp@0IfHJ--b3`v7_?>Y{SEi)f< z1E$Uu7_GZ&d@a-9+IpMc`rdn3rp{k{{uEPH??7FnDzhQcs;cNL05B|B>$vdue*STi zG-IOT^u3q*KC0G}X&PMHX!Earbb+&r6MX*h!+Qb^p{L|}_EI$^k%`Et??tUarKrR) zlW1hn`M1rJ{Q~}lSFkLX@h888;f>*UI#^aWy0R?`tygiC_LP8a+vek^W_a}Q zIF=42&n4+S7op58%Ve`1ab>;5;zT9i7q_}fp3D4Xg|}8Bo?2OFVRm{1Aa`pShLQ8} zqpG0&UvZLR=z1RyoEzpe;lrg3zW(|Z98>3$r)L;RFF_*$anhOTFJgC@*U(6%O73KxVqZp8$Z3mW-H)RXJ&B*Q&yobe(6;RRArIJW8b!rfK5)TOH?;=h*I= z1UOXil01rB&rTXz_Sh^FU;a;MUVaO=HqPY9C(#UxR;xRhDoqmB6ZrPKYiMc0=gv$q zGc`$?WrSJA%;Y$0YimStoJToXmXRh2z8~`2Klp$@e(egMeq@2a{e^Sb=B+!hx?wRl zQRR(mH;BS$L}A?v8f#RIwg2n&i>v(a-+iBtKRnBqpE*vNBqTip9RvY74vUi>Uwm?r zifeOpriNi!pl3JfD5+FTF^4b=REnSz^$e}iJIuvsLiU1c;ESMjC!=BYGtM5F=I{L6 zqbyFA(15`AF?x9gbp)$WD3Wv7uj|}Pm13HvL{Ze&sU7zW=T5)-@ZnirJio%rAFlJz zktUT&nNFvZ&+1SILdj?C_WDI`L>eDO5`I{DalhjeV^$^^JNIeAAS6mNTuaLp_9tgCS#@!>fQzdQ zjvSgp(+@`a`hf?K5sh_6$RDya<=SeU50*AroN(|vZP2zT71wn^(^wcU^Y?!KiNfLE zJH<5U|JB??6h&+_S~#|i=U6vI6e@TO0;9X#IbZW^zWC&kJ_Ft9baJj;y1(yauYqM* zgkgy1dD}h%HEAx?*Py(^z$m0r=Gl|eeB;%Ne0cQ+r;p6%V`$~ssksxCI^2zOD7_s5 z7^Z2GCNY5@lBUDuQvyH0(7`lyI`tOqEFw!2lBDa%#A(KnsS1DXQztR9m@M*HSzadV zQFtN@>H9vK28LngR9qPN{QTpGcJV z!(HR@N}aRE7jwXfOj?`R^ z_bR`l9me|ZX4$q)&4O01h+#xw-DLoga9!7RMr&^?NfK5!>R5(`Wf+*f63I%%U~X!> z&)7)l9)$tbN@ZU+dk`nYaf)l{Ib8wddQHQk&+WYH?V_9QqM%{vwzNVOe5#w3R zLkNd2O1SFl_T2#VfMJ-%l|(9Xeu|BQyICdA42={R0mwb0u|@#0`wc5xcakLN8dS;^EX&-M60t0crIj^E6U==!cz^uLCEmHZ z&R>4vBx9bLbKkf6Om~|k9|k&u=(HjLNvW+$&8T1?JsfJcwEWk$?Y?oZv68Ue@94Z( zktI=(ZQD7J+zNPffgpM7$+N*wqkp--As`XcBwO>ugEm)|Xy%fwMc7zX_DYghQ% ztJetQl+Qjg$KUwbb7-io0~yyhI{f25dXpeZ_l&`><|9+@wllJwffL}Bd#H|RRez^Q zrR}DGKuSd=sa`DK-HBRj1rb4%GG4aPmG2=@hyaM%Uol85aW7!oZntq9hf{~=Idy4+ zpI&Kj?&u1$Qxi97WZh~6l4V`be5!0=TLw{_py?V56J^TfGJ5YmrD>YaTCY~CXj<1M zJaJ^4#}})tt#8t7b?`j5ug6AagvgY`APCTP4c`xV`NK8pevF~PYnL|IXtb$0Ta}-2 z2rC;+mNwh?QOZU;e4y;bM+QJfGeUNbHq@#g@wVjOckA`0Ndo&^)g*b2&z)P~3y&Y} z&f7jf&rs+X$+M}Yz{Bp_ZYrM!QD~-V=DiP6L8a19YE$7>^sUkKWB%zk-)5yA@avyE z$x|n0`l{0;pCojz{I}R3xR*WEYPIsH6yTW?)4adbm@A9%0X4YRJz$^ zo_m(29GY;su-YaCj?Ppmdk&Cn(T=*#xnr~Zy+3Eu3S!P3o*V(l{ThLcM%~_Qq@?6g zINu@{zSoXr3Ec&ZZpYB8k`-de4oW4RYP`hg$@T3Axb0*_)#@{Oy?pjf;FD!+w0vH_ zu*PaL;A1DJc z$$ix8bsXC!>;b4@7?jK9d{#&|0?{dX9>4U=G3Lff7^cai3pMmCCQecu$H{fzEZ}3O zW*)0HQXh$pIW@m<0rOd%xtp&0ZzT?G!DfX^QXrT@JdZ<#aEj4l&qj zK4XhZH}3ki3H2m;Z;~e&CNy|t+TyQ#_FeG0b9)@N#vJHs$?mu z>WpPsByr5rdW$!&Y;tCy%4Eex*NuE^t>n|j$H!S;TSL<_9Lqq{bv&<(<2W>%%^YMc z%ffbSs&T}Z9-F6DtC6HBVHDqT)HVW;`ydKQl7x&54ULS9jHLVjS;pG+I<1WW!@5ml zkU^Scl*e5r=4*X5mG(Wp6A`Os6#FL+%kg3 z9q-S$m3^%y+_xk(wkR~i(D?jghl#?FFbr;rASB8VPyANCpU_sW>kcg6j-!afbJHBU z*5LIkbsjz5WMOWukERpwl0FeN(o(zdi}ap6C&MrZm6Cmlf(>2cgQZP=_a_(mjZYk5 zraF@kyHY{eb6u`s@ux3e#g8)%PgVHj8IRV=3SqDFUbMS99Uo2CyAcfnGtELWm1z!z_C_YskiyUBQuoCB^<}iBdboQgX6e;QCRo-4U#0rG#~sZO*gMxFNC24N5pq&_7oq_u$5jHx^f6NgF|&cto<3lMh_*01=qmLs$z$;*+9 zz+$5jaQWR8tjxvkl(1$KYG-vU!(r+~8MkI*U|{IxEgxo~1H^0IjY@0rK<68Fiv@QsmbRbUC1L9b*!#@FWLKH7~QBwE7jF`dbMttwD0hBefIUBR*pjE~U8| zQ;TERjs<8qj*V&TpVtsQ5)y_{-vdw6jQVPm^(#7Q1Zg{@zSLp!&vcvyTs*u?*{)EU zF_=8(QXMZ-u55LB?-T*3m1eh^bQXiUm*_)HCaaN%3LsgO5O4YzH5c99x~?Dy@|h5O zFBRxrp7| z%XYh+Py5?VG;5d^&!0WS^5(mI_l?WUO^s9XyuA0qvaCJPXsV+$3|ur#>&onBpcNWA z^FFaSCW#`n-ihtjA7q$@fv#!2X3DMMRzkO$rkP8=L{UV^vH0o5RlfR@3pkd><3}fN zJ9-U+kj)4Z%_hqZ&Wxi63P75zCado@*;s1RdKaQ7CbZjB%`vPQgUO$P$;Ao0F`II^ zjH%z*5YsYkEc51&x>~8Sc&yu5nv&9LbZFH(G*>%pTsBFTQkLHCu>4AdJJDkLX`AVX zDtMlYZ8_UU8#|Sc?j`!z%X<_Jjyk_uR_BdnZv5jPG5dEuM(L@Aye>b>vhMS^gT)QS z`58i&sGRzPx&%lp%OXi(<;P#8{=e)86bJoE68Tu*AR`&aE@8Pw3}`+g3LvM<$&G5OwxZF78KnrBb0 z@!fZBkY*WG*W}};XPF$Y^(1n%JnE3-y?l;bw`tovdtwULHhJRcBvBZGrgL$v4H=xA zuVL)*eBM~!q|>PL`N!$gF{i+61si?ggXrT~PuTE8aja_gbo57eY5hW3wR<~NGR4VN| zRiq|h)%h6$j2}fsf?ll@Y0!Z*1>GQx0usM}VxX#fH4H=qJb-Nz#sb>K{gkFD$LA+_ zW@UrdF0L^~uPyfoXQD$C5PV@MM{j^W%9L_0_dH|BtV}j%%6xC%^JE zhbGEJSvZ{0c%s4e3u|n?ldyR)VEv-c^@r+ApD8hYc#Kl1g2w(f z?d{dT7DfMZ05PrnXF(94AFeX{_dbE|`}oavK5leBK||;g`J*P0KdLe|ed+>+Mdh)d zp>yG7;>Ie@+$orSm>^EDjjf71Lz!AQ3_K)q+$lN`%ZETo#2`70VhOvHK_^K<)wOux^fY5*HFU!w zPE(>N&hMr4CY8(O9ynRVVMr7wSf)V+SgxCYXHC->AJaIqIDuv8l%2hq-86}~w${Y3 zOl&u(0e9&P1jRbAOW%4nT{(;{te(7N_M zwpSsk%wdc>a)-I6$}F52r(CYwcJ#56g6%M`zb}8G>BOxKZv4)FMg7fhfnhQ6 z`G1@7PyR&=!^FAG>ZU>Sz;C6}>>vWeZj^ur0f=g3#S?cd6SFrhQgQ)ln&P=G`qUy> zbq=z$E0kHO;QK!9b{pHa^MOxs+)rak1&{_kb8&{${ub%sP|ug-XDrLY_x-*ci443_-$U1QY|F$nE8T|2 zB;rqBzQk8wyhsqIynJDu!!tEL`SAQr*JK&Dwl|xt4l9w(A-i;721(sl6jrm-PAdFsk89-I8*Zzx10!QTvx0GbN)!c__z;i=pTKG%vv-$eh$>NAKS|>RF6U60*SUl9GR;}#{po)bTYTuI# z%d#x1JA0*frqrfdxjumF4Oh{8h*%Bts8wAmQ6d(h~f;_G>Frb zRRLc8v zq(3B%V>*5Z+p^GgBiDTjqlhq!XukaW)PMXtm~NGc&;M=49(tCn5CN)r3W+STETdAX z@@RZn9-MO927y^t6~jtOw?|4aZp^> zB_kv1B&0@0l7v7H;B*5c_SyK(ZxUR3t(zF0Ifi@q9GY&R(O+pNQDM1U?o&P3?KP&E z#uKLwv%FU42N&ubn!V1cql-JzW6}gz+$U;h{X17T_`RQ;=gh(wpF6jJ=XQ0l)aWcp z57L~^gPJF7y^z780JnG#>A-k1$Z(NIr+X-XG z9CY*c$C=7TRYmb`0}dIhj&bgDC9WM^;nH_E_~3VaHclj*_|iCI zNQvx6nk2+Y%GC3}M)d4ga2yxcbGQ9{F$g)Wv4=$du%z;K(SrKS)vBLCqigp{7ab%T zO%+(Y>E~puyb^N$kLt`m;j#ELE=d{@MKKu~S?HsAW8JwfhE3+w&~zQgvC-HPKO9sZ zyO;f(N8Pr~xnpy@yLOrHzIlo1u?k~jV*|far_;$DzhdsI*jV`E4{q?suU+Lv-RFfz z7AY4T8F?>}cvsJY>R6>|%Hau*zx$=f@;wj)A*NxlI8|kFp96$2@OkUXIwebEZnAbD z_t=2}kUx6u65o6G8ox9cZo4D#-FMo9B|#E<^l>ol)KJp1p> zaOk-*X_}#H`W}o)MjZFcQ17=WpQ&3MIkmvpY>5wlu)@msBLbE<_lp|UN_FVr-A)E# zyF)LM4r=pPyWOVK=`c1nhHYDUVzR&^RAI zJxueTDaLw0P#kRNv_65r7mu z@+_tlMND0?Si9^qe-<8oewOLE$$gJH1{s*01}3F(M(lT0e3K+0iX+lE>+@I#8Z1L2 zY@}?Q4=69{*fry>Xe`yLV?6qW5+6)m<>DW8c=PwJbM_Z9YPH(H=tG@6xZ`0@Q{p5c z=|vsFGbc%sgNMwHZnwLgw}!40hG7oaY6PgxuuwVmLCUR+^fY>Y(d+mO=SopK|x9y>h7Ba6@A*cR&6 zke(0$BDFG1lINCXf!5W;($Fw1BL^B8k$Wdr6!^S+ehJ$)dGf^EfodM?bHe}g|NKAy zPl0L zO=Cq>8bm0aC<(doR+E?iKWmH~@t8VMzH0_f*9^uNs$>s!lcC9g zdb5M6X`l_JX@ok6(+tfpyHf#mquWFkMYP-PKI$NeW0u!8@q-XuOG)CeJ4UsTKrWV{ z3aALJCx43nrYhvBe@5Uj+_=fUl&T^_HyB&=So~O(v7-)g5_c(?UeAc8X~a=P&}ow< z5te16}Ay1~+Bhf*nJVWNb7ALSA5NAM`h@JqxY$zU;jK@gCo8JG}8 zAz7N``2?YiByucD+MA|HrPA#?+IVk+rOh^muJhrII-MZGb9P6Gsx+m58^GBUhp4xG zzWMeVM=mY#_`}BmZCj15L8a)!oI~k6SDPV)iRdQvGu+<$Y`*k|-1zE$jc&QPA^4I=L%<{w?yACmw!vG{nx&x=QRAX2Twru{QbcUvBnB#EtGgZPMBnUzr z=k8T}Exp?2;x`+NpD8i>$%N(aCR}}gnImU)qM&OWQODuH$+o^d#WM zAO0gYfBaR*QjFR(Q(yj%anF91PP37Z@yxQUCk-CsI4*BqTIIk0+FMjSi@*D&$2dMy z9a;K22p;lG)qQE2-RPlc^rVW(Fbpi)%5z(CHbkLVl@Tef$BxhP)QMHr>OP-1JwqIJ z2uOD{vXXz3s6nD80l!C%AL8}v9lrPWRpuwF%uG+`4T*zRv9VAnsX?z7#f3f*#vX7a zNrKfY2uRS$oHAy08r}9tO$Wo!Ft|hA;91Hm?_A)*YK!L|nq_8k{6O!ydjcSS==1j1 zudw`+i1|-hocZ)&ETg+=qRnOeD{qoT0iA2_5Y<=jD1gX88RV%X%D|byn?E7V63{YC z%S6`(9~dpuuq}rm^s#Ld?GAesX_kVPa{2pp-uwMcW-og@`u8i;H?FeueHX`FW9H}t zn&#yEujC=JETi3N(h1s(l_$}A`be2>(RlZJG=BOG$TBp;B3{2nW^2>N<4REJBVS^+PS3sJ9gVtkBWczm9J{=E?!_ zJ1Hb`b!nOJe6Yzwvn4)t?&v|1Ejbtf;s-u&f8#34FGehU+UDU;E#}~n0owRHwa0&s z*84xEbmr5KRatl_``=Qm7!x=ZTv-!D`0&uQf0%oriyU0=qouLNzSg zByOj?_s6SbZIijDON22nQ91KG0M;EeMD2Eq@4S8iU4y4jEnwQtf!}*~ z6+nW}=dEvSMIH}-W)Zsw9ziQ2$ztrWS&sar|BUv^73}djQr)7}sNc~Mr@F4An;Kbn zvT;raNJ3W*nD6`f>xD;NI^X1--(AP_bQV8R!9F$Qp=%jSKZ^M2|5_&rQ&!(8^W48b zkLl^R1scVsJ4t?KS;qJ|ohQ$Xk8iO=VF|>?No;k!plVNxeme7rI z&($2qut+6}qP{(}ldxqm&o}tJHR3cwSAH&MHVi{n*6UPDF6DBmuh^j&brj!QH%)%_ z@nh&o$V(U3n4enW)bS$&0YqgG1~CfP*4zB|Uwe&KC*d6RQ}HbJDwG#==AZL0JsoF4+x7sqmm`uegH)q&Jt7V=OmA<-LY>zw2T@f_ zm2PnH94pn5VjMIMKRQM8>UGxN3aOuLF|#n0SG%c=XL7&A>x`lZvo_7_Fa5`Ke)<&t z>J^;h&ocJ(mj=Ruc$sk=qZ`HuJnj%})#-F{$6>qv3jrFnOI)p98}>UzfyTW`|H#~o zsfjVNEFE}u)iD5rmg9OndwPL4mqWhs<`NUNGLw^&eb=exeu~jZmSt#Utks(=ZM10x zF{^c-Y_8fjN4-=k@iP-;bhA65)G!Q6DMWFM*>lY97A%FJH4IY}QaOT+k<80j( z0P&*^Z++t`D=$SXe5MB;X1}NI)oj8b+%k-0q)7s%kq;e`ka)kF@H%TTul>(!+<3K( zZtEQTe3^%Sr3zM-k9Hk2YBi2y%8Mq?{e#(V`Kyr)?84Q0<1nY6vbp}cL0HdN{8S0u zOJN&EwJ0K}Qf@^l`axPiY1;j{TAt{YJjPC0Ed9Pgb17tYLCfD?42)XJs7hj+mWf_I zPHFbvqSb8TcpiFBu~Z!2GSXR=QLa?@;<;JA_Ua}6^^e};D<3<}|e)*i@BY_}ED* zmGXVF7wYsMw_4nItxc9`#GRC@Kj?7kOXHMg9UvH31}MCV0}!=oSB*kc%5xY!)}@mT&Ye1n zuEAGdy2$VT=zTu_c)*eQnQodw$$iLqP^H?#FvK)8K6Pdu%`p2se0jb4N22aqk@(rm zYBuV8^Q{}$w!@d6I?dLOMj3?LboURh@ChdT40aX9noLj%DhzZlc(>q97Vt`ZK% zaZF0W>RWAI{BKw3tR@`#c$ugFooTGHMw$$kxzKwFuq@r$>|qiUr2(1&q;!+RdPb|= z!iuu4WJ$qjiwBqkUE1@c%QP;=XpfCj}Zo8F0j{?;|{2|I!ujM`?|%W zC_)3=9xw=q%KcCey(CFTYkz=4_JueL!y>yRO$ih^^+DykMaOE`&-!Hgd+)JbW#YER zrWdWMps`Z~QWWewd-4cbmhpS9FY`M;c%P4-SmTL@k6~NgT#NJ|iPNW+q?byi9(df$ zBv_W!2c~kr?_BhpvA({+pT2g1>y3~vJUY+#`2AO4az_DV`RW>1Uu@t!q;c~3BRA1j zgFG0CLM+P~=#_}U%rNL|viHq4Dn6{RPLnA!$*y(6632%!4wT! z26V2zOY8ERSVx|~nOLAwaWQrnVzd*m3^MM+0A#0#Mha3S!L5GAF#79esU3~8Cyz2# zDe>aFm-)&0719izIDHt~aq~VBwTDU5G(686EGXGKAFk`>wn6}9L7KkUg`KFuTZWD- z;ob9>`NkX9xzT|yo}J>khmRcShQYfIAVJ*W!k=zJ!{PW>%9Op`P0N!gL@1kKUQHY) zRF7*czEGlhJ!0V#9^Rxy7)0n=l9v+7#%o-Sc;%noAPFPNkZ*xE{Ts{?b=G{yJ*T~N~O}3W)DIt)e5a&h{*m>DY8L;CHJBj#b#N? z!t4~EbxoW%F7U1M4X)SE^NG_lOixedj*OfuHGTSzV8z!2@{8^ z%>2D^n#~q^ujxlXM-uL)Y2uV@nyVdF-|>msDW~ccDy3?_7m{@tKkiT|m+?CRWaLzV z=XD$8n$0G09MfntFiiv3^;ms1;=;G<=q4O~q001=UD`+*qdJ{VF3}+Qi9w~7vf*WN zoJ2cfG}O>qJ=}7y!Z@I@84~yrSq5P{qTTLb*(PQ$xsL`>M@LUh%H;~#^b*Y=piyt) zIbNQ8l*Y0o%`i=apwlLdW1Jpnj8#f~w4$mmyt%oV&sG?%+mAR@`caiAQS%{&VPaS| z-qFVyd*Ta}7SHU#8_sqefd~L>mq_1fsFtDhf()ao)%zhJS{xeHRYxfE{9~uk?5mu= zw!)vh(%|_=VjezuG|zE}4H&l61iXCSof?hYsMqDw{Y1&3o#&!TI4`xwiz2%`|wGV=U_93m-Otdz_7Lv}oeD2)2N;cB%?5Cn8O z9Xe|rj7g1?zg!{^n0bFkmV#+m=opxWiSPS)1S2z@%jI(3SQvyp>(?8+ z_RkwME_63_^IF8mkIrFCYjiqcPIt+8P}g#&9EY$au* zB!$*0Yv1`z{Q5f8r+<;^nNMJu#!V5UI?H32F&M4kOQJTppTowq3QsTjFDZD4ndF?RP}!6?b0~n!nI}o?2SuY*^D_kSL4q;eeAvm zk2?Y&DKXbxX%MC%Cq7f{^Yr%;g`^RD@byhL&qqu@Tw?wcE{Pru)b!EN@}zUrQ-+ls zL8a2|IE|A8@8{dyiVGtl3{oO3%DH>lL_#TbIvs#KsjSK(2#w_%DRH}w;pk{UrygcxRLoU@oYWKK0zXIrrR%#mTlk~+f<1YU; zh-xiXPHsn2%Xd+=sMKggic7?yk=&p-Wum0p{e6@9xfy=Zw)yJIm-*@|*SNI2!BZy} zn4g{A79`~wwv)fV4Ze!2OUwM^z3aTW)WWfCe(C919y+>!eE_Em9tZ$gyH;oOrzv9( z>C7CNyyf@Vcsu5e-`pSx;M$MdP#Wjx3pEU^fty-FTs4$dy$@U0(X|pmwl$YRG<(#F zCkfFF!^mew%Yl{1AW0J9BqC0scHCm+<$z3s@#7A)1(zuB3EEpT3%Um*Ba8yF6tWQX zs)lZwdE#2UEh(9m9FQ0YwS!oO`4ns4yIz_`MuuhCI9B&SisEh<1|0wSGABMaL1oe8 z!ud9_5n)+1Y}@KmUtvfT$LOX;5GA0SkR@n_MHqyj#~20a^gN2|MO1QsJDtw9-rr7< z$}k#bCtw*gJ7l|m-z$LKE~v@gQ>m(922Kp6M4xJPktpTfs?po7d{!OnTKt{ua+AB6 z3$H3*7iCi<+Lwq+s8F>SM4UL+b#rIMG)?AbXZZC`*u4J!Retp01{c;Y@YK;w9yvbO zn{22JyjJP5t@<=t8d<3INlU96Pt;&7%jzY7gT7t_P1E!IM3!avzMp&Z ztyT-$wkefLeO^hs-Nv?UTCEno@8=2fa=DB}S4&r^Vnmn0W5bV^?b=anv_SP=F)|0?Oqw zzVGK!FVg5X%-|INZ8xvk>Gy}d=XOnQyZyY~0M&NYORA%wQZcF_Rm;C+??^ec6lBQW zP{+vL39uVRFUfTjfp51IrtBMauDP65kyXj7EtNc=kS@%-Z+TF~s=Eti1 z;$w5n&rTnBVZ?h5Ab!|k{jCUXy2JRw?F|U79ygeL)TD7SX5ysB;io3?Y>k*CKU}hr zP(%F9EA~jC1&p9Hswkg%dpTg z9mg>#m&-VgL%Cc=H+1}4vg8TivAs7HXNRdSHYG5_-k5Ep$^u(;*19xtKwPVvvk9ABib*p;%OLZ6 z<+wdTH{q4V;L3&;4m?XU)|czJ6)P_(mO~}gIjVM5yWQTBAu-LoH>Fmq5hqbDw{93Z zdha_*xoA$i1wOiNbYD}Tt<>g6*LC|qTpd1CY%)BkYd3(l7tm9iJxit1wwhDo4U3~w zOs1>q(A$ZM?j~YWg)RjMR4|Zh9@L+qO6y1|dJ&KYje3^fRdak>RbWyi>D?;HM^7K+p~JJhbLl!ixv z##@velgaThz<`1GFr(A0?9#xbj#Z7$weXQ|UIdPxnNLt`GFJ5uK8+ysYaCiX2K z^^pLOjFjf(7}L_2JzGKVX*^x|ev@~9Z-bBjg9U1b?H$1*48zmaE8591SKG|g7t*cSvrUKOPt2#JKc_2ye4 zzirzzo6Q^y(j-OKH4Z&j;?jCZ*o^V!b;`#y+N}<0yyayT`&XnwryCK)G&Va#nUT|7 za@}$mMJr4UfiyshWQs%yahhP676cJ#l66PaqV+Wfs*1dFFpHDv1Z+Id%RNI!=~9;n zMQZEsM0w;vi(-lq$FLlSDx)v7pU{;>@Q~-SQ*+y108VHmakSL;kaITdJIa1ie@}oz z1wYj}lk+IXU-EboO$jhqu8HS$6{L$xjW~+^Mgqje>$Y8&#~wP)sl_&%%_eVMtFyk@ zp&hn(<-I1Q^akUe!T4AW*T{Qca>!xf<7E=lC&ff(xB(HdwY=*#ib4lr14g1p&W=bOL08AZ$^l1+kJDJqbQ6Wg{ib(`6b$G8j7UeTC1<}rT6qvVzHC_)+x^J|s^)jM>SWid8Z z%K=S5%CViU*JwbdB^ZX4HxFu>mgjd=L*ZHureTulDVpA$k1YVK9zp>Vp%zrHT0laK zS`Y-JJ@G`l29mXHm z@k(1>($vE)QxCiNfls^H9$05BQXaCY!Z7UH5b|%uflrdm6{9XmarOQ4L?sDvOQU%) zBlc6;%Nd8xR4~~Z|0xGqfJCaGB+{@f6U(-UqXbt#M}j`}Ll1{n}B`f8F_yx49Ds!o>CS7jnzxGJP404!d0agfpd z9C2)?|20VXvRFk|)Dsh@=uUy{pwipj^zjT*=9RN3XJOFyR6$C0_HufS;l&PWS9-B( zN-fFV-qB4+vkcv`882DP%{ruM%F+2IWNa%VWav6xxx{ER!5sjQI7~>gl#wYY9KLssz#KW z6VNi9iDNFOe?27(LS~+@nVX&=iTkyvgs&GPSt^xiG#W%vNMoagX;^4h*UN6VyL}}a z8yh*5lqM-@lHrz|oQg=2gmS5zM=3!NkVGjMNnWib8(-y)a|!ldWlEAHBysnTrfHPR zWinE3TwLeUABL>F-tC~Dc*JMniyD)QH5|*`O8WPVHh^LFw5wv1D2y=luJPZEhLv2S zlpH5%N}QxLfBJP=AN+*cFa1M|QthS)QJ#f5vs)c)Duzjb?jQroAVJGPMt(Q1Q^(O3 z0p)J185cXmccQ=4?97>96v1o|;7GJvth@qp`J**KypD zcH6xK5Y5nt>=3OdnE1}M4Zil$MZWUP5spq*$k4DXgVuF}m;b*v*!-Z^0QD`MNB(M! z!!MNc$|uKhx*g=bsKjxcJi@3{D!E6aR9-kPox#R<{o64CW{3H>%+0YK!t2+$Vg>DA<{R2HfE zmV*K&Dn+>+Ri#!`ZTC90;z|stB&YAx1kUYpCfmuX7Xd_`l{h-$xa|b~>SxG#P!s!u zu1oH>oQ+}+)J`4eLJ_N~yK0_hFXh{#bq4_CrhG<}u+a+W^i*%-Bt^I3#ydWZ%SpF; zTZeEn?!-wY0=JW>*v-BXs4#<2cgj3(7xKoV-Kza94Iq<*6&hFddCjMT!amoPBN z*z)MqnGdRXqguZ&uN9Cs43p}!f1a_YejcMTNf3ru1Cp~sM;2$B$lukuDtqz&eXr*seeMony zx)CkQ!Y~cuAm#dtE%Y>G;*>*q#v+N+JaUoGR_CXyrHkq)Sn>QN!7GPBC^EGi)^bb? z2Q*VB3sdZ}fn}QnNziBP#oNr%E+r=At!l#^kXJ*g32Idd*KwRY8d38+($^vK)0S4rsL>VGtOI2#4BQ{5#A44O=u*{wjHweRME2m*w zXsN-aKd5u@n{Bcfrp~&Y{i{{1$t>5V5>OBzD2Ar8ImIh%wOaXRltDC=N+mZ?VszWB zHdD_S9BJ5eRwL#oW>hCjeG!o4 zFT_AiOibjVct*;ppBtxnF=pd~5Hgs2#9{u^HenoK>Q-)`RH|Wpy+LCsqIycBI_+U9 za?)zFQS`t?BTSX555ur)WaEf5vB{JPib7AQ9<@4dbT^)MF**?sUzCg0=w!brpS?sJ zDsb#Z#$NV-I1vI+_oB>s(C7fwyH{mb)XA8`qK)0?VHFLwx|fF0SE^&DCel@f;(@tY zrN2gv;v!g-IAN5?@a4OSED!+2Ej4x=a{%~D*? zp%WT7N(Z$Vjx5U{(t z=!u1aiBX`Mh8amQ_|kBwMs~v6s~z*|fH3KnS9@iA-`|nD9u%FZ+_f5=s59YjmFg}dfyHj*Oa@U#LS6R{kD`zEEhfr$ znmZ$VLIs%OXGC#A7^k@I2te)`fS87fHkQ#@4v0Dt>@YjZoz_|WOt ziE(4~8flv0S|zHr3btcmc?SMkf(GagxMjN!Jj7_pp&YcKiXF1HWwU;%MSCs7I-(J~ zF+nrv+q_*P1!o)9tYVvwY$LFhUGzpWDBy&vEr)ulGAiJ?&QCOc6|DsT+SUF3(dE-QcL}1!=vI9%^`5G8bkxY9SY$E?q$FvsUXxJOnx+xO zDgXQTK4591#b5r+8Ro}JBSg3t0OD8<j?O5Mq~XPJOw``L8vJ{gmm)9o)kyX_laCJI`${Cgn9vLo;CgwS+hRWu0&n zYR6(u|HTsCtWFwdeX6_?NqDYDR_h<=B=keO-Nv?TG+pa!bn4PLX<@`}SHV^!K*BJ* z$zu|_Ez2^R&1P=Eixh)pSwvxsVe}fTv@92*llNBVc9hFyGz~O8Ln9js94c)ghHsET z5o29UjH-q}092F))NW$oq~&1WY6)+#3tH8WQURwZ-JwPkgMdTLzwFfOvE5R&+U{nu ze7mJ4{ly@w=W(a|eXBW_LD7uJ4v7<@f`&Tysi=oF45$Y+6{`7?`X-mxT5Pm} z5rEvwB)VnADQgq8A~X%ynF)@+V^YIfL4n3UQD!b$ATT$Y?fNId!D+ z_eB5^k6t~nx~}ozpKZ`MpJLb=Yj1|Eys2|&+QBre95iIpiqfy@eKwm-N+l0X&q%VE zN_B!XN&3`O9oOzkq#GJpmJ)?=el0@Td7jrNnkb%=nv9lcr)ZGWJd0YjB$6s>gPLiY zgi%Ns1rTeH7&j$Ki_+oSam~B!8xY4p1QzAFTb9+GFxk6q)xe0M-ziBtY^jZp#mX*K zPJCF>TYc?z3H059hkP%!1o~bqRpC}0SD=nV*ezg76s$Uc+m!+j%8v+msn1I8nF{o3 zmEd-JLVjMfD-scl4JbJ#f9d%XG=r3r^J614xR(IZeemqqq$!&%H%j(!qa^Q@=M%D& zw$Z{5d|G~!vR9^5D&17^G-$M@c+g^GWejYVC1_eVm8Joul1sHx=}MjV4w|}w#mI?# ziKc6;Uv9JZ(+Fn@CO)B|^$b!Nb!n>Amt$_cx=CqPXYP3$XUstBeL2^4bIMI^C@WTs z6}>IhsEapSoYgQ$s@gP7(kvwiLNYA_JtIjIk~ktu2M;!qC})sCP-(&48XgrKW#)sL z7f>tD)CfW?DOO91cVp;OI!mPw#o(zCmMU(z+r;>`5w}vnp!R&+ZO|x|7^{*qYTjb6 zdRn`g0kYc&q^RmE4u|YX`3}Q0!KC)t5wTFlO&;3Ds|tt=S>xpaa~HRn;^7Zi`kFc z1Zxnir%XRmV)pSex~6yY9lZl0eHSV)*|tr`@8Eh4m;a>0hkx9_n>Hy=c#NIyHq0ei zOt`G^?r%3}T#YeoFl!Y~e4&Px8hr`-X0u7TT<(j?q#vb79jPUt0=8-=yIiC6rpUci z!OC?!3>#7{!VdyG+rzMpfrm~&e3(NZ)nt3|sMUd4LOrQe)*y#MO_&eLg=_~Z#omQ3 zjn^;2mrrBt8K7IGs*3kdr33GFw{wwxD*}fa_1(%SVsQqGV7-@F>#7{Qyr23U)&0Gl zGb7J;SXEZ>cO{oKS_gr`@+@=*Hm|pdk`T+VhtgLf`H^Wczy0d}$c42x__sgvU$8KC zd|;AoPy$ZnX$26vJrXgMN~v#Sb~+t4H#c+7Pds|twwZn`WAc=TiG@*u@|aB=#W^=G zUTCM&$pr!P^4zqWo5;+BtapauG$M+6vetS^nwZ2<3K^tHhL&~@a29KQo~e`r+qRA4 zI_R1{kUEko9x<5G6eWj3s-7foBfP!}-d)NlB#l5%O-w^4PU4}ZyTgp0N=HhQDJO>b(HCf`FQ;Hi~mx7u?eO3&it+$}N0Vzi+)u5L#w z-AY5pnI{w9oVZHDbCb5xqDIDs$<1Kz&4#2>w}!iniJFPxeninIQ?af>p$sGTF@CkYZCeqx@P2uBo|8Th1gjPnVt=-B2k+w2ORXP{8F6iwN=PG@5s|i&#e&To0mJh^YvvahfI$CO!+3s1=T~BWMQ#PQI*J6lh&f_YCAS|Xk#QM zq+JD6`OfNWl%0eX<^6V&zt}CMC7s5iK76a*p;}R86(%UE(OI#Cw&)!fuR-pusvcWx zu9N4~>2wB0Ja;nMxRqpoQG(=FD4jt$$L+3nP`qT#!lK?{b`-G4`FU$8jYL1!=jgSXzV1WwN>q-_6rO%N~-s#@~7R-? zPV;~M^5fV<*oH=&q&TK_Q<pB*1~ zP*kZGmEKY(%t@pn2TuS{at#~H4U!EV>$pK2N7$y38{IgL^BE%B9Y~e4zFh#3-xq`1 zZnr6y%e(g6i#d)#3F6#o=+U3DZv>cgfj`rt{q}bVuDr?A^M4VuI+@cegXC2Na1FyC z?$K6GPnPFyL>qE#x0CF@9WlXTB7M6EWIMyH_LRu;l>Vrq)V(Y@yE{d!YDL$eNrt0! zj{yXrw%}29t293F@t^VWoYGC+o7zC8Xf1FFCv>g%QDKPGObRN%?lCBFUA|0p^img^FpQyNQvx(=qRLbSM5^Zdk+t|zd$}_x`_mOj` zD(n^u9aNASL_w*MkQz0rJu}6~MJUhhq)gP;%Ij{Yd3ChzAb^xgB}!+PS$ZvGbGeCk zxF0|yiKT|AgND)w9VJa?#RR5GZ;6JL%*WV@OdwUJ1WLj-2m*ZH&wDQNyo0j2MRr^j zaPvG5t)o+ZDB;}Ss!%zi69y3-t&=C&UDw5RT@1sZ)oSI}9|QrFN+ti97&A#8=hOc* z9kT+5Kj&f?{nUz@AROe8Nd=J{s!FAj|Gb!JH*^D19ow;RN_KZLVVd5sQky|Wt-5wMp%QOpHN#32AzEIn31cQ@X-YCz{c`&XFx#IK@xV za~y{wiRv24jmQ*1oT?e!0oq;Vl{~PPaNkx1&5%noI3o7RpKW!c={yn>LcB5k=jk zn{<1t$$8K7`n(%8IV}pk0w8i2!XU(+NSS=dqwJLlgNR0>ksG`;ONo;R)96xDYinzH z17N9C%7H+g&L@#UzS-jhEp-5m%-Hh4RGwXEDhc(a5l^l5QD>GH8z?hUvX+6>w27jv z1FFt=m){r9Ps&_X!=)OIJ5dg)R?Mh6NNRPQ8gZz34%sia%5&>>3El2GK!!qtgkhKq zO3HT@DpVakAfTdx++Jl*)IENulkvCv4Ams~b`jp7C`bNX_O(PIqWtU?=8UUVTD!Ss zb?&=V>W#{G4XdiE_sO#RBnIJtb}I0P2+}-S1Wa!D62NVs7$w@*u+m6^G6GP$LC7>oQ|!(B9f<_W2+HQJt@QEg$nBt$jcB zwr5eXDrn1I9y#22rOoy41*D;N)26!_M22j#3>uvfKkU*e^o*uD`gYL96a%M9XRC>F znP*W{02RaG2R=y_(d^W*>@7uH8Gz$B4z*g1O1Z+7KZSyOmEpEFJG5INV^8Rejn@c*Fz4~rvgjg@t(JwVxrN&` zK0ASkL_e^Ux()@_j!~EQ?oMlzfoi zmu~i(4|0YXI+&V;hMv!NA4J0xBPQ|SO>C#DOLcm#!hiUc#~Cl# zn7Rf^&w_;hstkpiWR~b6ilTfbh8T3An8Z8ueLweVgV-miC&VpCql|DfLrYE4G|mmb zNUcM+h`=_x5-FSEX5X+Np`#?Br-tgCPKR>2+~>`U5fx8XjJbGHYT2QfHQFi$H^ zBGxW7$)+-D3-dWGAmWg!B#9VAp;c7+Mtz2IsO1{=nz-H$IEpz4Q7)DUPpaH@n@}x+ zh5%48icx7rN!IVhn5s&^@>z{Wqp!iST&{3@ev%V6+Dw!!wj@38?%IzCQU%=Yp8p_v zTBWFj4wUzhLX$8IZ>cF$A{n(if3yxbfK(?cc#kc!{C=C}MvKX5CqMA&pr7J~N|F@2 zs`Kb?Ow(HRsU5M&;)p~~vGk0mPtFpBQQu}1BQ8}_vRR6oxcGC4KE&e`V=q68qKLo` zm^f=P_q;{Csd4nPRm=)RL58Mn=`TqolxnoqhP+a#)HjlIP&uQ}AkAhozejR_B+^k0 zo7}^jrwwk&)(_&L<0K|nO>yQ8#^x$FyEqd zKoyr%%QxlU#0eOb{}==sgPILhuXVeLgnOmp#CVm<<$S*gCHbi{bA0mQIZO?LAl!4c z)_z1F`;`|cCen8kffQAz)&EytbE}g6615Dn38Qs@BalkfW33qzMM>WV6XUFgl4?>^ z*LB8^IaC()ZnVgs(hicK6ay}0pX$tMwI*B=$I>Gr-mcIkrD>Cg|8f~E z(U_he?;4;?>nrn>zKDF{X>1Gz1tyZh$vpnP= zs6(ODCPDGC)CfYQW%`U`lwdSU*qK3^rDSo^r{r6#9#TK6IO(xy6y#n=qF5rlopKz- zh(k@_7b6;p7}ZEgfIxa+1Pu2A8Y*2SfO@NjTrD$K_lN+Vs_vY`F@~;zW?=N5uk6pe z#ntau4oju#ilcIeMIiE=Wgir)q{PYFZpO%V&!MRFJ6iVvfOJozj@9z$YzDBfHS<_{ zECz9~X`1G9GBiymBLO2NOH(YXN3r-fHxH>j3$hu5AjmzJq6nURmTcHKi7^cm+p#b$ zo%Qu~N~KcXKcefs_lY8Gt6LqT8X9R76bh=->Exg%RXV=kZ8S`RlqAdu-3Ul?ZdL$7 z9gZatg_^NzXqHD%YRWFkGRqwNWhU8?5G?u#5 zl3z6%DNQp8YaP>gJ~ghRZG;xx!cRLQH3){!io18fJ~nBxHz}W>P3sg z4@LQeKeaBtm{e9PrZjZc-fhv|2$?+X;n)db7!foRTrWj;`VE4BL7Jv`o=28tc~qcj zT0YIMxQQIsA#BE6eZ5WCNH7m47~@%A9)Pqv_dSUdGIQ&|sa@v+P$Jmqx-P!&=TiwY zGA{jiol9Sf2^%SkFN7TWyp83Uxx_}R)ynm;#Pbq~6!kzBXBtQ}rOG-CtHp0Fhv=Hd z*h5wqJPdPSL{}7Ul*1^w7?r0UIJ;#)BdGfRgMdSFJ-eN5C{c)-XHXNdI|=NmGtLLi zd%u-vV>f*pYNRLkL(P{+zAg;I9i?3M13>nZ4jU$IGYF*A3M+Z$@?DFwJ%l;f3xKFp z@QA*;&j6%6;o??pqI%XxJLQ9<3VKm0g#}Q*9P;x2uuk)O$V0!H@X#-7=!QXU)+3Ap z;wWc}?JG`RfD4u?No!LI4(^w-d<2P#cdqBzFsRreH! z0jbo13M_*FBu+!xOA&5T=}sTqMyg%Be2E%WYC#hDLc8tMd8{600o`KB>|RQ7)j|Vl zYAog}igeVlJjbv(=zEPe_WB-!Ktyevl}bD5Es==qc6F}?(RTagofiS5m;)(BW9t1= zrwq!yRRLYfw|6VKBF=$)=7_$!&j2LLx-?d=vm@VNs@#E;=M4&@V?QHmC!`UizI1bw zk6n$Ttr4v1p;pUHrGiH26tzM`jBl1fdpRZvK({oa4UMRkVoV!o=zSm|faG~zpY*v< zU6M-?<0Xf}^<3PNLwPJWs%H|$CTGy~?Kyq{kwFbu0xGIBdeJjiOIHPiMbJ|6BYWZci_ME_ z_kPjCRHG%eN=uU0D%G}^XhZEex?Lf|K_H_3OsciIWzrFbk@OW$?1xd@&j>{ByQ-)= zECNv{OR5!xY96mhiHY;Kn^IhLobyQc>VC|D4B1@5*~{TB){M)hsUFdJ^sh|NxDjyl z(-kb!zR9?$bI#QSc;|4hQtYb}zF#>_J|X}r~t=aI+?d3)@;W_{H=h9T4gr~2tCiE-fZIsF%wmf zBuVq=Pk`iBuSfRBegTQv*t=bxMG78N?JHHAZjjLzM{qYe8#THa0mywBfn*qg1z9%< zt|r!0$qlv2LS7TcF&G&qer6m$=#V7Yz+pd986+E26+Tqy3(12>^I5yy?yC>49M^dC z->G0}HkBENC*~*xk@DCRmL%FYoMIE$_o#Zi0Cs68E969u4^~VYT3@f4U^|q559EutHOek zoF1f6rABG0K^_De+vP?C#KJJ#QL0_8cQ@d%-_gcSMt4{wBCA^V2*apb>aJ+DsZ`ot zuklXkm=*Qd)aXNX7K`}_p<#Y6^VqDb{Hg$ox$Q5?^z*1HQ|EgW+k$5dw=N^=HY*}-wV+-p^< z$0X_ja>J;Cmipb*yo+$yj_so98kv@$0k-Y*d6GgGsWRrS>p-E|N)qPsy@naYn+}ea z(fy~rl|qUaS4@VBp;w1i2~V$TRLT64;yev`4pKQKl%Ps6iT>4gMoyJ)DSDy4@8?uv zrBca1Z80f8n*+Z(K_G&Vw(<=&zksjsIPQxqE%EnA;|#4Kr`)|hsR{} z$r}thSpA)*23Z0I7Phq|eplpE#j_SKIF1qw%>*<|b4wdb)nigQ`*ypXdr$HjHCLhn zqWnqI6xVTkbexuN@@BJ{_kYMAwSuf@yyXBE=b;bdqt)NbA{~;w0f>O7S{f`>LgLkX zo`-GQbUK~<-U$6S$UupsAooTszm@me3-zFS<)Sno6>91=6ibX{KMLT<_m%3WyP14d z2a*jllJY%OuoOcnU@Ol@6r_iZn^lebe&#~NsVcsAK449`cB!JbmdnY;pAk9*eBxNslqWGOebWse17-#9km+Ko= z*)uGsAq51*%Bj5`e$zDbrcE`cH0X7jrsWBJaSRTE!BHu>VRV+zU8*dOYGCDgB}qb( zX84VD8ZZ9=?(`AH9{pV3{v1ek?o+N)edcmsCBl-uD>UbBOQ_|{ZCBDO`IV9G)qM^i zNtEHVOC;@^E3xuT+^Mtnum5XW@BavE>M-TM`#)eEJ~!~ttJ*|GI!E~L@1OrO{+A#9 zm-umudc4f9J^de`Yd6nk7o}S@&jH=JA6cxi@m`2AmNI^5OCw4xQB=8qP18W@FGJ3< zj3mo2ExV7uRb@BS35sG=#Q+N3qBcNE2et^!?ZoA)b3wYzk_JX%Lbf|2sS44F$1aCn z62EGhbg`RU?TS~UCN&YQ8V!~HlFF&wMj>*2YB}t%h)S+SynS&H4vM$BQ)0cS3^44w zcJ~gXafkIEf0goyXK>Ga2GZ_ckY};q0HU7pqHK?v1eZyk!;MAtH6#c-IJS4QR~m=JjTLm=AZ^zP>g%`#mR?nzRcpJ&AgJDM-Cre4IzYx+ zYl$ch(F=g1&J^%{KL-!fG|>%>8}GOH>HpZ`^skpNj_Fv2-8WuWs=qwX!w-Gh%{IDb zQ1Z6EUl>JbVH=_dpZ;(@%QDL4a{gK=msQJ~RlpK&+O};rHa2ok zO}I-QN6netb8cCwa2o^?YT{j0mmYYJym1!(jsJr3_!Ner6K7jJGTmzw3H%PTzy6<5nmw9dbF0c@)Z!Jn z$7*@|?E*?M*D3F<_D1FVvKI;M<$e$C2}v{R-@ZWW!VR1+K14W~@z#Z9{?$vDS)447 z0OWoH5C8)cEjIIZ!eY3r877mT`D=`Q{MRuY7acH7BlnQhiWAxV5&;y;cf%;;#I^^J8Vs?!8v2eUBzNE#8PEcd2s@=^|c#-UQK68Hg~tb^xy-MJ*almSz6m<1rEvZm2&;J1A?F8HLa z5VN9DJ8YvHdhV%`=DKeFjCcAhDW~2meRel(Bg7dSRQ$&u;G$lBkJ0Fvn$nV#OXxy1X>0Mdj^H!uy686i(<79}I{`Q}+lM%pLv zXBg5P=;2u*Xc=J?VJKBxs&cF6c{lZ-07PL#nsoKAbWhI>bl-HdsB4%_M@KV(Ov7+= z9M{1#E$qrk?7#ls5XBMJ^kL$j0W6hDxhJ2`_edfj%K=JeA5?2qu70o0h2L)zx4N!b=Z=+x7h`;T70F5TQTTFgyIuT60nmKf{3YDo!YC60&OQ;{nX$KY0nS*f|h{Mu|C z`-?{@)fX8*JCA8PxD^<$cq2=HKLUvF2eg+1%u0%78h!bU;;31&6tWDf=UE6Zs(P8Z z{*tb7^`!<;J>}>NV`QX#!fOB-S?+zSG>Aw;sHMC`Ba9C2!DsyD>R zXX2c}nZH~is3#oz^ca_L|R@UPOU!R zP-kC=rzk}RV*JIZs2;w6ikfWS&SR8(%w7|m0uIvUFA<3Y2e0hizCQp>895rsr0mxxfHIRzqZ~FjD*~mg86@>}aDTiI-o1m967CvW_r5WSn zZvNRp5TKrD6L{*y?8ygZF6n4!B>Cs zF0Q5V=bt;lxV5v;<*;W~6!ld5qIS~b5|ELoR%C_L`*^#RUjj_xAPHqT0*|}6C-3OH zYY;d-?u3bsaZ|{x0*Jba)dYF*XBs+Q)#lL0D$G3PfEUqjcW&~cB%dG#w%aF?>d>0Q^&jf(VQ2!$meAcr=ufbkMiE$&nH zRZCz6e3B%|llao_F|4^yqLgAM_%INWsBl=boLsBiV^Q#xdnx@u)oQhGT<~^z6p5a0 z#Yl zI&QZTg{TaI?A1YiVxx7RMj)D|kr{DcO|ELJRgIh?pcFg2``*{kc=R`>Xm{GANs4J$ zee=du&sYwMBuG_5r}k{fXGpZ5ZgiPBt|s8iBCc=v<)7>bmd7$8;tMt!}Svk(w0UYisb3`#Wb zmeLZS73bhyQd-+ZA}40X_~Mg?aZQ~=ljY&L$pP}}yG>@xo>2=L&Uul%Px1QYJ{89)@5LD^ z%ERAFV|kTT&Yt7`B0F86-)1(|ys<3H%T;oiyr>`cXL=4jNcReYo3Y8{~O80HZ-%zK(-#n6%#i zG0lJdUt%{eGwkheHxD9_y_%C7tp^xDRL-+lN_Z1hrBGRejF=b&6%5pJU75?#YPI@Q zdevb=>Rb(}N-EMIK@fnZW4j)vX%WR+RY9teHVlKYu`$~1HuZWvr#e)st_Wsf7-HxK zJuQ^J@0TPAl}e>2_89jyK&r-3JoHYd(^t-_RwQ-5Ylh)wM2?T$lZba5r!QeHG}LyW zy`8~PoAP#YBvdIBxkjNIZJ zKd&jvQlioGx$3>C8cu5Mf087$+ig7CB)s}It;=tagns^hs!o+u1gZ1T zB}&P%Ebn2Mn3(7rw>zjTQfM9VctxUH?uiPj0-&8vr%w(=KHs)&N~IEG)f$##5o$g` zLGoL8ZE3m_b=;z%-APDyo{c_I}wmSs^Ym2zibKbAXnNLYzP)b|xC zL^CatORsSGpZ)_b{F8r|;DaAQ?=#hocokG?wOW2nNs>^n*8!+js{>`b)kCZfQj#c3 zKtvS*l)h?3 zA0$hjBnhoni%zGLSCI*DNOhJPrR|3&ERl@b47!)9vE2fdJd1+@BE`8JyP+U&mzq|A zI*wy3)4rrQ7NZF=Z?V*l#6$(ZEy;LgEXf*nI8PqOV3H?RPP$&V__&JVCXZeC4l8bkyK)oF@qZbyu*7%92FR;!g84YiR{%5Deo z+qJ1GZly)A*_8z`H7k!+r20w#LTyZxNNu;qM?7>f7-C#(+rFubyl9Zci@lYu^?{qb zNAXF8nt-H44!4^OSA`9w0`6W=Dr&SYdvMV7zClG0w-bR#@rZy}v)Rn=i9~#=q>h}I z+ezZ9XQN2tjp(cg06>}>Z8n-4j2(99E8MZ%Ry4X+O}=AZNkn0RRB;7 zxp<9ve@K?Fx!NFT#Y`<2SoUz454C_H3`0E6qgt)*>Ts*_H2YQUq)z;k`=&m#{YWCq z^W4wtz8w&eJmaw5i~Wc?RLK{q{FA>+MV?x;qCVRqkn9Dp)UzS`RL=hhK<;w@S--Kt zyT88%F&uh)3{$s;9y-;S@08dSZ+?rC*~%BFk{&|m$VQURa8;H=jI9_*>1u5@o3vUj zN~O{ktz+nfm09M$@*k3>5+!WOgoyVklnFqbMr^j$$YMP=?y`i!5rZSft=(=D$1#;k zrSBd|enaRanHM6uT52b@T23pvL#k1?42y{)6@r&j)-E=wO;q#yE-I;FWaBtO*G$&m z3W>vv@rO+eN2lg`T)eTtci&s#(Ib;Qbz&wr5-PPO_eQQ`F9%zd6HyK0ei&GZM#QO* z$aY^2lrrD@UQNZ5dnJy9n$sHuAh#L;2>40`qAL9&*CF7nilC|r*n1UI6ws3WrY6wU z-m%dn!uvD_k`Qt6hZ_W!O-}sGB=d)7hi=~8fQI^e>RbW&dy*t*dM|12I=R=YCS+B~ zYxU2dLm`~JB;3X0=^jKIUDt@?DF1ggiLM%p-+k$y@Q=Rz54h5N3&(PE!%}P}R5@vN zlAJ^styYUhqmk1Ra(z-VIq0wyjc>8)tvu-vRO>|P*7s1O6^V8%$720_hadmrC4T(h zU1#aFCYk|`V{(3_#XtY<`+WWNE7Y59I_);?cDs)jDwoT-qOSn`Ua29WwDz0dmfVFr zJGB~YKXNbfoh5H|FCvja9r(8!fe7Hrew2GyoSIpr24zpGiEg31r1Eb!OU|)+uT^`p zUD^L=9dH22NV)XN3M+578T&-Yk#los=tDWy;=JTR9IR^WMPghwY!pQpx`D21-7&P9 zhNdxa(%qn@B{hjBb^YaXnNq2g|4br-B#BAWq)$&voy@l-K$j7PF*oX$S!-V-q}`XG zmb{BpJE_fA;w}2V&&I|^K3iPMT0PIhaU3d@O0ESZV{Zo;NVVKoy&u&H4{IFO-iYY< zoq-;{rfKLH*shIXX;@_gw`5})CWdKo?&vgs?bE0E+#~b2_EsN>fRV_LsMm8VJs1Ka zsw(q-8hVj?kwS$1TB`K@UJT^E(hEJOMH)&6QOJ9xjt0q+$g@$K`BbT(A`M;Krvf-T zm3|AwThzSk+q1epN~Yhh6jr@a=jyk8ysFLdk56N2*1&_M9$WZl-EOzL zysM?txskB+{SNN9$-*Z*Oe?*~>k<#V7zL;YKtgTxcf^yE&953V&-3~We@@*bDZhB` zZ}HiOeuak?o*?!UvN+8n6xVh8#0Ts3I-O1@KOmJ#B?lU{I!VAq!uB8t@I0^2BUJBg zH>8iSZ3o@dN#pK4sZ=V=o~?5ETWv19cAeu-%wrpayR$2cCeQo_Q`ojcWx*hb0>UU} zx@__5pFGk1jHFi$)9cWe>b0VJ>vnT3cH_|(duaAE8j&VYq22b2GE*rn*(Z0CUJ>wB zqw--?;&$h+nCnn~rZ$es-d1yx>b;O?Qca)_>hd3Sjq-bHey{jCb+*Zf#=4IpkT3}N z@J}~r1x*fp&S89Pd{>4+{r~N%K#JIx=Az&oD zvgCDCuThmmm;aZ~FMc=EG>JPI7r(p7`da~MuhU&a=janN)Q(y#eJf#od2<`CJ7)5P zNA-w75C+6iZ$^Y=VHhT1xMf&`S`)!Np*!Ths2Watt@u%gOYP*T-m0M&N>DBN-LFVT zJo7=lHFuiIQmYtM zB5;k?eE=ZWF08QrYQo$TWez_)w`&hajOTW}AnNR7IpD7A=9{WCZ!qz~6RT@lQtIi!!N2L~dRgo`|jV@wt5<)wUL!3lp+Ezb@L``a_E?^|;vg&k1 z;fGa`M9EKxmsY7%a(ZGAJpi!$O2`lYUpIL1e_W<UHz*_VKrSC?~1ql5iN$gvpg~Ukhr-4_Eo2t8|_P^}M5`ev% zl$N@m#5nH;K#I8zb-aNJ9%`xWU9iel>Q0F+G+VrK5X-`zdy}me`5lp zoI3~L28f)p8%#D3bnCL z4zChZZM_6*doM)*DBE|f$N1avx` z90*j6F`?0RL-nXK;9|gp2E5hAJN16-H;Bk{SEm5(XChpj0#&2!jvjEuBj2tIU!{=q z!EHUj9`uaWvUqjU;Ct6M`EP#jr+n+JB@AP5d9>Q_I80Mb-cKUfB3KNX0j~ncD4Bkr z07#O>TzP4eWW(h6rzRL5AK%ui83rK3A`mtD2&3Lc(&&@?)^!bU!oaC*sj>=PqD~)F z+$Fs>{6+ed*)KT)#-HdiX@@NWIl)h zj(o52@$tS5ua-ut!;myhqtof1eIm4r0ASH5&p%b>`Txs2kNukyl&9@J!A3(fsGiVi zHv?8aXb`7Se$4`qGB#IDpzc=Suz28Q6s_b1++j3ug<^Q9^|FK>2u=W3k`%gwyxeHg8_T@;}{W7+cp zf_-CbhkRePziYG(Fo3LG-(dBPnDS!*hfYoHYBLY>d1ooK5jn`VVTWuWI$-k325J*655S4MO`G!)dL>PwoWW~K2QdL%eKS4yLd*pM9 zd9MAYwCZ$ljN$pt&Hqc=^yd_Y}?MqhDrpbz%-;9utk~4{i=>v zn0c(u^*>EmJKv=C#29Io_Guc)_3oBG-wTjP6`886st&o@&3mY{<9>A^%brrlB1_|^ zG^*Z87xkd)S7%z>iTUfrSvM-BD@7t|)Un-?XCzf?Dvg<@DW0YA{Mke3x{*i!+c}ck zDNzX3Dfvd|HsS7Oo{Kt)cQj<`fJPvzS2tLHGiK~zgPFyhqmN;;KvdzkVw0d@88nvz zE`GhmmG3tB@Q<1_KLB-5l`14Bn_D_vB@C7lO|?#4x~4@2JqUt)qe=(0=XvNFXqL}KFAZ3_s`{0deNBtOsJRQ z%n&uVAyJs;c{rxa!kJ0zvdQ|JDPiL0CB>=$<$etR8D>C*DiPx;_h+|>P?eV1PufDF zj$$dQ(1t+}5bwk13Fm*Olzmm2ws`*3O2VC>oW*8Re4x}0A zmWF1hsL5dQ80A0=^19SSoN(`AaMCo*1^y)AD^yLAB)J6qX1$K4Y1FC}DwPUpno=&8 zsZ=UC<*~7`LA_qjJ!0FoDVNKA!<$6TT&0xMT#(vuDBnSyO)g_R(Yi1yKqcP1+VLy2 zi#jS+A{O!9%heL@iHLf=&dRlQGP)v^s)v0isQ`6wSg~AM9niItv5;PZ{W8GA%8tcw z+P1}Jqs>OWwQu)99HITDv{af^t+0~j)SYrk0;FQl2Z4_2OzpI1Bp*|xT-Emyz!rx| zb!wzSaHlPXk_?`Nb@#s_~`C+eg;{A**_JsEZx zaoe5OZuBMPg|1M++%!zaj@fkHG-zB4m_Iy=UhpmMw92XEpVWv#RRUJkUWa+L#fHQE zm{2E1XwWEJT{jr3mI%ZBo0Ts435j6$i_%iZNXvOp_k?`rpwAO$Mw~R?_w)U)?hlay z+RkBAU#}|l4r)%6Gbz-bP`m1k`t9zKoaK>1?*Rjll$h(U)=AQsg{NxR=FUQN&Fdjo zUv4n-aG8md-ar5m3QN_3@_nCjxyHvBGn^h zxT<`)N|6Z-rIz`s08_12`@l&mRMgq-^0}o_sZW`=SgxoZnj(*@>pF1~<2g22qLT(G zhM^OL-DW}Y!n1ZCeJ2m0+NrJz^k~*_xCn< z>Azp&^?$KKyWx{&Nk6Zy_vk4-BaFhl>8?_#+_a&^$V-?nD!Rq;KF4u#K|i%CU9BKd zn*pVwM2wSEXGyh}>h-8)t(8h8{~cBEQSu)`iRHX`51iCK4|#tz>QMVVREj~@bM?$d-sg476xU zsos-HIjNC>l*3BJhZq9sd60;r)oSJ5z4S;3KuJZ5B!Y|c(#88zWmQ_ORvsa#!<+=D zgrgR~k^F!FfTn?F=y;}=A3QmPK@jAx7eEm&S)G>xP#*KBR!ekVw`o1ordF%=9r!yj z#cr4plW1vBwT;kJs_eW_GQ}Z9Vtj|a*RAG5hD8~wyv%-5XyUjOdzW@v0-$m&sv|WB zbX9RsRWiM(rd*8br5|>@A~(Sf1%3Mqc)Xkhs=pd;$8$01+*JJ@Bfz1%F8k684I7XIQwsSbo>rM zZ*WtoRO*{AARAuI5!kj(tJTUwT2)|Bz(pahw}y>9_EGKL?art(Hd}YIv+l z(hH|slv*ez%hgRUbemcpD)Ze{YDDraY67w-NGbP2ax!5UQm@x@`H`Z`dLG%O8M>tt z8!_58-s0U_5~c07TvO(bNF=B>{E63ot6lHvlIUl<@=!HO+E3v}RaR#hr6r$P?CVg6 zs14JkD@L61S&)$?U4g_wfH#pvu zE-g}LD35T-KO$bwH@qTJRd!Ez@3>i6S65|4xPShAuX>*Mc@2Y35McT#-lRnqXJiSK zXPkabesEC5fwWppHn+A|+ibAWXtBAuMXTM)fpaNk$i@-eL6?yvt1v7`h>6l3j=L?b zA$W^)M@#cxrBcZwqhe2lF0tv9TMU?#t44L-YAT~JW2EGkrfKc~1$eJiD!D@$HNQeT zku*(nR+b#XQ4$Zib4x9p(7Ed#rF`{nIuWf!wb%N!MB7>hMoN+5h!3NaTny_@21y48 zhvB%2&nSR*vGI0PH@V)gyJ^qqiGPBn-Co<`?d1lT)?N6CIMaia>-1;o5>@dt_gj9F zb0oo-l<`Y0R+^w2bjY%dPNy?8$3wCW-E}M3$NH-Q zH-6Y93NscT2k(3@uf+<+QLEL4=9tTU>v`4Co{f*Jfil_hnTZ2tyYLLm*kON9-Z4Z7$#fKewB@{{1>F% z4wc6~Pwf}}4)|qUXPXWy*@R>fGDkg4Q!+CpTsC>_zi-jJo?w_JTR#bS=-;rJxnK>I zL!^XK#4?JhcX4=?HWXsyb4A}VBWNXB)|rB);7VjI>!B%+;?xAMk;5ZKM$ezt>@q12 z*pAKCa+AhJi=&S@R13jDQU2v!jc^7Be<$2wCqpmBzBtiPFp+~A6Rq~V+kI(0GYKvZ ztE45km;@E$#1F+_Ykj!lTy*(4?X06P zrE;L`W0VsSM2+G>$c_)g;lD8247I z)z_v9JFLHy(Y%pjSp5;Wz0H)~bqoJ7pEypiOe^2m#mKj4OeLb#jer`|E`o+dT`nz) zEk;ckTcZx2)`^m4D*?ylyG21(Gm+$Qnx;h<_DGT#(;PHaniffvV1zE^NpIvB;-4n? zs09ZP0!kMFcQGcNPA6x@9TX1{TxvH5tBDMU!O+rzn$p}lF3Tx)(HBcbIt!4!BhDd; z6YgJ{vo5@(qZ~k6=NUSN7PQ)y51x1rgVaS zMo=!7hc+sJfr0C|I8Hz1mvWQ_x>KNZ>Iv+rV;H3xmHR$|SDox@RSiB%=4lAE&+|NL zwOU_tz2xDSee9Bjp`P3TTHOZg8|y<_QscUEiy4R*^P*u8gI5IlwI-EBe4=HgGl|`z zPbu-p^9q0{3b$I*O0u9R?qRz&y(lD%x;W0DG)I3BSNm4PwQn~GHsZUC@K5U!JYlb( z`d;eeLeCC@AYZ40I+0OxSa!p8?xjCPE7MBAp{My3*GTtVXv1C1ByDVOxu}K`yW&QVF z<;vgr5}SW=iG*|@J7^p{18KKAbY5{N&qYkk?H&7wdnwQVf0w!QLWiTD@VM_c>v$z^ zh@GNYA+m`@e@aR-`Mi)QqICX~EKD6GY&R$`-H+vXkZsrYecvZdQ`+rzZX_i7h&wTH zlw!^Gs9wluy=Ic8P&s8#IvKLL*`;F#xk_xgT)wMms>rU=2SJxabo3++snhA?nU^>K z9qq~Y6w6HGB2Y0z(!Zh`6Q%C2v5#`aXZfvu6R45elot(_p0ertzzl05Vf|8@Yd^_& z^52@rpR(T*8HjcwI@7vWd__u?Qtp)Zx1a1loVfJp?B(aRmeYRwI&_D9v9zOAp7pS_ zViRbQ%%LS@bZJvhGSp=|!Sr@2U+vZdqSYt#ltKxpgbZ-6*~cjCNGQ&7F8)kjX~yR7 zzfSAf>-f(cqyCF$iJ}-RaHh*R$LhG15}xfs^&U%D&DDTLx52_ACH#`V=X>mKCahiT z(!3tgyyRfv02xWLU6a)tTWZC^IFgMf9mu_2563IvpLqhZj84#jY?~{t(|6M}X|-BI zo#$~Jlk^hY36ryb-lKQBueIgPr_>iJ7>1Q=XK8tH0kcOL7Ty1$H=`JHseNnaS@BRv zWG##-p(q!}zp)n!bD3c!iX5b(85~Xqdg< zu4p}A>nm>%ym*JS6H@*73GAweWtezhxWL5ICo${02SmF%kc^bg*F&7hW%_hws6M{i zRi3pu`PnMfC7Y$EtCVY{!7dyfm1x?g#xQhRZre7N0fuRkr75v#;hQGCFvNhoXG5YR zi8ds1H4KA_U%{Pnuus^uTP=c47sIe9m& zNVT|Wbq(Ei9HKZT?gpfB1=IEJavaiiEoFvLQMv|+OQjNS$!7iSfXz2UOt+8yMD2vu zm6U}KxwKa!;@D*RWR;oI{>XB}d*QklP<^+^RQC-?z#*l<-3*Kv*8NagwRHcu=D^*u zj-4Eolu9Ky(SNU18?+OU3`5VN8HFbWL2w{;lsuCb7Zs(gcp<=23=7n@eP<$9d)% zi{X++U>WvZYN8^@CsCQ;3li0DY;5E|*X?%6Qu0n(O%f;`Ks}dQQ)+G7?$4G;V%k6W z=WIOpCALh1+J$GB`Sjl)N{t}}RXGguj8gK_8b)F~k|d!Qn}kt}VL}>b7$#&XWL8SI z*QIyOrgSu;ezbH~wD?|Qt=uc9zFUb*KwUjAM)uCQwa_zYG?uWJXBj7dvR4)2y*OJP zw8*b+x0}-HWy-`uTlxTN4&pVZ0b#_zC;I%C%X7-1fg~%)#At1>Ae<1OWfz!^* zgq0F=|BI)X{*4E*r_0;UW4~u{w;$MAY0-JhpnTH8^S%9fx+uo7OdQ7|jKSpL#~hBI@VBfs%~!ae;sX4W^Dk}>G| zYL;b8PfzDv-m;m69$N(e1caBYMxx7Ft(KQMI-L%!R*SHckfj-ZwS;XA8wL4HO(QId zDW+)(mPPB0KV|g~|0~j7i!jUR-n@uWo1^@p-@NNHW#jAYN*_?^$o737+pw8fayj*j zaOJCQk}#!m)MEM(liOEU=mjY=$4f-Lh;G&$q7c8=()*&ZKFr9mSpLy7Tx6ZcMXOq{ zazCXV&Crtnmr~?mDDet5qa*EN#IFr^u{1i$0qg~*+sTk=$E8)T_5W)L_ru(SQkjtF z5bFM6OX$B>F0oxYhz6kQVpZ=gi{IUWtThQ+84Jhj`;smxQt&hmF|LWJU&68I+{#$_ zK?fu0Q92cI=ZosJ>HaX`F!L&|w^bhwP`sCg8g43C+yAC#-Z}B;}d3 zBP<388gtmG3@2HN?lan}!5sx&7j1$rZ^=C$W@eyEc=C>P8S{fu($bFOutoyx%YpQw zE}JhTn6;S6rSiT$SW+c@u%+}c3Y^R%^~~h1X;+Mho&qS}E7^-=3L;gKnl^@4!>}B(B!WRiSe`n9=epQNdKb$} z9Gf^5$8o4sD)|^+Ifz-75rq-1=VF!n8_5rATzUH%y|+qCJYX<2J4qUCm%&6o%QP~= zUY87Gs5j@Qed&(yy)dBmTmBKJtW}c5X^5j9Rbtv{e#lM%SCLA47};M@^;X_%-dL+x zSK5K@^u3b32!(l+fgi`-D?X!^`O#UBW`4aBS%@Bypg&hPeZF5=TDok1(DLV@IFKYs z=rvL*Q!cgo{-jIv@E4srit!xvVhj_q#2{{hVH%i@LEOq9=|^WJ#~+Sl7S1#IEC0tn zc3_zJ16lNTr$zHx%<2zPN=qTrPngtdRXoq7)oNl4qIq!?f<wURSoT!+%5pTXI`E<-Bq7EB6w7$eI+N zS1T&NpGsP~xm2rpzoX}Gw?&RiAx0^?OCM>+jZ2DY8F@!{u{T6xH1g0)Hc#~FN);-%E2isq)kZv!;8|YR=QAn%ZqEhwQTnTym%WF(O0dr5)z<@A{ zNF%^bFcKrjH#DVKkNuPytk8&?%_faT1Ix0Qn3xy{JhpPmtYjrRij#D_TCL{MpBNo2 z`j~4p)ux#H{NJJST-zl~!);cX32W_;fAo!ueCna2{JD>w#a2?=dd~W8b@O-f(o!w& z1mG%$Zj^DAgQ^=uB@^5&JJL!7MOhUwmOC-D_Ub_7b0z!N_bmHSK7Xh036mbp_9nhv z#WaUAu2DT98dnscT;ngAK%#@zQPg3LXC77=Yt%ShZTmEn?OtSW-VMj0Rl48Jpw9aH zfB*0QU0`IfwYAmZ`b(>nXKfbG&R`n5FW~JTx4H7I29-G%uQq-@K+*GSY`~t4@sDRL zJyqlAr%IG2ts$nA$ejcDr4qhh%E#aKGX@X0YGO^s%sl2WeY}cgnOylsled4rjZ-x# z&s+Uj8kR|#B{+7!+g9qrvWa9un?(LP<=0u3G@^-Ix|9S;rBZH8B-=0yV`wIa7?E6p z+O$aA8fImRI0MJB2zw#f)(!lqfj_-C1UO3eBx!d}2_9@DF+%eHaU5gW7ArT`x&7@B zr(zPVT4ZgD+JZ;FFWn$XQyj-;VXDgUsS?xGQXY9q_Mz`X*Ia)Z>b;}Nrib;};&8P= z9%Yb(`6TNg`?_ePbbrveo|e6Q?{0=g?+tOb`tv2am;02C_EFdOE`6DQ^4x#Uxw*%g zsU69cE#%B-M^tnU@@^!k5|(3;$}9J)*F)azLDpb5CnEPePRmPYBZvL{hvhi5pyj(< z5$Nsc($_C`aBkO`dd9{wclZ8jl=1dgx48T#4QdM>^~KWI(twnBinG1}3_D}?A&+X! zCy7#e-4MevhUA$Ad=>^(5CpmL4tpW?gu$sVREVPlGO!(+=H-MtKMa|D*vIu;f^G-f zaOiAAlxHjqBgL}pygVf(ESbe2b4Fw`VNrfv*j1%cX^;^`Ln^ug#FoqDp{P{ECA-~j zP9t?32X}Ik(je2YOoQ9M^Iy?exx|@&`@hC4)$)i@^u?qcp$QBU8R`hrv`jkP7B^qm z#I_tt6}b36wy7M6_~d`Egj0404l|Z&XKkbs1>>)h@;-_^#JHCx5 zPRPnJ)tTDfUWj9G;!}0X^ES0pRvyWYI%JaGYw#?O2uzDOiix`Ymlc`YGs{b*($G*O znT1}j*N6HddcBBRy+$|b|GQq$WBTcY+W9(54^QB^7Tuu7#V>8K{(Q{bQvpjq@8+K) zo4nKM42_$W`xl0c)}Rt2Dmqk-phfpyVLx;Ydl6GV|eIrMtCC zl$v-2AiY|x4n=!fb+u>^3^JDA+@$r2#pL4&XP-DmbZs4f-oo;>0ay8qBy+HA2co_- zO0`-YY527It=yZ=O5SN_l9L7Y$qYJ(6WOg?rU7@$+EzFaW4NFDD^A%WyuT6cUG zvmp7e3{caf1d7*%`492X(WePVfY0*0g8LMK^P&JgU#^J>@_QJ0o%;4EBBymp)o$=_6H=ETP*SztHmH^vjb4l88$TXt&$V zy{x9PN~R#uzLW%V8Id^2n-H@!!6O;CpjE##i-n7Yl6zAh(JDpA* zxl2EYPR&JgOEy#gP(&D(f$Os$S=oFP1mq-5k4DFx=M&Id+!PhL9 zYPCwU*`(QQ=Djex)tGhDnFjgv-yb%+<{&iM{ggeV>wK@ky%=Qqd2w<(H74$4!1fBR zivyRzP(@=T(X<$N$wp*f>%9}lF=>_(#Sw1U!<>7+7ssK;5$sfEe7CP%ckh8-lL3}#_>y? zqh^Bah0t)AO1c_M-%pStHmW!k@}0;y^i<7JBdOoB8OULj6m&)~iow$NtO;qFkR&Ol zWf62bLk3WfgN>7z)$5zsC6n6GT3>3!gkU-4=Cdto$83&1F`Wa1jYfmk))v)TEthZ5 zn83oL9`g_Pdt5s0fL`3o9hR0~m-JdnLQ+~Pl}cE)h3A&I^pysyKWZ`iu*az{`ru@_ zL6b~H$`=yFw%cubyBL3(d%4$9(b4LS4O+J%j(vE7 z>Dh_={^B^sw)%A6a;0*Y1h~*rg~}WR0qu4>Z&ut-L@3Xpot>6yA2sj&AWlT;?eElq zlQkJtR+213um^cwSwoGJ$obf-fMbyyG0s8g$%3OwSH;p_(GkcQlKn6DyW4va+)$i{ zzQ0jp55^G(!BCAn?L+L z>?8M4df+p-C4Z=6Tn>yhw)u4r)7+LyDR~~3zPHJ1|6_}p2VG|FD`S)rx}6?D&?W7) zu_x-F4`NE9ygM!k{sd=HUr*Xq0CIOHI<+wI%|>CvEu zVf2MDuk>(}GSg>E`CJz%%Vb$bHwfr#tl(AaBcpCHC~{!5K|ILVQSB_XGZ76kO*=hE zscA1`XYbXC2zH>Q`*odKV`s%txZ@fVcXOax{-iiHQ!4|HdTz-~NyWJkb zDfa^WOCzhC4{aEWOd)Y-dojSeJN>Yn$U%EebhSjX%zLGg>r$1J1mDZo-tO)m&z_E8 zB|_039lZJtR{!9?#5?&UM@~LY;+F1eh>^pXrYVkRV&@Vh4nenzQI09i8o1NY4FgR2 z5%lEb1inA$x>a>}9S!Pol?J*k%OXxB9IYfi~AQ{h2QKR%vh)G*Yk+i_kC>J?gP=i9wquXi$vfPk7qo3rh-#3u{;CE zcJssKd0sAIBAZ(C@TDGHsZ^*`Ds(!XeuJTD5Ck1e!y<|!{BkKTUrC8a%1@4KbNsVD z_kC^_uk0eM=i-KvLodd@)oS6oF23*QxQJjqGE}QnD&>Dx1a76IwY9ZHtJT8y{ao%v zoL4^`j##_3Nw(%u{fLcIvPS}kPPv9Ze~K`($BG;i+R1b@xQdDa_CZ83(v z?+?+cM^UVcQYQOxAonsaecWdrRDD`E9_~j=Ym{2}`{~;8Zf(zkooGAgF{FK^H=lfm7-xwhQc|qgnaVi%ixrZkHl+PbLeHX3;)Kk|z>P@_ z6C<;Rbg+t>Mg|#44@jfY$PKTSmKO&X1VOHGRdga!P7+K)8{l03sMlfrjV`!QTc{9+ zF=-Or)x+W+f0z@0`B7T!4((QhN~JQ=SZMLToHlD3*tSI&Mq?RZ_nMh#tua}9ou!UC z{QH?*zTZnbHCg*{m|xL}?4%~F1ssLAp;ZKm>ni0;A)SoEDulr#`%e#F8-q{!25p7se8eAb}O6ig{4)@+TX8p+IKunvlq%-dHD_- z*InWVVrc6~Br$evT%cF9`Fo@!i)mM7l`L=;+b~*X^ z5))_L+`-7<@alcGi&xYGIWJKZjecXJ!{()kxpP(Kj!j`;kr~MlfZcyLB{0CTZ9Js`HcE~|oM8W5g;<7# z<5_qmk2u<9A04*Q*2YQqnrLTJbS7H4_ppqPE;Z@(mJDMj1F~0)rr4M`4se%XMaToi zAyRro?YL}A_N4q*Q)?w#*CTmHWt;LIv>JlYf{W$r-5M8vT3N`w;uw0gaIv#qpEnuy z_I{R*-|=L-B?r$ck#_ror4H-T^DNRdrBbQj`3X@N=6x7)_`2P0PHByknAIO7tUsRu zDW&-y^AFZ2mnu1KAmV|2Juax1>qE8hZ81liYOMm9k(Zfd<8-^-{{1ygvNXeT4U!1j zt38sijOCd_qKM^c8Q;(7#a*(Dym?TfW!Ws^EQ>(7Y+i{jrF1wf*>Fa z!`vBWS(aldqVBtWSTi=ScW@eYrq8)}u0K>7(tvdwN2FmduT|@LD8BFCwb@0M<>DW% za_5I#&i!hQ`A4clEFL|o^qnAS=uUVoxn7jM*8+$4a%eTfYE-#SV-rQAxfeWSr>MJ# zlW19g-Px|sjUL!E&S6QP%BW02XU)Z|SHEBRHxh;G&u+C^L##ge%u!==_mh<#W)`Bs z^n3lxB1=n85dCR)kH32uNH+L&C|(1iAO!$;u=o+5_`#UW$gr*LNbFuj0rzugb?Hb8OX@KKvL6m| z>DlBveTHs0+)0AuAky!Wfywi=TCJhaFP6VFC3{>}B!P?GOY*bhy2Qmf%lp;RHFBQx zcZyTj!k_oDAI3={-7D^Pn4c%_SFq0aLihN)=Ro?)a4282{$`h#{)bht;M`v*GkLPl z6mm;8t1q^A{{Ov+<(fSCzn-CbqQ99-rBYtzGEI}98*t|Hb!talxnV?O8Xd?o}2<_g3u12uJ*HwjWXR-cbK|HTp$6D7Kx{^67Ebucg;Soo07)T0Jr7*Vb{#8E;k zXytQ2bj?(H0K|YxlbJ-`65$A2L-&0M+e{xkkq;5WEoBp}uqsAS4w9ZG=(;Z5pu^_P zHg*+`T$soM0^Q^`?jVV?lFUT7{jx^#+?HigIcif{C}Uz_nijpZJ7g5)S2!qBzMFCk zMG#(kZ}Ndzibyc(aNo;p@*;6$lmS0z&x&LhVuZ!vi<*FB4}Qrdi9@n%XJB6&Pu*Lx zSEDDTTU`p%EGzkZ!B+M&JO16uLgao9iiPMPQ8GbIRuI+j_p&_vp*ax8aq*AA%H=kV z^){si|G-}~an51!$qJ?m^;7+xhb%F$Y>T;v$~^t=9iy@CVjNRak~GD(9V~S?#CeP|R$3Ci*qb3Kxlow}dkA}d!N)Z2;Fl|T z^eZaHa#(aE`fg?;MMGIGm-98$;IA&jXd`{E<+q{;WAT{<57{f-STZ^t!ApRm8)cI? z=GB#ejaI;i&(2ZGG8nVoQc^9_ZFif@Cs?MGiN#s!fo-~Er-=ZE6&xHUm@ba^pri_U z-^KeGrDyhjADg?g1F;;Y?sr*v-J-qTg@uDaAN|R8lV=>B__wFY$Z#ry$io_lsM#sA z54%LMNfM<5K{tPquIu&%+)RTcPVzq!ykc{6Gw<<;q6mM%rpP3w>jxi54!|Z`UYM{m*WigIK3k|tn&G?HkM^! zyCve~i>!X_zoByGNhUu0>zGy_Of8Bp7KioxG!BxcT*~_CPIzJLNrUNO+@GGcK5G5N zIq%kIp?fjLy+bk1j^ps$TUWTg(c#1QE%x{7n9hFfK=j}?9hr|aoI2o;z)6O+Nl>Qo z7hzZ)mcf@En8S$bwbs~PK2L%^S?}HU$|wTD`xQ{%H3YCN2d`J5wcI0pFvi?t^ZNRm zUEciiCeshvEI!k30`w*=EX&5kysK8&>qbL7@i>mb$S^GE2HifZ%CLr}?8R|RuN~1` zUu9-ta(m9kRMvM?rZa@$PO)8ZN)oOL9D_k_UOviwhjni^i-&iBb z5~`Kzj?P1u(RMntzVGMHZQ2&`>J^$l`j?nl%ejBdBf#>Pf|k9r*HPxBxZ zSx^#nOJ}qg4~ZCczsW)GQ>z$^b0WeN8)t}$gP87e{%Xd#0esOWh@sal-;*yLa+l699fd~uSS%-^sbo1hVL z78^{a#IB{%P#}L%4dorW3B`GBID~<_|h-t~RMw_cmN=>7x~F zf02okdk0I!FqX?@5@PQBDB$w%^@sy#z8+CO9x!#%&&R>$rJcaNi{X<;#%e^ZI02n< z7t{5ktb-UlF(g8dlup=QuQwQro6_wDcwT8JD=7-<0eFr}^Kz57{%DI{JLc%qWo*|R z08T-%z8UGsrV{5PYQln-Qg@_fBs53@Q;{pr7mWf>%cs9o09_x*gZk{BEfHp=?`G_n!fw)5T@jn@>PQ-jJ{ zYD7Ex{Y0SRu!?05$#{!+i0tukrJof8btX5R5GdsgVAMPOf? z=w63B6{lSm%Q_M`=s|0eWs7dtUV32mx)1k~HSE{P-=*b6Oq!%vrj2DEj`I@-t*4Q` zUrJiLIuHYs>HACE`bnGhw*royN-){oA(SRP1A64e9oamB_H$?J_+*J+zs{Knk5!lxjt6Pz-VLg^2?xl}dS&om`^tBcIvF zXEN&b8bLQ8Y&LVFI<6j?0Sk}&c>k75{iH)?q_np}x~+&(%^nME%c0a=$&yJ)S*y`# zu)e-!Bn1A)sb$)Vr9e~+- znWyeMnmYom11FA21G*Ai6`jYps93VLQO1ANxLR2+392Lu5t{nFc7IFxPm~kxHImoh zeBUueBuPrJoZyyRy!pf3m%91%{Z!K0(<)RZ%2cZX%}ZUHA8s*GpE#Uv&)~J+S?A_+ zEgt-96UjLGKfDOLw+XC2bXHtB#eED`Bl)8JC@=WQmBRq~Qv z>Vjc2mLXF#sB!@1;On{9eT}LPaT2q6yM=MoV0!7uwsS9)@`Edli(*Km!E?X!I5ZVi z>gc);KsymBXX)WmdZxMSu>?iUS2c$K+G^1-=7OrRJ6pgMp z5s9pKQs%Wx1J@Fg0{E_d*Za|cvwWVEv$POn9&PVH-`#04pg0NrZ*|wXoGaPCdhEb^ z2@4VVqa;aiJR75H^U^U)*5g zLv;?L!7xoST6ZEES0l2(!gD+_&&cr-eW! zlqB0@Dm7rM0X&I%#qnt1P$GR@($e6d=Xr#2m-f|+SN~yy-bTuiCww0NcczH#aOe;g zm17OVAWJf`G|Smou4m(w?U4;kMG#)@QJzhgP_~H(CE6QnMBNm3+QIgRH)5$&A_#)K z`AeK^QRHnuo48nC*Py%xjdSX+A|7aPRg9+?HW9&;zLa~db88t89nou0{UAb+qvYuK z;!Nb(ih#7NmFT1G$$g#J3InlEdd7KQWRNQS3R9(w0287S_~s?&A9Glzoh% z)avF$ty-)5Lk_AAP%H=CYa^hZJudsgHXTwYV*bMp^|{JBUQ(5yVmAu)`@(?$EMAyl z<@wvJJ|A-Q{wB4;z@YZw3Ws9f{mY)&D5vH+yK!oj66g6{QmsYDaG*(sWw3-KB>~`%BXaZsr5(CJHIvKX% zVL0i~Kq$Q-N2&8}AHHm?x~Yyn$4zk4fNz#%RI4>C8e|b{tZxuk6ROp12A1#p1VNAw ztCGX5OC92n^oZTPIuS7#a=+RzOQu+y+E+YCQm)gT`)$9 zBsglH6!8?x_eyqsN=e%gXQa`5hs7Ho|l8)$xGA!rOf_bENSh^ z!phTW$0el0+VcriddwWJ-^Hjp$mLcosz)45dpnbmjVm~Vrc>rX^Z;Y%SHe;{%L#A% zcAINo4_vU}#25ablqc>h=2Q@|7OJ zTnuK!(T>YLWFP5rtLz^sk7@^{N4OpafGiBEy^5tJt0kNGsz-WDwUy{F4$au zy~C{^1f(H2uF1KdE8|sd;yAgBda0d=VHi}(6>h9tWn=vg$7jw_D)mJf4a4Zq7m2#W zX+#+H@=Yd(!LFE``V|k;@Uh(Oj#&9Vt;(wDk$UE_F5MKt{80mfc8ZR318ejR5CdaW zuh&S+{c_#b))rx}i|?0lJuk;ZL`!Sb@GI$nmkxI+C+!6!mcy(gD#01Fq0`!7<3Lg^ zEv{+IVvM!1){SxFvYed&*-^Fp!vah-ZX)-eBng&j5oaN<-h7sdJIR?N4`7&gmz}Z< zZf&;d_9AA=CbepH*E2P)=R^#Z1O}1`iSsHth@G;JarKwhG2$%bVP&b_YhZds(P zy&jr%7p?iqi(LPQ|2}bRo%*A{z{FquPcSU2f36IJOUq4GwgMhKIYZfdX9yqf<&xIE zPDZs-<;3SI7{Ik}x9M~{hkrxr&`U%r(7s~edQSeCS(cF|DM_02#RJp6 zg07SSy4`MWghZoCZwk-z^81mjq?pp{)Kyb0M;*kww3ddJseeEwCnu>^D_p$Y;&=b_ z4PJWdMoz8GvW#BX8)<;_)I|9%878$8dr7mEq%4r8DM1hn^(Bb$(zWMt`$IAaof*nn z>PEeGyG^Ur%8lNB9D&9qe`|Mho&%>Vt%FY?w(cj(#l``D>5R2;2P!}ZU}z7ud=1Lxy5{Mvq_`T;J3f^ z8vo^2Uf_kxEAMzoOOLAFD`W6IgMr93voOixV_mL)x5MQZZt=iJPGN9(Oaap}NDcap zX{M7K39T!oYqw%>W*;c=k^jvCy=Kbn{XXT2Jyhb*ilRCT2!deHc<5nbpUk*>BL<1dKYR8nZ`^M3x(nE6~CN`%& zK0|XYVC7pW(@SeCEX^O<4MnYt<%=E4^ES03eVq?YtCVttt{qEsdE`-dWV9+qWYk=3 z+qN-G_`*YfohOd`0<#kfB-u8N*GOUVq`~PgR++oMjO*E0R=Gt zfMh_Dok%tz5w2yKq-lbo8tml0#lViMXY0AyLuG_4!wMY?+Zq}OW?2@VYhxMUmmF%f zDp3^D=>!;=Nw*b&*``$Tc8nP18Fasm2J**kevu%TEJo(t3udH=2RmgBlHEv^QD%k*PhV@xq(UAr|HUTmiHJvkWCrX#6WH!1)$YSW^xmv9j)oO*cl?`71pEj8|S>l0TKZ0#+uhrGnCRdi59G~_% zwJ-@7dAUc7kd&?V0zztqU2WV)mIVeIUrI#MSSV{Fhh7_|-437#T}n6kPLY|$9mJXM z6gA2_+zFpK>?;U@q3le^9P;ktC?X@H*9)muE4gfs3^UU+LiGL^MJ$l!Si!1f;Fcyl zXb^W4ur7{BzhC)InMPQYH{a>fR9yM2gE)~O2=X#varE#`dqeC@rBcna^Zi`=-D3y2 zWM68h@-AOn2Xs}U}^1EW^5o1%b1_IEmw1)K6KIW{kU{96jOh zFeZ^1Mt>#=S&BF4jFwuxFps3u-FCM7NwgEvk($tA zREuR!EnTwTp-%^mEJqnzp;t>VA!SruJ{pDV>{W_H_o2vhce~x8F|1OC6f95Ek4HJM zVpHK>*G)cC4^5MM+l$n_9`7s~Q#F1bETMM1%8wMx6)&Ie=ZOhk;El)lDwlZ#^?H4$<@ z_dQDIO5VAqA-|Iu$T;RyrBWdXf*~5X4kGq~y^K??)p(mYn&R4N!O~G3>6%EOgO>d= zhjbIE#t=s}))hy{>VQIHA*0qpV=dioH$R{6)O*$aF~tVcgJve9qSG+!{lrl$?)~GdGyaa7N{sToL=2{5V0#u=Mt_1IHc_~(4lEPt zbp0}~pC>6LKchc;G0QvOZQIWI>{7p$&(o#1EX_#MgvC!e)XrC^)~n1MtAWu!%w*f0 zvAWbC(Vd=?ZdxXmX>$GR9p3(02dV}qel@0AFAp6iy^clWq1jcMwItb?Og$8UT^r?{ zHo8QGTGmAjpk5n*a=Dz(UKc8-l#YrK_g);B-21&yA9d#BI8L4cNF-jAB{@tCWZWg0 zmk5d0>-8ZT?YL5yWFMnu!RRuqlm^9-j4FfqzJHf8g1jSnxB9FeWF3m7L)~~N8PIOv zyaXvlbp>he6$<@f=y4rZW+J^R`@u}~`bd!QPO`KP?USq3Di3^dkypQRo6CRHCd+Pe z_Q|C^NxvV|b4wO-uX4~wKUAeW>tMMC^#z9{O~?$`THC}nOuT6?|6W~775tLx-?;U{E?L$$e&up`Xg-NJE-?(6BAAg91~H8*37s2I zS@bZnghs20nOXT}8Wo94L@zbeVx%SpYrFoQ(P%VsCYfFnc|SUODvJ3@HX*-sG%28` zq~p4?U#QW=EM>2UN^q@vAz?_ADrJ#8^DE#c2km0tFWBrj4$WpWXQA1amCJ36ieSf; zeT(JUo$f~m781zF`w-_+boK{zB6>cGI5&BQy-v{7@;8!2${Cer$$Ra9KTP|kMLCNk zkG(h(8O1F4&#o-CEbadiHQFo#!y2m&e&`NlI}?FdzI>ajf7}M+`T!F-{Cc7o5uK_Z z)YDq7!OZ#6kb$VzYOHj+*q%G|=i{QWB2XqNq+}afq_ErV(h1s_wn-W#q*+SMulHxW zXC_G&=XH2Z#T2Jgteh(XZhG?AK@W>1;usLNimHhaZ5v|_QwqYmms z^nj+Jp+kdrqRR+7NxC021JRj?7z@|7fWA6{Jp$txH;Gc?9h!xxn=!S)(pj|b@zGL0 z#X9`G7-vx>)-v>3DrYZPmsAC$^V~3uTp^-dF25(m3dcDU9dwQBGa1FwD*jxr8_;OB zdFAF7>#Y#aNJxPQn^Q9-PR~#D&wZ^rG~x9faUlInq{aik1h0PiHrKus)7`kn$q&y^ zuT324_h_(BK(fOck0}St_8cryV4^LO1h zXc>;Ptqv@8`@K4Y;w<)q_85$s9H_Gnt+g~NdfaI){eI=hOC=AojIX_P1J|+n*x4C8 z$HugsyA1!R@792~0Lqf(Cvk*v!5LZw16@itl>(W(1i*Gqt&L z;|||(JWQ{|BS$=rOiys?=0r@7SGIJTkfGP zrXFEg>_$F}%Nf*7CHfjQ=5n`tl;|{f25CYPCcOQXHgErNi!_1Y6Bg(HVrkIfp5^i& z((^HH%<8C()#`Lvd9jC?Im|y)fy~IKD$37@ER6JPjB0e!fO;{4lrwaB2XeZS-o0o!FMVO(h$^t~8=c|PekILO`+cG##4cqd7B z?QF)C6!(*<#8Jf6+bewQ;tE!l&}g(UESm?9cpRCVW_of0)3nB}kvKRlV*=oLF1MNi zuiswg{IOXop1mWLS&Vs6W%wZTIkX&&luD&^S!8}`tg8s@%bH7{lQ=}LjvNYxDjhno7V}n<2cZiaVg)%&{ROj@3jk)Q1AHy}E7e?G(-Q-TA%W5OwN0&Ef zTn_m7$~sTpcZ|u22`~)aF?6L~uk+w)}L=?oVztyGJ=r=EJz7b(YE}owb&B+j>sOz;m zKU>DiwRJjgSUPP94Cn(j<#Gb=Z$T0Uy>cgZRnIbRBB~B*UR^UXawz*Vq3&U4w{YVCc|+~sMv2Z zY838%%Uq^m5QROi-df?gx9)IjGvNHR$+Txf7O~#!@%6PWEVse=S%;a4Di=;18QT{k z?;w|yH~LaS-?_NT@BH8rf8#R`@cGA&k!2~4~>k%Xz=3Y+dTL72CpoK{PLppP&Xyd6Q4wG(XmR_6Hn!(+^znL5U>H?a(b`ACwh=r+fVW<+ zmuDBFh6`z6U5|p5pBGU)J-T)ju&#}UM3VA%Qr{QcCCf5QB23F9=mexmnma-%(P&&m zQ*E{3)ZeYKk%MF-y3c2?0gRS(*A8BnyGAM7>T9#n;2SUB;LYV0RoCQ^r7HIyo2BIS z*CR<&-oCZQ&GinKR@%J09I)AJ@!;tt=BFn>&C1bJFEwccV4~u&IN?+CWa8y`Z6`fA z%CfAS-Lx0SIIIn4jdkXd^^GGbNB|^?4I1B&vX9^cAH+*%CS)05*yG1~7qW&(fmLk(o(O%-!beuioLy&tKt}jeF3-+V2&`A#Z%^ z4lCb_NM|}6f4a``hvxC@d!x;1-5rTo52MLTqTVD<2*QARy@qAj`}z(^on?l)Fqlfd zN7k{p@m!N6$~gK|mCO%`!iajko;yKpNThRB<3Gcxs==k#uJZQ3>~Z8tmj{3G*q)?i z1f(8SW|H0zY2+IxB_R^r;`DTBDh$K?AWJ!~$jXs2MUk#t{0?a#)pGx`zU6Xx$Ux}E zu_C3l*uSBHecfZQ-)5}h*nxvwvhF&<*5wHK+|8{m{^&<<2L&)Y$lRuJNu8LngF z@4!|P45V7E=7797M+t~V?Ll3F-ivsmp7Ap3^Tff(|BEw{eQKJ<;Ll7x&{vl7+^d)P z+AFuXFkj&_kDa0H`}vf`G)+h`dHr^ib`bI4iD_o4JKN-&x0m_yk1o-P(ye=LB;2!C zG%Y5N`*^1!+LtrdeweV?S)(*1Iu>hO0q$$?SA5 zhL%$i#*Sw0Y!7A1?o#TNQjV1Mii*oSVHA3n%|WraJj+saji#9jZ6obSCO(VC1C;gH`_hF z{pu~MzDu>_d?0;Cnx_2lwYT}|%eOf@SK)I{ou^)}W9librooRcE%Oh)`WoMQ?G`~V z=0j)acfq(TEYv*SzO&JLS9O3L+hytGBGun)aPyUQ?tCxh)k_;3`Scbi9$Y+7HljzT zijj~q#Jxm;^4V!-u=bOXm;Sp=lD5g@sk!Z0A-gy!&8e6FmP(}@Q%REy(=?D)8BGk( zb4B#$31BP-)3$9=Qa0Xd(7pzk)l*A*zYA{%SMElj_VS| zDOr@z+*~0Fd!$K0i=f-Z-=(4Q=)xSo{8YwIMM!>Px=!sA6{^## zTz_tptG}PoymXVJAE_|6IJ0jpEs2z6lS)1Npa9u0_0VAYg2%aEnqv9^hd7P)jJ0S7 zA_uurspQ?<`oN2k5;a`u!XAk&DM7n_$su6nVh77`S$t@Ml2;}QqmlH!aYK~G0o@Ww zN>r(P9Hd)ZPXrWE#31P6`=$ON&cGPlgWwtZ-tH2390T%dww6S$V&r5HRVV0DDtVY` zA7Rs(&Tj9k_`SmX(NZWH1lLZk$SjjGRMBzmrE7oO``Fyt;*WlEnOmCyUwrI1XP4$k zGID7by;hnQE#+9#v~b=2dOvV#i6qVV-WzvtjO%>r@yf{kCPrRQ6dadjN#Ik|<C zQ55B~MMe=UvJARm45WFm(75yh;np2et28uZ(*V*8g0P2s?OBp;n+PX&IBwRXOpiOK zKaEqH$B4TaWSEwP>DBqyKY50kdWA4ba2@Ld^vR+K#NKR-vB#55X>ymZ~)OBqp;;@BqU;GG>kGWYIbAmieSR?z11pRBX~QcP@x z%sgpw`pF~I>wCYYV(-GeVj)7K&Gm-TBxn0bnMUZVd-*IK)r#}!1RXrz#WF0ilw7i) zQmN#)#7;9cw(GzND|c48_`6MJF1S4Mxs&;X$YOa$m!`CmaB=qaxVpS-CNT_J1Ws!a zd8HCzuS@XSx9Gm{U9u#m_P{48KlmB29Grop@AZ25T9-Yx4&;my~X z`1o((&79~PjKMvNqdQ2$m;k)vu#sZtwr*A&r)Q-zXx(cgY(nkuxiL@VfKKr~o`pxec^ENsWYGEI6>42Ff{nDkmr+RN9-Oq*b9mF$gg(n}z= zN`#q(yLB1QNNL+s6y`L8VGvd3@h4{~PtJnrY`d2%rn`BE*474gX9FwgD?HdH#DgK<}+u?eCo0LhO$(Bg<(h>MTAL0yVapw za;es8+jtQfy~N<(@1Cz8msD;hi zn{6sHKGhj-XkLOeatV!iTyvCd+jP1i8@HR7U7Lv`m7(#%MJaOaOvLbx>#Q$6gBTI* zlm%;$iFT3|wK`pTS6^iHU;Ia;?RCg98n1tk6B9?MpZie$xx&HkcDr;s9UR9Q8I_K^ zH1p2&JkmHOe*K%YU;a814}BVA?lcDJ5HTVMg1m98XvB9a_Z9mLiUz(|-VzNjJ*Q-+ z`RO`?k*3(3C}9}9dF?hgRylGWRg}P5jHxcUnAp2+t8_Y7&45B0>!z4~py4@zGWz)Lx2GP~$>6NDF zt=*z}`#DR`D?>7cfj4&vGd}@GO@G z+wBpDT?|sPG$Tq9ECX8Wcj(-?LVGQud-3~Zulx~fM;@X&HH&}dNv0N0;aJA|(s`sw z%$1b}GiHbLM~{tl9#Tc9Rw@|19{3*CK#{mosZguc$kK#2-@3z>o_m`hO1Zqe#U~#; z%4B6gpMNhrux&XUIX27e(gc@hm%06e9&i849(Ru4Wa6yD%&7|XnJOi(G*;zTA|E-_ zTH|Iv5ofUrSOb3Aa7t-IXBML_IfTXNI%(Lv_zxPK`JBPT7t3T>nmbAxAu)TIqm(V1ySC6VW9cb&Aof$92?rKCZF_U+5K zC!c^M8Ul-DZN$J!>O8Kwu4t?!STGHfsn7iDR3H9%YNsE^@?4^@H#A94FdV^;G|r+8 zvJOP_cj{XHZnD{W7?M2CZg`Y#zUw;=xN&=#ufMj+u}P0dPR$cWFAoS0{(RG~Jz zK*=v-44j2!8h3?|aV!Fk+r1uf7-A~$J`N*Fu8mur?iE$>Av-SS{J{=)~OFM_24I{%^%0H4?|o0-MiYI4i{G=<|b>*OihfnOF2_- zFcZkKZOp+!Z)~jNdHoW!k;T+X{qp@x-Iwg+z2iV~BV{<8`S2pM=Ud!qn~Uwd$@@J)lLv=KYi^iVUNo1CfIy2X>sU(l}5Nz@M@? z@!2Z%)ArzJv%C|%NKe!{Lz+t4Hy|bi7Eb1nndzRJ9Cb6H&ftpk;`Lg%uA4{SJ9fqc z<=JCcew8$6^;L@fDwJyd(j4i~a4Gq0c}^MMs#!U^iTjad^ujLA$tQ46f0!uh5qE>J z@-u?ni1XLqp&hHHOY3#Zjnn`O7+0#2%xy0ij8=LULm&3Kym0vrX&my=`_D2pJ(HK~ zB+HQJ6HF+}Qr5RtsrnN`PEYoRkQtIB!L%$YUYRE!ID=&xeDjSpzVqreKKqD)TdrY~ z4k`D_@1=wlh9OCsl4KCH8g!bQv@gGaxp9@IS;gA8LaDpPX5|EyZ8LG=!<5U@*!4MT zM@};D`xu6aW!scIx8Nv@v8BY~XkD#zod*=AF{Dk`e|PE(n@}tJR8QYWcj+Wy?`eY8 zCR-PuC3x%mbgsTkb!rxO=>clzpJrlmlJ`SSVj3oH7E|-TKn(Rv#N({lc zseC$1kpJq={Bf6m{2}Il{@-N%hrdUfBuqc~Mdlv)B$-_z8q742XVn9yq$DO;7qDlo zBFPHVv_Cyk)>O+^NEt@HU!wS;^n-R%MIA3O-12wQ=TgM0G>Kx|Sl&@tNxwAY5{Es$ z{n8~~x!K^EvokEsPY(%HN*PWXDbqA1j$%?$(j?8t1dD*6>`_ezj|axXG)?Y5bAs^t zi!{IWPg!}b&fG8jEwZJDa4kk;qXX#^U~_Gq#?@DeFMXf5-5_)-_>M(ds^FgcB&GSI zEIK7BwMi-ylX*sA6!u|nFw|@(%ufP~Q9mPsi*k>8B=V>#fPzsdxem5zQZD;U&Hoy! zXP#i=(u;&QU!eEw@6vkxJ8azl8D{SP2(?=6z3oU0FtY^H7`8djzrD&o{FB#c1reWp zXn|jTe5qd@$TCbauB>2P7OM!7QF9$>#`*T68S z)~Zx%RgRoU=yrOnUvIK?E2aIq$(v}lW_V?`;@oKtq@q6^llcM9&y#28b)^?cugtV}F4l2&ha`|YsvmdgI zPP@(bUcJhzHyeEXzB!&ae}XiFWFVO$8K@Xmjca+HN4+vdH|!2gauk4G?n4}76h&l% zdziib1Il;)l;DoR=G-Y}mLATZEjQezNw*iUa_ud`H@-)+7n5|>DV6J#9(szYBWIYL zTO>^r9NWTm9O5L!b?hCPl(M(83~b9JjYCY^0b^TgW+xJaRwIy~(}bAaalXE-FtU`z zW2cxtvP2MkhSsgOXubMvI?w)d!q>k+>+xS=?xCk~-UD8wn3O=H@6)88E`% z`wnEtFwma}SUz9o=(&XMM*_BPme{%y5+pvst2Q@Z59qlaYPB-{={07KSDBozQK^>6 z!o8`R76Ej~l zX2HGa7wINTS$p|&Vd#lWjf^qXa^Tvj?4)f~RD{)8+qf=xp=axon8sZC;BdtEF5c$3 zYb`!;c7~5UbPlKR%(`@?g$Bh5ce`E6emQUAl+SOs+eA^6ckYYKM+RV+^yW^`G;LDD z*2nEcdV!}2F~WD3gK>jp@9kNfGzk>D>3d)Ssm zy;`Pv?h&Gs_p^5GBAp-qJ}ck-CvWI$msTZ zBuR>6TRe1Pnv2VA8ton*KDWT!^kkofl_c1f$+4L#lNE*}N39@luD)?{zU2);My1joEWmY7Lqx-yC;bh-}gyLXfJmuhjnc0ZsROY zWSpi@5%1Y6ZcNb1%wPko5W(tT8Gb*hyLkdZ_YnKE+worP`y@vYZc|JMIN5;W-E zxkUNQQ%pSg$z7d?I8(=QXti2-WnkY}teP*bvyc(gvj$s^PB!ich!Qu2Mu zl?ts^i=flt!hD&(`t&hU!{pRV8L|w+Fp0v541*}S`wYMD9LOk#GBe+2SsYnP={?zH z?Rtaua>VA_J~#d(WaasFrXJm7>46z0r|Lsg*P>w_75!_PV$om}rK&|zLpsi-oHTCW z3uIW9&GHW-wq6go|JP@kKI`o0JjC#=tv1-am{L01p*lNt*Jq2-9XCwoAQIc!7>cpg z69aW$h^*yiZ zL^2OO2DCVfT1(3Brf{HV!ARLfuf255>&RHo;#gf<<9lzdF;jx4FD!s*<=LJX6uIBx z_*^|oRt%v85*k~RXBQf^2xtOiUX99!egiLx_~_ai-+KKHUw+{RPrmY}EM#lMTg&+8 zK8An#2}+e3u4Cc3UjFZe%_nD}*kCy-K-2dhrO->ja7q|K6D$XF2jyQW!O3|Prk$QK zevmz`hcQVxI_&kR*Q%61`D-j6zrfm${(#_*{&TKB`YS9w{cDsw=dP@vm^Bm~YmxC; zq?7NZ0adCV`N(b4q*QXb-RO`MDjE}I7s@U{5cEsSmCBIf_J__b^fNcJKaH>(1S~hZ zeD&pJf;i)gPoCnD6EoY+_TAFLdbe;B+j1yX9cE6{nY*uoGn*2u#%#R;E7vyZblbQS z1Nnpk6ed9DC__66m=@!tSs+>xTt_maCbT6<7Ol77#Aj+u%vMN~yUTByF;p}-<7Q*;XT6Icv^LtNX+mmnZQ~-p|I&ZW>6wRE zm^itw&o2(i(NtCGbI{pJQ9nzwhKkHMd7o115ND_*@AYTtp+vi7ZhHK%o=hlvMgLju ztg@6JzkY?wD=nTrf0VN)juI>9rRQ5q%R3ea1eHn^%QT3icu28Xo=-|@q68rCMmzJO z0StnGG>);V)425+oXP~1M?Qyr`Xkt0Y2>*K6(*!Lx1@BpS61R~*@)b8k|a2$NquG> zZ{Y&XC?mM|Ejo#bH-8ecG{=l|@KfB6TC+{wt7hNnvatR&L^|m8@_sbIzI@-u_shiH zHZR_2act5XN#&I`2XjDZh@vo;yeU^Ilq(gSfh5p(Uc18|zI2-#>m9N*f)f*SJ%1xwI;PCmov}I;W?$Dl8e4i`Ocyt z)0F3fWq;;KsX|1!z z>a8ZkJdgiK_aB?$i8FKZJs(U5 zA`6%Uv9`nHe4WYDF7|XnuoaN}(It}IYUM>^rz4ZB z+++U!8l{T6WA@Q!!DL)|_BQReOip~Z%=G+JZcs->yc%cF>HavUxL+qy%x>g9<+E+e zq3%!NI^GZftZVsuJxoPsB5SU*5m6S-LFoZFuZ@Fd-03Vu${+HX(kQ1Re{GP&Q5DyF zTsEQ|mEKp~pu@Lcx{684Gxr~5c4j6Q1so@ZBJZzAebw|{dC#&2I#bg@gf{Aq=;MfmPEU0}s!yc^Zy^fU->@Em`yc{l>hGdhYzN1$5*lKL?>dgixradO= zwY$%*W%2A=%l!A>e3RF2H#s$5rRv#qf?!)YyHw)nY@LP43imHf^63YbsQI~#`d~T` z9Wm+`?z$eexe`;Sec~`;^VNjqSK4%v2HvEJ=ebyxJ=TGY8$Bvwb~{mp^;9%HN>(;@ zH|XKHxqG~UUIMUZ}j-pardt? zBndc@Bq0iWym9q5&tKi-Lno&=cVZFS*&CTcQ;_Aoia{0Ge2pLJlB))a#d!olK*{%M zwc4zH_n%-@rkMH2ud}$Yz=`<@yrjc(*E_U>9%mOOaJ^E#|FyzyoTOly*jYr>SR+eQ zVoW;SfOJ5|?MLd{nS)?5dVd(IR2qdL8_hQV)gQgaa-+k;$EWZ-hcwM{N3Z*JwD70& z6ctAWXw_qRzmn~ZDl2JvyR4<>x>Og>(T*~@Fa81DUPSrmeb@&qok_M61i?^HR4$iy zbQ;5F!=&mMym)<+Fbp|&w4a6K6%#Tx+g<+Y_b>6n)&A((*_zLVqmy{0QchAaO%vC) zI5k(}{Nf~4f7{k1aon@{fL=vulYC(_3%}%Z;R`t3^oQ8S%2m3OCk;XB<&tyaVLeS#p!nK+V>$l(_dIS7Khv?I-mlC^4e0a;6J zOf=@D4Usq!drbBqSVk_}GWh-T*Vd_&Z0O@Jrlz;Y)-Yw=m07)Ia>2%s&0=ILeNKGzm$()NBrkl4)usDcI``1N7+Er=L6;Zz zD>ACHrkTka4=q-C{dS8tuioU`iKB$kKqoCp=*0>3l8t3T$uU`+spFRRK5qQ2D>wMS zIuPANrlWAnvWSxy2Z#Bk8K#cZxH_}K?HAfy{YuE%8&^2<@pr*!u2ckXIKu}(5fO>Gsq6R8VJv@Q|9+>v& z30DOc8q?G3ou(;%xyt7Ci^OmLfZAif!s5yEm|2`l!ux)i51m_}({A(4S8rn3HYXP5 z2zotWP|n39y7C;GfB0XJwb%P%e(Tp+U%NtOdLHMYPZP&+F7#+w7OhrmD3H+NjKa1{ zk_0OZ`GrT8`tK>t=ydwxn7gSgOQY|-I*(!?CgY~t?KYK4h54sG$6L#n37-2h{=_WP zb4PY%kjXD`a62h4jH3P)f1hXOrp2SD=D5Dm;oGm>!nF(*X8Q~($91XKJ^s=s%G`f^ zmRiZ-i8FJ1e*Vpk4ZivMZ9cFVh;Ae+%1c0B$n8@QuLK0v z7S-7jj_r&r7l`xFa@spZ%W@!!V`HU8+w1j)W;fpjY?^T8m0Mi>T8rriZO;GVJbtOX zC&MfTt_a}E{f;Zo?RUK;qTG+7?oOpC9mS7g@a&f9=(@H1TMhi{5|osbr0k=CZZSN1 z3SMzfX=fte<2W|oeB~zpk0kN-vL z)yhyGiR-%fr4kcmhqsrTyn16Dmzc6^<2p7`l+X*>1ke6+;;TQxaD5EZ!Z2;pZi_g} z;N*u0g6@#|uyz=ZtUECm6F5RBNH5(sbcSiOp~SDytBgBUb@beX7<4?Vd<#2$OV_^ zTa0Lyz{F&onU73UpIPJjkJq{N$IyD~HVYr|SU5R{Wm{zFF!fN+zZRC&IDmqgcJ z}wswNlA@aYh3NrE3)4xSP%C)tOKfVW<{DSm13rCzhI*yS#+~a_CT3udS)2|Ca;kHh;aL6Jb;&g;Ip)Yc zp*!y5IL5SWy31FwZ@z%_p}$0ZYAQFnQeu*GbNuK6zwCN^{l{;8iOy0N*t!Vy98L;<)8LeBURGA}Zwyu5S=@x`bgXe}AJg zQ(a;_Oea#QROt131l=w**P!XR1Q)-{%CW~Of8=vHy;lMmDW&QGWuwM8>mbQezi%0lH*X8$rc!@uJ@g~2J8Js)5(3gqX$JGluym;v*fBMF4TB*xt@0NV1TviwVmw1vEMvl%~x704UQQ!X&f+VKFit6)_gU zT+Pg>R;zjKH;)W^9WFn2n`_@_Q>oc3JyT_Nar!`;TstY*#5xKU>4}3l5j{s(sYFfmnQhk z!^fzUT%sr>3?s5Q+&nK*KRZY)GtvKon=@QZ5V|?5R?uF#DJ=|;NYoA3Yr*uD0hnP;AJ&V9<2R;f!ej&1M}s244)+rBP? zJf9|TH5Uc=`jX{Y4)^SOmT#+61PC_b3yQw2s8Qv?8C>A=3Ql!t>wO>j8;C zd*Bi1+kM$){i|k^KEM1+Wt$GAOa>wXTID`&YI#t473r4uN6AqL%KCgbE-GV__6Qcp zuMj<#n9hiPm*K5;&G%Tngi0@dJdQtgx&a|Ls@Oysip*)MLiHA;`o_g^t z_{Efw_M=#FukND##SKL7?~|r3lS1nKJZ-Ayzw26bcLa(oD>Y7Kf64(W>lkZ7t%2K( zG$F{7$nT+5aa8+`y8aP#3KoMElgmSAGTfCpjHFeI7Ftwds`P2%H!~gZsI0x`r#}$;_aowv=+m z683FD8ztiz@apojmF1guhyXAY0Qzv#$k}L@br{JY`lf|C6po_~A!<5MBJvt(9tWGZW*F`y1gxn$g4s#_@O|5Tv|8*d8SPCczeQ;yE3 z;t=a2^0rMYbNt-`_TnUe4WCNJl~~sHQnFAD^gAb}R}>T{HPW-nOz@>dszzaYsCM^8 zaMKoiDw-&1TKC&0u{9e3Uvu9+*L$;?UC3H0KjcaCd%W? zQQbC&D7_@GC&6%KV@4M5&?HOq_^gqXTn8j?{>h1SRN`cI#0R-#8Ln&4vkVdi!@lcL7v)?-PfTV`?Q})A)Z1s*Jcr$%YEHqHJaiLXLGTAhFX1o8GA{Vb6oO-njfM6))w52NG+ z3)Qs`L@)AaX>V*1IyBd^a68pG9$3QVhgecG%@eT@TsYgXO(`43qg6$uJ|kbhMKlXD4cr~O@6;PnLH zm)NQ#w7C0EL2*cADbv5Vk|jp;s*6bk8Sx!ikET(Y(jf-zj0s5))-oK+FBU7;EW**# z2D{DzlWL5A>YECW09_6UKyB09(L#jzx%(-b##eV39M-h9cinAWYlhO0%gA0nGf!Bd&07rbvQ-Q&FMdy}*BsLx`<<9B|Uye!TyU2mda zs{5zA?)@#c0^?2TP^`LCXuU-b5!6SIc;z(q;!J)2o=g4 zG2HnVR|!2=GVOQ9jQNW)A6JCsw7Zmc&SWNk>QtKK@@Vl1iti_q{O^x>DNJA7uyQ`u zi|(go0I{e6_YZcH*wpVqiEHlzj*^rGt*&m-Q(LdL14@z6(0wgFPBQLJZyE>qhry`+WuqTOU2fQ-=n6H0N&BiqYjoNQD_{N?mLI{hu(M+;*p4`A2*@Li!k zX5=AWx$7TFmFd-O`DFcV$HuQV=bYiv!&(S)oGDSMky=wN)Hhq$6U(=2EEK#O3|$aK zMk|on9+Q`J10%kTz+2cTi|%1bUl`fLdT<9(%YMZwPG%5!_01@SRM)=_(EyndlheY8 zXosfKY-@U3_?t+Es_ne}s!E{^YTM%M`z83I4q{0QGYQ$Dy&D<_f1i|pH%PNe zUV8Vf{n=%V2>Kq1q&qh2D6Nlc%+K^$U`WGo#iw4jL)$8&cV~S}W>Dvu%ntPv%fz=u z>MWBm>M^h~r-rMnlBJ~}`*M`|pDoDex0jNKL+3Bt`SJlKs0q==$iVtlp>*Cxd?~se z46t>A+f)|td1pJi&~VobV&n$^|Fz!Y=QAOiSktTmC_bYbN*BW;PV-CY|I_ z^V}b1fpQN7lbwyAPaWO8#qrK3Lnzi#XBAJu({lX33P=^CCG>;&6qi<3dYp*L=8uLp zOW#N+x7dQ1#v#>f_Nt{CPWzKJ|Mp)=w24%@{;`9gR7l%;b^Tn-Nld*g6Lrdp;&5v{ zxifjc+K_X(Lb>M+~3ys?UVMiBo{@g&`VktS+`%di^f*GPBy?z>-Rhw z0sq`-dVQ>^5o#^r4h-^}p|l$fZv7P}=w%B&E1sw2MJ0NV(eZm__mKxjc78c1=Qdrh zjDuaZzg|BTaz5RL?R-5^Ac;I+WFnN!T%@?&vB3wTQkM zQ5oOwsa&`HR*+C_&u%0dcXnSGrMG~GTUsjBlFT`h9IR$Y$mq8;z)firmY~s0Y`%G8 z8TVMPjGD3i>dX4pdB0ZIbjg_%h#!`iR?pD*@iAu|UzX@5oE9}ERL1*&KB^z|rw&9g z&Qq?du*bNG^5<&RtDoJtns@Fm(}beZ(kDBr2Q&cPi%?hulrEd}SPRoZn?B}80Og@W zMI1bf8thvM8KLwn+37?m7-feFvkVV#tNc z4~oC|&1nFhkj8o0v^Gqjr7~hYzTsd$0TNeL>5JRcGq>WSE;P zO`dB=7blR!7<8)Yg3Sf7sds{!UEQSb$qk(@qEsoY7Ks@4kV?D=NU;_kwwBPX66#f>3k`*Pq<(|JibvJWxdDmDD2S9&cSgjR>2M=YVL#f*CMlo|JUn3XU0y(;`}%cZmG;TqPuyzHxQR^_{Xtjcj9 zNe)D*G#gTU?0K?Ud6J9rM!lmsarbw;S)>*$yS3qHjWTJ{c}}5eS`U~0isyUf31Zug z=Qa15Z>nrLwx!mc*au%B9>tonXFqh3i^^@)Ol^4mo%I0N0%A>Cta9)U` zT0YY?SmN|QbB9cZHc%Jam}zK^lgp`bC;BBSLv9F}d8(5S^_{h#t9?f;_bjeSETyDd zgWM-|{nuW>V07khSuEJn^cohYk4#$qkDz-RX6G8*tNP-2IzCblV(lm|2y={BuIbA zGQ?PBO8`&%Yf3;J)Uv@W_+%^Gq4M8W3U}PNn%Cnq=7_mJ-PU{tc!A_fD4tH%stJy% zjy#|}T^scyN*K9v68mXd?QDYMG0jbVJR83->R|wy4j^>4QZ@ud87=Kq82<5C00jPXohhK*j^%(ZRp?DuR1oc_rs1?*1gcF4}?^x}O;Dyl@S zs1X}>lOph}WTo|y0Pv}k%|5N52yr$Jy}^N1SiZ$s@^f|kEudJIn2kUsYUXA;2c;Sz zP+@jVo6>vT8S{h#HJWRpL?N|QVS&$^Ja6$7Gn8Ay&<@+aaE^9_sMQ~K(8bDQB^}V~ z%EA)GQmM3Z8;kc7$G&)^$G>ZNPv=UEZaTBMB)tYFXv|-rl1soX{zLDU9SPa13!W69 zeS$!BN1jyLQknR!KI9sBCP`?v^_?o~dHZi@iL|JV6ou7biF@ z>nkQjM^0uv`_tgrKDm=`g!r>uz=N%oy+I*3!<(A5d!;IT+q=)$!Ah#xa}q>CR9L1qQ;G0qxtwefi&x?; zibO=F5y!SafKL&A{+MeJUULvl43}X1+BiqeOz(nY>9R3eXx;ggQThW&cS9C-$8$Ch zs^8A7+HZ&kw#3u1qx+Q6m8^9SUnnNa57%TrUGCY$_pxw_3PzeQ7g&Gg`T!bgQg?L= zW74jXXw~Uoa3TUa3xQ+jmybKh)b&baYcMEy!RKyg!B#pkNonCln_`nf7gvi&G(knl zYs25mB+oA(oRJn;P{0_ba?k|*)4*@`?dH`{FJ5{Q(o@g;`j1xgp?80MbDvaj+^o`F zQ@Sm6oHWH6+N1#R<2f&0T{{z4yF3v`n;sfz$Sqmlt5lMFJgo$y+{4IB& z8|dGs%<;X>?7)DW{KY-L#6gaWrTr4&OJu-gE|rRACfg$fHXm0fzP|xv}Eh< zxucac94Q;q{aeRT@5kw|X}fcN_eBN=ARn&Q*93^M*? z3dVZ<2buDDf&S}%6W%j5#7lxn+yufy`v}uKs3$dRr2G7iTCzky^*kHmQslmu*Bp~_ zJKIv9V^sJ2igx})cPQszH{1QfsOH0f()!M@i?nuj7Vro{Gr!l7ljJp*a_YI%_%dHl z=i|2wKrH~~nak#wcL&M*C4ANKuIr7_)GlOlj9tM7-7jh;1N}x6%7~iMYTk7eXqwrt z33MY{KsO}05wcfM2-k%)lBNl3`q$%^2OwUEL9kAQ8Z5jSS`2?D;x#AcP5GnI%=99~ zXYql)qKTjMBxJA`0B5bn7DXkgn?~4*iULg`KuUIhLzYa3q9;%9S@DjJ`02c1Y*?@@ z7KA-|QlG<^BByA*R`g2;s4~hewKKyX&4R^5qur;yQgot!|Kng4GuP`MyfxPB$F^&4 zV>GhSXAJhLLX}89*(dxlm``cvcO%qWv+>we`Zm&&2}!$a>+iIpmCsab>}L217CPP= zXK}$%Dm=pdB8pZi1>pg;JIny=S*H@q5`z#S^;oQB91lC6aF9LK?ym4K)~+eHbApMO z{LIbk@Y1gHb;~Wah}UcL9)%Md2UPy%;P#Ema*S*{g;4idY2$ZauRQp<6`hn;{{Q!g z6Wh=(K4J0Z#bB;q%eH^Ll-ENJyhz3^z;cC2+Y}b5CMz#@78dlz={p&jC8s0nDJZf; zk$mw^I-b@D)|r_6>NU1{i{1Ay8FQk#Xz-p-=)g3|%ER{xN*R1pAcXRg6XR}zPmGfP zZpc?|+`R}nPv`Wkh%Lp5f07ExYG$`ZFT=6j->eoNp$;=<1DY;EV%xE&J2&yY_lE3I z!wE?FY$fMB_|bsO$V?z*${lleuxm>+QeCoV4`0!u9jEyXU0N7tvzd`2EU0|rI|hnW z^bvc%_lLQaM}YCf$;~g;y2^VAH2?M1mHHk`D*Ih7vgt#(6kr4gQD(TtLj}Q9-R?w= zzC9zDNjJJ$2<^^(;PZC(=%+Zq^yT$==u#U8k0y4sdaCV$B1JX6`&zb+X`GPkiQ`6i z%sy@XNF4>*pQ$wz%t|kR<1M^rNpoLgd3AfLu&!h0c!%dU5%#ha;$4>3}xAz+=^uHZ6d6w zZa(HA)*1^>^~wEHAfH71>1|^myl(Gko};0m+ulgRsmrSDObmed;e#!B0U+i`E5jF# zx!+XUu`mNBOGk}J>py+;C&L_x5ur{8?wolVVDC!cH~#{V_#oQuD~Td=lUKT|!CVTR zF4<}*plGpPA&RzkH=2TlYQ7og=?t)*x7%-i^IjC;(nEY*4a4+e7U(L( zqiN3OPMSC5>rER}6F&GhKUSrt`gf()U87*+#76d}Djxs;GF)Lag+?&}x{75U+E@K`oZ_QIb|E09|cAT z?rrj>&O=VD2zGXPCa;?Cb&H0xkLw!PCRNv195%G}8p{Ek;OyRD+M*SLCZCAtaJ5Kh zpG2d?@*O|N{yU4@8(H2Kjk58{QtKq6bmK-+jP5eD&Y%N=eJI4f1KR}^7c5PHNg|8uHB zgID+jbn=cGVuubF!DBzu`Z|(J9AWlVP*Tohv*618ll;!lV?LznX_deEN8OJ}Qq?a} z%N>>@T4nVHqrvj{w6aO<6`$Z?JM7cGGZK1Ur&r%;E2nN_na;#waiBaq<3CDN{Ax_8 z{hjH~a;|pH-F?uE{sN?B#yM58LT==lf$4t(u|=z|z2R%i(3w2x?}J<1(erGQ%rL zeLy7}0ZvXb+zWL1-vg3pQ9peC@(;p<`ErWrn~yzAe6219ov zZE@C}`_Q^)jmLY#$W`FBzLTai5&=}CIb3o(N6-X~XjFQDxe=tDL z14LBPm9-FSEFU3p7H*VtVzsF`uN{1;9b-7l<>_la{K$!yDarIVSKr0)Z`xM%mV2&* zaQ7^Mg2N5>``Gy0UF^@e=?uCJ&>W$6ECRZRyHnbc6Qu&Es(Z@Sj<)q8!@4WxU zlCfuhR9)+q&jZcptqYpP^JEzv@dcOf)}Ri?IYQEvN4vXxiLaA{4{bn;`t-586QWi; zJm(BK2|TQY9m!zR2Z2+f;AwnyC((o9c>EX0Q>(O6;Hi^cVfXGl4{w^LwvOJAVAqwf znGSrcTidCIAw^Nv&e#CgnK2(VN^{KNqEiQ!)519lM5J!+JOiK4O#7H>{GSi80P8dP zTFU5L?!EfR;2A9n<&0Q<;Z&f<$Qdf!3DXGo-jBU6>*0%v%C%GWg<@8`rb0Gcr!830 z?5GoUF;k8uA~%HBsjS#`t9>=ZMY;FXBX__PcddsbmK?*7(<=%K>8TPLZ7N9jM?}uc zW3E2>*Rpk0ghY<0UH`gIx0u8#&=M6QLv~)h;j>x0eB@}yxHHxe%}ux6QZ;H;*k@KK z@hJ?@I{`zlT%q&gnA@_4%Hyo50=GTwW{0_Ug1Ku?@`m3nhvohV5k#-2i76Xagr)-( z@E<5*TwC{or4Q}a$Rq+ZvmEO#8Ngm(Z3{Gq-jbVh5XJut2BMQ?6Z6wS2F*xulE_0d_+w0*pD+(JD8dOkvGx7M-cOR zf(kx$75EVJdJ+;Y8Z6o@;rOD?Q9W|~qO`3>bJZ=4R6Y95y{HJra z9jv@TS%kQDY+oD{R0Gux7R;7cbM`8C)Z>rrkYj(lT zinx#Vl5?BWv=fmnV$TS?lp6w+%aJC2hnk+5qII_O^yX`meMc<&9bLV2+#7HkFswzF zO_WZlih395!%g#BRfBnk>V35DWloKA4_%)3vsion9X2g}QT=#s5(2ZZta6*>E*Vmh zN_I;7{%6sMghGR^&q!57RUHD^Qx%5~hSnXJoWo!+La_nM$S$ zPx$eQWPv;o;{aM8){SEk(B1W&ERtp1r#}~N82+Y1CYAYoq=`9?Ztp}7rBFyvENP?sJQN)JL2w^y#pR4< zK66XBsJ9vP1k5O^u8SuX@x_gsto>cF_%rfIgVU94ikoV=31T);FOum+dtC*@aaoQg zcG*#`p`;Hr;RGb_Rg>gGveltZHT#onS6OecIGq0%e$)W)<2)!a7iAb`ij6rU6k8m4 znZ4!PecYKO8hYY>!c(Wf6mN%I4*x(|9q5lJ-&ir(Y8Xt6Z&549VJdeps|c(eOM(Z+ zdWxvvai;0tFs_#mC}ehyOhPWzux9^v&Qdl`B+BcB_L?BRCaFN{+O5p2CUwBOK|C=R*$Krv z(*&4(&hq*zhM8zfyB+ z_nbK7#N%NQ^MdT^4uFT$$;@=BR2lQ%=YqRfm*MyeMWg<(Wwf04-sfiZZc-2|+crfA z($B9b?sxwo>zAVxi7=}`Z->Lztp6O`xUuro@=MCY&mr0AFuu9vvXN#tG@$fpuT()x zoOo1)nptlAd#e>@3OGh0IHm2GO1absssCYE5Y;*ZcsHfwaoutDCy-!EySlUhO7bXutZlGqa#rit z{V)9_8x3-PMNBVX;|S)U!KkXLddV_GQRt2K8MZ+da(I{8Ujer2U^g5{ z&CUm$kZ?ZP!`sJ4qn=AFlK_oA+@htvK8d*P4@DHqiSR@{&UJQ#lWss8{g2_|f`*Q^ zHGp?Fu#*odBz9%DB^+!58k+y-xHnXIJ-iS4UcE`$fxdkLmI%J0nKSw52`Iyl=W_v8 zj_A&4k9QWzf+}m~I+h^%)xNl6KY{8CPQ=U3Q4uNpzPxW+#ujAw_)b_`lbJ2*;3LfN zv8ZJ$+v&4D(EO-)ePh4Tk*rf&wRp&J-;lf-t^Tk#yu~ydl7qfHdyKb5sd_xz5;aBF z=j|#;{r$svm`U{ni)&w1ZDBAMj}0Ql#J7KiolY@JCsf(l6&%9+V%bGhBV@xXYUT5R z>?eE9)Sc(p@M886=3QzGIBjcZ30nCRnIQ^PU1|H#c@Y}rDae>3UFCoqMs~CuG-co$ zaJ^UFBENsJ%3!>7tVBq302!a0-0y>(b(Wb;=Q}aUve-y0z#or|)$3DkJEAVfh>_lw z2^u}LgmDhHf$|jDVN?Iv6#lrUg6~>JYaApgmD=~yTNS{XY4NPhe_wt0{D#?a%(~5- z-TQd_#(Q$O-Rj#hz|&`KeIXm%Y0_kufj4mGtr44|>*^z1R1}YD4*7o!4VIS^>`!BA z-14DMiy@Sw!pz*&(z|cOj{`uiklNBQ{t%}SYbnp*OSL2_Ds50|fvW&HKAW&IVHS=x zWi=<7ao)k1=jpe;j02r|lG8H!VVz8gv<5VtPJ&$t39QZ!oAO+Kcu^f~M1|cB53jx1 ztz`HG5|eGpbq*~Ga@z4p=73wQ$}TpCmlZGFDiap4L`~T@FE1?_nV3)*7ORvd^VS?* zMoV1x)G?r$B@IZ$&PQ<8F-0#g<0qZ@HEg`1O%rZVWj?xiDMhzK=I7M`1o*`>N2Q>q zmC(~~iDrY|A&#;;zmS<;$YAOC9`QBMNy^!0P6`ya`mTkXF`+OI=jl{xoP7{(7TqbU z7Ei?*RPMCc8Up-xUD$)vqdz~}9~+r}5wx1s?Ght+FA<9~Msz9pxJ%+B{dKd4Zne=m zwkobPW6yKtX5S2j??{ltt$EmeOWxe_ctl0VcU|{R9cfI{es=MXx8IvZ77$O~20rIt zK*Y9K;9#C?nhF}d5}Kjv9#R>J>%LsUy|KY}s6n8hPNMp#oNZ)ZiNV?>$>WrKx#~m^ z3!sE4n#w`GJBE~Pmy{>i@v}VN)5SiIa(v9kV+=N!!e3$a^ZSi;oQ3*-ME~I;1r?XZ z@Aasd#nHA%z}-+nR;t}8XSgELT$fZv@F~!ZjKW@nivW>XA1AhD;>&eS#>-G>-&%6o zn?GT)rCshbRGRHBaa&GbFZkfnS3nov?Y#d);>V$wvWe^alU4L58__#f4n~2f)#$O| z7DfNcz-#-uwkUI^N+DaL>-@>D3k-2yYO+eXvffx+Y(R_Illah)n_MB*se3e6B)L30 zD%;S|9G!mT$a~GiF?EhlkqtNM&crk%4@|%(CPw{x_IhNWaC+(Dmq1Th7VX6w1rqKezvit6d%YR~GyXpDsLC)|y4 z%Q36QloR#%w4y*yq;=W2vV6N5eMY%kfYv{!k%i9e!4kM4OB|VkVy}Bad=WdLzM6yO zG4G!f#yrol3>nti-jOlUmu!-Me)B~f6gwv%d|Kav^gHz(Sp>74sL-psM54ZMs?5y# z$kedp;C$ee{o*iMS2AzoX%N}$Q0d}U7-(maogL~u+(Q!Zk3*7`)PP6p?qY@zdTwzv zCvNL^%x@1Y!sX+Ai8egg*h)0Ymx^S4t{4jFmyTLdz)X=5_U$ouV}?CfqXn`;JO8*P z{fe<_Pr3o3{?f6Nk6kqWhQ$wWigV&b7b9(4>r?>6(bITL6)Q+}yy(RIuUtK;WN~r7 zj@Yq?T;YP5aPr2gnV`b|i4@$VQTiJCmJoBw@l$Z>u`Gqt;>esQn3pF+(ftLOJ<(a%g(NYw%xKS+#VQft7kTM&vbwKx;L@Z~W{oaNkAC58QHbQB zP8$$Ky2}73GT;>8cV|A)2>>r_n5Y)=YkDYAxgQ=3j`0(p=y_6?Q~R?#GF>_1v9D&m zHkI{U?3n7AMy-nlj=|3HY(+teS@w7rv5SijV4yerqbUl?-VsaJ{geLnYOzF3Kq9KLfp;?&9wKK3doD>uA-NVJacx;?xSdRwr=EoKz@;q89n*Stb3Q0+(P z^2pV=edqrTS(sD^k-`@3l+LyJ!5A-R0kW{GYR@EFe1 zGsKi96{gu-E5BDIr7Wk3)s1vtE*~h#_DXgR`ZHot&!4Oukvjb(#wyRzO)hPRm##h1 zkfvOn>fyQ?W(-Kamn9y_PB^}OFnN4?qoQp+=Wjdi{)!JqM}He{0{m}JP+v!+<1haW zx4tHn1_qeaN@zS6ZaBS7k_kR2d%i#`480Ri#!UI#MUSt_Rr`ubEw@iC$rb((`Mv@y zK_KYbQpiDrU(^~)IO3CHTc+ilY#4MA+3sDxW=!dRSj1DbyJJWjs8YWSgx7@@`+xtF zU6uAHaR?BONL?&B0*ZgBQA~0D|N6^jQWb>7+QlyP`)n?8Sz5@47>9I-&l{bdrpaoo z=UvuzN!XcO0z%@8b8HVE{AWHU?~(+w()Tvq4U3z?9aq1|_Vd_;NiYf{ZDD zOSnUmbr=S@e0fl$u7Wi69ODA{d$|@8;jW|pVi9IHGVdccyuSQ6aWkkXDE+g&yXU3v zN6Q3&4O@EfWr)LD8T6^RB~F&_U=Z_X7eGr{Xpi5#aR5&+bNFrKzc?pY8~YwC9vJwC zZf-S`BMoz~*`__38vcB}-zOiHnW6IdwDn1Na+DpRJ8p+qeu43P4FG_vXz*kv$0YQ( zp1RO-h-Q+s3y(39M^MIy(WtU)oc{T}#*(85)SJc`XEt~y|>=?l~q>CIcSh4@m`=y!|T3mMdh zbs2t4s^CzoPf!fIXKO{-j((B_=h0*6iJ2H8rZ*Pfb$%zY_xE_6O-Cg|c*o{qh`=4( z>9_dykb0Hlg48>O=Xaspgtjw8Jg2Ffn=)JJ+vNQp}L!Zs0mqoY3UyzVU$`YF3jj z%{wmHdQnEzR<`UWN_RU#u>?7_X$xD2TmHdG@hc12YG{k$53Bj-VZ64r|NS4<-0Y2x z)9o}-6t=3ANN{?*sb}A;JClrMG%yw)Q7w+J^|FOWK zHtrz}q;CR+-N3i(XF~Z)^2&^mJDNCQwiVjCRy1ov74m_5OLN~TBp`2OqkMP9EQ}V# zN}9&NFZ1~AX5-uAC8^PgKkTzT#Z&%BNy(kbx)(du2ROZI`Qmxd#iEcYAz>Zb!bO2E+9LKb(GAFW{U zID`7tkCmiXnWe0^h#(xo9EqGL0jA!?N>zHSoTa!Gf8}oFs@j(mj^CTE{kWGyhCA6r>S{U^bQ3TTVqj zVTL7YZQMd@M%vZz!Z2*Ib9^DBzW0N^`@{ajfq%DmoLfCHCOPnzJHyF*Lo=HFznrd# z4*CL*SUYIoxtFUTaRh}cYMnJAGZOY*?l#{=Ut1Lzkn*mQAXr30T&+SL@3>OU**VwD z>U4^QzLEbv*S>znpojJ;LXmgQs9kX69)tWc1msSS>8Z=J#>ZHa1pR-R z|Mkg(IsvnO`xPb8KGY1!94S<5p=0@qQ~73oCp~N2;<7!Gs~sl2ERA}(&g@TS5xa8b ztgAShD3{dkvS`m7w@PU!T!adO>U+vU2yPf`;4!CD)kNRN_}bzTE8&eCx+uUArPVY% z4{2`wS5FW+j^<;?Vg%Gq)2Z`(fO*en2Jn_cm(gFNP8J4BPWYd{+=-CT!5pUHYf`of zwl0-06x==0Ah%6f&U+#8FG5oy42NapW?expf6dxg>t6+0QHaW@;|u||pv@mO<{X)A zz2oK9w%p%;bTq2!8IV~?NC6SQ+p+jM*KFF(<97@W@sD$4L4GIW)Zw;h(=1zt%oD=l z1leWyjxS$Qg3>J7lB;$)hRr}D-jUOn8U*74Vh6O;z~G28S#Xd*yc+U$&s*~Lg5CnS zlJT$pXyUK6LTp#M-L|h(`;pBV4CE9zmaH;q`b`oQi@^cK$qNM)yH6ta&As!H+L!b> zfnQS_OpOWl@)lqiDA@oYi|}v#0LA9s)NOtq()rpef-sAqY2?)Fh)0QVPSH}8mod{@ zP+DL(v%8RCGW(Qyv(#_-o6n+DrxVIQ_RxoSFKb}Q?ksPeev^YaO zsjgLB+P?*LB^?|4yXPsUBj?KoNKo;g6`7n@+8#;x{$7iNq|k-X_09Y`ZsR-T0`8-w zFUU&~1;3B(W;TkyNn%S*mdzfrB`95eM^werU~uo4rLei78Q1XXzHYTL8Qx;ZRB~o& zvKyqag12gu8gWjlpv@XjQYSc6}O$C~M8o_C|r@ffR zs0%gIc4l(6uk(jhI(+J5n7?>X1SzslyW-OqEpzb1SnG@$_}@IM$>ITwlYQ0nut4K$ zRzFOs{-T;v$(xwyoaP}^f%13p7Ukn9ygwuyPfd}O+Ci-xW8TYWKETP5K8N_XfH$tZ zsK1>(yvoF@(ATXrLmM>iXxlWJx9(e(U`jv`M6oZG8kCU9H@SK-^`FWdLGQuyZGjfc zS~}0afe}~cj%o;qCc3z|$Uevrz1l(toU#i*^Bcuj#0=ySGH(=7Wab2}E5zBZnIM`x zgKAoHQCJc;Ls_%+@3xCJjRs-ZTTfRYjzOm+&{ud&*a3H9qawZ#k0au1CI6nrL-__0 zpTMmH_nD4X?8JjK+pktlVi;4lJfF>aY?Lb3&b~QtvAL$_me1O_Eq9qaF8>khc(r*? zkyzGj2Qn?~goN$l30)qMnM%9xy$>GgOku9lB~BZ4cutr&`%6I!1+e?&59>$&Ze&pwT)4 z{G&cEE({28y(AsF%nz&7frgXe&2%bhZgfz4BVY}S{z_UHJd4AC;G7?XCKC5cC?@Dm8*s&_0!Tkk2qT zq2Ye$Nuc}ixv@C)nDS2cx}p!&sn8aWjMpZSP+z}B)uE~7aWDQL*9+VO?iydnXEi#k zC?9X%=oTLr5jhWPo_TjkWanCrj61i_c(meh zmdsn=*!bx;q8r%08N(aokHm_;G&f9iNk2|k_uN*4JwQkE_zi6F#{3`CM{W-9R18Z& zG>hMeUf?n2Og|Co7!v>|r_mvW{;dVQ=%Ra<0T`JkPlyNDt|d-A3^EOL6H=aXrFpUn zYxb2dQ!tAZUs3K(1i9?9^IYz!>w>fBQsg|>Sb(hnuqK>x-Q^1=BSWGrBPNALeOTk6 zm$x)42{Jzd@#y6l@G}=3BYgbA)Q(ttQVX9lZh>9x;p>s~jzq$7d*uC5*FEgt8`T}i zE01oxuk~8spdUIJL!pNHFa7BAR#JrJv$@tX5{9zjWQnF`7vddr&3;;kJ8wC7MssF2 zI)&uKc}ahE&4I$Ys2?>tEcMD6s>5T*1ZOAkg1kMbeKVL&PtLH(j&|I4wC@#9mdC`O6kNQ@d-A(+!5hIndqTA19K>gWp*S`oEq=8XoG3 zxK@48-~Gfy5HV`Yg8}=TY7uClx9$%z!^AFc;WWUps#^`!GrbOrxZTWph->WkWB?oY2<{k`=^QdbVI)kL^tccMO4w1jap$4>-R z$KhN8Bsw&bo!|aUQR+=@kKBLCv|v*k!D2XXUyWBR4kisdh?TV|enm6nto0!2A4{Rf zjrNGK{TqtOsX4*@KeE6kT4uQ#3n0*%HSS6jJ=O5Am^^QkiaN#1p%Q|736T zA%_X-FDe}L9J&(BPPKaag~eC%dYP#P{tXf@UOZt*ll$2Miy&5GM4npYi5E6DF+tOT z0&ARtO9b24%3q`i`P21CUMWQ^d|4}Js-=sjg107B^=;rBw%1J99g&FH@}ANmVg1>z4pc9(4ePDs0~ z>mxUc{-DS!v6MS0RgSyXK6KSDBd`R-sJ`P+Npb1pb!NmoqB$BEbR?SBMz(IlFPB26 zjk@MhYKpm1F0mrdeax*;oIW`aQ(UDqQa8o@A(=z1YcXOdw%p}C1GV}iit}q(cG&sT zM=%mskCoFG47n<%%TaUpcX$_9qM{qqhpt#t3C6=VcA!9UX1N7dX_^}qMxI6YP*Olr$6^s&QwK@3FJQ1^EMWe=%H0+~g|H-C%_ zj@jDiF;s+Cp7t{yyTz+AVB%45q@bbSKy=3_b++Ttl!@JZF+H1iX#7+hv7LF4fE1{S{v(N}z9)2N2MzbAZB7k@43 z;_U`Gu2JV&Ag~g#NolH#9a+dn!8N6GgX)W-J};QYVzM+&f@EaNKtoG;N3jY|qU3BH zQ@efmcmIn)*9pka=V#F#{(m^{stKd#hFD* zPdMCY`tF1QN_ZURx|w!4f@qQgGYtVhDcy35ej4`YBCj{+lnuWhq}t3avagasjIaf4 z|7w{jQ?LGSfuc0mwI!C>E>LCPL|VFOXa~*4ti1#QNSP@&xZViQtJ&k{GzcUzUVG8g zsYa%xoiPJM!;k*!RZgi4YCZ6RI$Ka<&D-iHU7|po$1NDi^CRkPm8-t%S>C1$e^GcQ3*PtfJkh<1#1iCIr^%GRykq zBK(%<`Zz!LefoKaTW4P>X~ijh_16ZOd4Eiqp4dLbw=$**oJ?+3o1zjcal!%j>rt&l zJXXH8L5;ZLSXEslBa)9xhbl{v73Syb@tVVK`MXRaX^i`jM5%njO+?HBlpgeVZTg>qu`*C>xCLkhOf~OUaG5l1TOotgvb&GeK!C_3H}7oZ)(FjxlvkaVsO`8z$Q& z?>a>HUz#T!Q(&ub49RgskSwBXYe6ecY_7!W{p&;M?4HlM!U!v0|6$PLPNG|>S(a?H zNSHno-Jb9Zj3bD_7yguMc=!PPFHTLwRQe?eirTiH%1Fpy5~ViRjHHG=D$|zZ1rzN` zUn!e8MQ232e=ypzCf;9HivRQNTnQYH|UgvxMIu?Tz`ukiu{$k z$<)iKx_IH8a4|0$o<&E!i0#c{zmBLn#=_*#?ig_N;xxvXvF%r3ShnSPU8l=SSGbA8 z*PFC_vkKgJ>rs4W+esXM|4atr_{`5s&pymfMWAI6V10lbMgYvdzRXO~baJZePk1+p zm3pm?$&SyHe4oa@b>7m%%KJ;sFH3ZCgeVh9jwTPqpHk`4VTZ!z?wjgpoE#=5p(y6- zL-Kik1pZ`Km`l$Sc1pB;;aLA8GGiUS6_-@ zQ_P0!-JijRA+!6GOj{+%;zZ;{NYw|PKMlhiK40`LhoJ})6b(BBUkA0&YrrFRr-03*OF+b1V((&U;0_pWr|4x zZvvI2(Q}l@Z+%3whe%cWUy%J8*r?d-TtydVI4D2YbIaxmPc8?UeGF@li<^i@0R|tKVbhvPRTjyrTIW~`MA0nN}Ghk>0en9ikmndsG-TDme zGjGSeFEfWh5ZmW!CVJ$f5ut}3w!VeZuBXThj1UF^nS3E3H%OMUu|41bqE6c0NqgGm z9{BYF9ug6+RkkHeD>eFG?V_yCnyjY5uFizW41+MI9LHHw=0nHqby4B@0Kn*KaEwVG|( ztq%EOZdK2`3a+aS#`^n~>UrvhN!Bs=;=!$0rorJYIZj@f!uMRhbZ86te5_pD?Zg2{ zu~d#fTr3i9*@@?egh4IB^Pv|E3S1}soz`VLElt4khR>z zs#K_+{r)2>eO7I-8@fezCcsE(I3+U~uv3TJ0J7QalHZ|b8}c1@BD0l1XMwdqADK$Yz0x&0#?-dfkn5Vk%qK3BAGdMJ z2AiHsF}f*@r7x60mp+2(u&74hpGSsewdKGt2$*fSlyVsciUq=O7B^$=FriGTUw_xV2`{U=89TlxKC|B9j9W&+=5`%oUo zHrGu6xB(z5L~|0wto0%ndJ%J1JLu_<;>h~YxVc;9t0loe>5r^tek6(_{Lo|M@f7v( z4EZse@-8QK&gKek~0!|1USrIeS;% zOX{on9w$#<=G4Te9NIO^jx7gqyB>yVEW(b9(9syLo@adSB3|H9bEg@zx0AC?UVeJ_ z#;U#nAS{TMGMUVpM-(?cXz}*H8)x&=IiCEd*>yqAxK}3arPQSMNBXI|s`%o_;Vgp( z(r7y9roI3?REc%TcJ5mC+Sfq8aHGn!Z}Y-PIquDP{<7sCw~v-9^B}se$MX%gjZR2F zw5YACfRFSHr2J)?CJ`EccV?PvGj+BNWH`EK6RA`x@e@&1jTZ~n`aN+}``-Sa!WdJB zF2%2<|Nj~~oV|2|lh+ztbpH&yTH&eg5wfX#FL>0^G?INqQG{t&Jp0f$2(^GxW{7PA zdpB0{4FI|MffZrAyRpa_jz)UeAU$BN3-AzT+ubf-EmziBFhAmU@oUhXjmT`)F)S@n zeeHBQXeJoCfoaZ5x61+}6kt_s@ow1PN|^?r)9r9&y3VK*Fj6Vu`^)#5RA)XlikEY4 zbvj%epQYVyv1_bylPrn=uMAWQ00%*UM#Kjfr}+LGXPIqu87pPjK2~9iZ6*rLl7$FZ z_uJ^I-s%0>k$Mk>%_g%es?@vMlhSn^Es8jE=_>#4!>i;oHs9X=UCM<#hGybcY01#?)G7bhUbm3v(fl z4Ccva({#P1o9C)Kpqg>13+^v3%ZZ(2`6=&9VeY<#%qV(Q)HR z@M_DY)%B7^UF{7?me6k{Ea#?L?)C$S0Jz$FQNgwU7%yDD#*aU^O3K#x&BNOn9e!fL zXB@`?4NS|zT12kJ&^HLW_X2>_dO!VpE&Ir3vv;K#)~Wi;jJK%l%3-F~5Bus~rYdXb zj2_HmS|)Z;qtR@jxhA!XF7{wVe%MHuRuZKzwTZ@*DlxJa8J!BquIH2X8Vuz}h|rd7 zo~sHA3yhii*ji`CYfRR=0Gz%)$MJomL_M#M{t}%^<&|xFCBx%82N|Dhv42yUErUfg z!^AS?T_;85K?Pp{Gs&Ko%H&j2uciL3{(k(%1V4W7JdS1Z(i6KF86LXnGf(Xu<;d<~ iQsxFw+^g8}{|5lSX8Yl^`}E!b00002C=52oMku-(+PZlp!D>?|=s%94zq4KaM;_;0fMdM$-ub0ukeX4@iiN zEL`A45+fO91qcXFN(c!5KnRHEPvH3&0>Xs_0^;N+1O#6i1O$#6%=tgDu#FG*ne3i)+UDHkZtV@_yA+fZW(y zX1co`*R5(PK_M5ctj9F4hGDz7J83)tPiMKixDXj%RnE$1toMwt42^B1x;bJg#yB2E zqCA;WFR}2Nh<*#7=9iHj2aLaIW%w?bEV`7{6yv!NA`?H3rNAJl1+M)^k-U@^E#Ry| zrN0zju;&>@N+lHrgDQ$@uy}iQ7I#uHas0*& zzw6)g`qm>(RISX#(c&}{U#C~|;Be@_gH{v)ZXyR%)Zjd`emz?nE8{l!>Qq7jpi8pGE6zhM`$hwh_# zcS`w^vTS|vQ~U9{-8zR-e;W8sb0Q(Un`8Z@@*1s;mquP?&Ey|itWSD_&S%>oZzy4^ zD={c$G9<%(5-Mzw6iH|Cp-5}uOP_wQ5zc09wsxssr~vapJW{>$~3Ci$8w zm5Ow0-+4-5vpD@YxI#Ex)?a(wUzo+XDWR`-F8PT(n_^2Q^~duBce{6Z3=L7hCf^h| znJ=Rz(DZKZ9SEHoc>5p8O~qq%hJJ1%X@?n;SyxpQ}JNRR)JSyXha_voNsd%il zY@w57VKEh^6;-iiLp_qb>FEN~kVoQkGsnZI+3774w@{kVu~tekJ*l*k6iA9VITlJ5a}Zke#%w@jo1r0ooTe#;3Iway;IWGf4Y^J5N*iOSHKJ1TB{g^g zZ?Y+%K-TOl=w@q|hAJZA6!;R;t4aas-?zOW!Ehuba!?U;1?K4GRS^}kqZL8^VY{to z-_Pr|+LajkJ-2-Bxo0C zX$;LOn@2qNNS)$PMC^7;`?yWEUdGj?F;pG)taN*>A-so;jh1?_7;xQ;rnsov?aP`Z z-5TzG)kr`Js=cB1;U0V>W0TB&7=vDMWnE~#{j4c9Hr6cC&SmXMG4&-M7}#ot?}QVD zkWAF*&e=V3$la}G-Iokh720X+AvV-NdsrQ*Gmf}Dkgt@HOtmk8EYFItpnb9pqJd9J zRhBTAH2ybN`Dc)IlCgwlQJJQZoa=KS)tnnUt`RLW)5{q}EP}Sxvy`g99U0|6b>o}!@hyjaMnQvhvUYH$^f&k2FlQ%VJz$H5qIVVx<5(7 zH4PR@nN|uD(_5MZ7p_WQUtCvKW$SnRF!~NlAgdYrI@&<_1O)eUO*U&VZ+2oe8W@w^ zd@YJk5j|G&zi;6$f74jP>KpI_AO>Q-IYhDF!xutVhxMne@%;Rp^A{VUh$(FRNlhXP z<$zQ@0H6I5wXT)1l*ub4m^yuoL|?hH4mnLhf?(9oLKY*M1OsGwbx95t(YZScdwQ~h zEbrg$DZgH9g9MRz_;|L9I>uP|jD7aeVUFn*Vn+A9o^fEEgs*tcZJpNtj64deSFV&} zt;A8@cNSO>gJu=d{jPho$*;&uz7TY9OD!ry$m4-jjDfqR#)?U%!r1)T#TVPv6TVVz zq}v{>p5b@WK`&3+0256UF{cpx_bkozGpLyU2XHe3BjUztWWr`TPhN#J;y!+p8x4{* zMZ&k;I$H;I*Fm5P87ehzK3q+N)Ga1-ceDhGpBm#RjtJ1UGP~d1ECldLHkp7F-S)h| z>nsjS%9|BHLS|1+$Um6=9QBp>{dcs#KLdPO35YI{;@56YC=EO=Z7@%ienhLcS1}vH zY0FL4Sq#r#d~ntgrWLKR&Tmlw7?JrD9Yb`rchY8%=)cE}d{bmyl6;>hlH&(`AXT9QX z{$V#UsxPS|VX}v+bQ9QX39y4mJ=VJj7H2g|40L-cSg`xdX~B>M?TWtB5=rPXRLSb# zMG6h9!zrg#C3cFME`8I*>(!6W31{5ABNif$ryb(2F|ld)-~(}xg6NG(nOM%L-OR$D z(CK_>hq;~X+!eStIJFa&Bc9O;5tk_m^}*T*vy4!T67tx}%jCIl;Ur;jT@>XR`i;}{ z_?q$VcYnBYi0bTl6Pp+rVCZYnU|6rYx!ewor8J^uk>Yt?=&o9U3_hAMIKIRXLB&eo zSu~F@&GD14!#pI)a(uKRj4aZe7G5%Ontke!GHW+Sx@Vu|+$$=O&*f460H@Ns?j_f# z+=EN_B9V#Ky!_B^U}2hRWYcE25wdv)zcTq0cYR3Ceb(`a+nVbFdv-=h{x&nqTF}5$ z*X-I7QWVOlTJFO*jIY@oSCDInsb%W}BHvf;a<^xs-8pgbX2?=E33@Wh@vk25g|!MT zLq0w23BOTR`ONU<4sQk|OXd@yP0ScJXGP`m?H_{bk=4IJZcLx_6xVp7muEh^U+KF0 zNlX_Xj|6y3elM7O;QXM`%NA$fL!40+^1@;18~;)-ia7%0DE3?U4Y-+ac&@tM)H}{* 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

    $>3Y$lNn5xxcs*QI3x*4`bO!TewKLTFj^?z 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 Ze*mQ8a`^wzK;ZxY002ovPDHLkV1oT-vsM5A literal 0 HcmV?d00001 diff --git a/Patent2Net/media/graph-recipes/app/assets/doc/voronoi_nosize_limited.png b/Patent2Net/media/graph-recipes/app/assets/doc/voronoi_nosize_limited.png new file mode 100644 index 0000000000000000000000000000000000000000..9881a709b15e6b2b715a7d96e7add47d33aae37a GIT binary patch literal 69305 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

    x%vLLtK4&5BJ}C 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 ih&47KP*ssv|N8*9N3MSW$+Oh}0000!I1 literal 0 HcmV?d00001 diff --git a/Patent2Net/media/graph-recipes/app/assets/gexf.min.js b/Patent2Net/media/graph-recipes/app/assets/gexf.min.js new file mode 100644 index 00000000..cf4e6e6f --- /dev/null +++ b/Patent2Net/media/graph-recipes/app/assets/gexf.min.js @@ -0,0 +1,2 @@ +/* gexf.js - Gexf library for JavaScript. - Version: 0.2.5 - Author: Guillaume Plique - medialab SciencesPo */ +(function(e){"use strict";function t(e){var t={id:e.id,label:e.label};return e.viz&&(t.viz=e.viz),e.attributes&&(t.attributes=e.attributes),t}function i(e){var t={id:e.id,type:e.type||"undirected",label:e.label||"",source:e.source,target:e.target,weight:+e.weight||1};return e.viz&&(t.viz=e.viz),e.attributes&&(t.attributes=e.attributes),t}function r(e){function r(){var e={};return h.els.meta?(e.lastmodifieddate=h.els.meta.getAttribute("lastmodifieddate"),s.nodeListEach(h.els.meta.childNodes,function(t){e[t.tagName.toLowerCase()]=t.textContent}),e):e}function n(e){var t=[];return h.els.model[e]&&s.nodeListEach(h.els.model[e],function(e){var i={id:e.getAttribute("id")||e.getAttribute("for"),type:e.getAttribute("type")||"string",title:e.getAttribute("title")||""},r=s.nodeListToArray(e.childNodes);r.length>0&&(i.defaultValue=r[0].textContent),t.push(i)}),t.length>0?t:!1}function a(e,t){var i={},r=t.getElementsByTagName("attvalue"),n=s.nodeListToHash(r,function(e){var t=s.namedNodeMapToObject(e.attributes),i=t.id||t["for"];return{key:i,value:t.value}});return e.map(function(e){i[e.id]=!(e.id in n)&&"defaultValue"in e?s.enforceType(e.type,e.defaultValue):s.enforceType(e.type,n[e.id])}),i}function o(e){var i=[];return s.nodeListEach(h.els.nodes,function(r){var n={id:r.getAttribute("id"),label:r.getAttribute("label")||""};e&&(n.attributes=a(e,r)),h.hasViz&&(n.viz=d(r)),i.push(t(n))}),i}function d(e){var t={},i=s.getFirstElementByTagNS(e,"viz","color");if(i){var r=["r","g","b","a"].map(function(e){return i.getAttribute(e)});t.color=s.getRGB(r)}var n=s.getFirstElementByTagNS(e,"viz","position");n&&(t.position={},["x","y","z"].map(function(e){t.position[e]=+n.getAttribute(e)}));var a=s.getFirstElementByTagNS(e,"viz","size");a&&(t.size=+a.getAttribute("value"));var o=s.getFirstElementByTagNS(e,"viz","shape");return o&&(t.shape=o.getAttribute("value")),t}function l(e,t){var r=[];return s.nodeListEach(h.els.edges,function(n){var o=s.namedNodeMapToObject(n.attributes);"type"in o||(o.type=t),e&&(o.attributes=a(e,n)),h.hasViz&&(o.viz=u(n)),r.push(i(o))}),r}function u(e){var t={},i=s.getFirstElementByTagNS(e,"viz","color");if(i){var r=["r","g","b","a"].map(function(e){return i.getAttribute(e)});t.color=s.getRGB(r)}var n=s.getFirstElementByTagNS(e,"viz","shape");n&&(t.shape=n.getAttribute("value"));var a=s.getFirstElementByTagNS(e,"viz","thickness");return a&&(t.thickness=+a.getAttribute("value")),t}var h={};h.els={root:e.getElementsByTagName("gexf")[0],graph:e.getElementsByTagName("graph")[0],meta:e.getElementsByTagName("meta")[0],nodes:e.getElementsByTagName("node"),edges:e.getElementsByTagName("edge"),model:s.getModelTags(e)},h.hasViz=!!s.getAttributeNS(h.els.root,"xmlns","viz"),h.version=h.els.root.getAttribute("version")||"1.0",h.mode=h.els.graph.getAttribute("mode")||"static";var c=h.els.graph.getAttribute("defaultedgetype");h.defaultEdgetype=c||"undirected";var f=n("node"),g=n("edge"),p={version:h.version,mode:h.mode,defaultEdgeType:h.defaultEdgetype,meta:r(),model:{},nodes:o(f),edges:l(g,h.defaultEdgetype)};return f&&(p.model.node=f),g&&(p.model.edge=g),p}function n(e,t){var i=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;var e,t;if(window.ActiveXObject){e=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP","Microsoft.XMLHTTP"];for(t in e)try{return new ActiveXObject(e[t])}catch(i){}}return null}();if(!i)throw"XMLHttpRequest not supported, cannot load the file.";var r,n="function"==typeof t;return i.overrideMimeType?(i.overrideMimeType("text/xml"),r=function(e){return e.responseXML}):r=function(e){var t=new DOMParser;return t.parseFromString(e.responseText,"application/xml")},i.open("GET",e,n),n&&(i.onreadystatechange=function(){4===i.readyState&&t(r(i))}),i.send(),n?i:r(i)}function a(e){return r(e)}function o(e,t){return"function"==typeof t?n(e,function(e){t(r(e))}):r(n(e))}var s={getModelTags:function(e){var t,i=e.getElementsByTagName("attributes"),r={},n=i.length;for(t=0;n>t;t++)r[i[t].getAttribute("class")]=i[t].childNodes;return r},nodeListToArray:function(e){for(var t=[],i=0,r=e.length;r>i;++i)"#text"!==e[i].nodeName&&t.push(e[i]);return t},nodeListEach:function(e,t){for(var i=0,r=e.length;r>i;++i)"#text"!==e[i].nodeName&&t(e[i])},nodeListToHash:function(e,t){for(var i={},r=0;rr;r++)this.addNode(t.nodes[r]);if(t.edges)for(r=0,n=t.edges.length;n>r;r++)this.addEdge(t.edges[r])}function n(e){return new r(e)}var a=["integer","long","double","float","boolean","liststring","string","anyURI"];r.prototype.createElement=function(e,t,i){if(!e)throw Error("gexf.writer.createElement: wrong arguments.");"object"==typeof t&&(i=t,t=null);var r=this.document.createElement(e);if(t){var n=this.document.createTextNode(t);r.appendChild(n)}if(i)for(var a in i)"undefined"!=typeof i[a]&&null!==i[a]&&r.setAttribute(a,i[a]);return r},r.prototype.setMeta=function(e){e=e||{};var t,i=this.document.createElement("meta");for(t in e)"lastmodifieddate"===t?i.setAttribute("lastmodifieddate",e[t]):i.appendChild(this.createElement(t,e[t]));return this.root.appendChild(i),this},r.prototype.setModel=function(e,t){if(t=t||[],"node"!==e&&"edge"!==e)throw Error('gexf.writer.setModel: wrong model cls "'+e+'"');if(!(t instanceof Array))throw Error("gexf.writer.setModel: model is not a valid array.");this.model[e]={};var i=this.createElement("attributes",{"class":e}),r=e+"Attributes";this[r]&&this.graph.removeChild(this[r]),this[r]=i,this.graph.insertBefore(i,this.nodes||this.edges);var n,a;for(n=0,a=t.length;a>n;n++)this.addAttribute(e,t[n]);return this},r.prototype.setNodeModel=function(e){return this.setModel("node",e)},r.prototype.setEdgeModel=function(e){return this.setModel("edge",e)},r.prototype.addAttribute=function(e,t){if("node"!==e&&"edge"!==e)throw Error('gexf.writer.addAttribute: wrong model cls "'+e+'"');if(!t)throw Error("gexf.writer.addAttribute: wrong arguments.");if(!this[e+"Attributes"])return this.setModel(e,[t]);var i=t.type||"string";if(!~a.indexOf(i))throw Error('gexf.writer.addAttribute: unknown attribute type "'+i+'"');this.model[e][t.id]=t;var r=this.createElement("attribute",{id:t.id,title:t.title,type:i});if("undefined"!=typeof t.defaultValue){var n=this.createElement("default",t.defaultValue);r.appendChild(n)}return this[e+"Attributes"].appendChild(r),this},r.prototype.addNodeAttribute=function(e){return this.addAttribute("node",e)},r.prototype.addEdgeAttribute=function(e){return this.addAttribute("edge",e)},r.prototype.addNode=function(e){var r,n,a;if("undefined"==typeof e.id||null===e.id)throw Error("gexf.writer.addNode: inexistent id.");var o=this.createElement("node",{id:e.id,label:e.label});if(e.attributes&&Object.keys(e.attributes).length>0){var s=this.createElement("attvalues");for(r in e.attributes||{}){if(n=e.attributes[r],a=this.model.node[r],!a)throw Error('gexf.writer.addNode: property "'+r+'" not registered in node model.');var d=this.createElement("attvalue",{"for":a.id,value:t(a.type,n)});s.appendChild(d)}o.appendChild(s)}if(e.viz){if(this.hasViz||(this.hasViz=!0,this.root.setAttribute("xmlns:viz",this.vizXmlns)),e.viz.color){var l=i(e.viz.color),u=this.createElement("viz:color",{r:l[0],g:l[1],b:l[2],a:l[3]});o.appendChild(u)}if(e.viz.position){var h=this.createElement("viz:position",{x:e.viz.position.x,y:e.viz.position.y,z:e.viz.position.z});o.appendChild(h)}if(e.viz.size){var c=this.createElement("viz:size",{value:e.viz.size});o.appendChild(c)}if(e.viz.shape){var f=this.createElement("viz:shape",{value:e.viz.shape});o.appendChild(f)}}return this.nodes.appendChild(o),this},r.prototype.addEdge=function(e){var r,n,a,o=this.createElement("edge",{id:e.id,label:e.label,weight:e.weight,type:e.type,source:e.source,target:e.target});if(e.attributes&&Object.keys(e.attributes).length>0){var s=this.createElement("attvalues");for(r in e.attributes||{}){if(n=e.attributes[r],a=this.model.edge[r],!a)throw Error('gexf.writer.addEdge: property "'+r+'" not registered in edge model.');var d=this.createElement("attvalue",{"for":a.id,value:t(a.type,n)});s.appendChild(d)}o.appendChild(s)}if(e.viz){if(this.hasViz||(this.hasViz=!0,this.root.setAttribute("xmlns:viz",this.vizXmlns)),e.viz.color){var l=i(e.viz.color),u=this.createElement("viz:color",{r:l[0],g:l[1],b:l[2],a:l[3]});o.appendChild(u)}if(e.viz.shape){var h=this.createElement("viz:shape",{value:e.viz.shape});o.appendChild(h)}if(e.viz.thickness){var c=this.createElement("viz:thickness",{value:e.viz.thickness});o.appendChild(c)}}return this.edges.appendChild(o),this},r.prototype.serialize=function(){return''+this.serializer.serializeToString(this.document)};var o={create:n,version:"0.2.5"};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=o),exports.gexf=o):"function"==typeof define&&define.amd?define("gexf",[],function(){return o}):"undefined"!=typeof this.gexf?this.gexf.create=n:this.gexf=o}.call(this,"document"in this?this.document:{}); \ No newline at end of file diff --git a/Patent2Net/media/graph-recipes/app/assets/visual.png b/Patent2Net/media/graph-recipes/app/assets/visual.png new file mode 100644 index 0000000000000000000000000000000000000000..032f004f38f539f276043e0fe5f8cba743f5f1e2 GIT binary patch literal 1094203 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%0DVbq(EDdU{6G$5^WbsVj~&@o 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�qb*=jxxaB z$ULOndKDEDbPw$sftWxIOBjoPxtV6GBdHI^mwdEDVK&opz<}n zyr4Yt0L8W!fi?8fh*xD4E_jMeL|obk=_^fiy7jD83Aoof<8Q=KG$iezzy3HoU;m?1 zrDUZIZZyPBbv&mis6)cK)#Y`%nR;nNw(0a7&(YgI%eI@|dUm|X;}3D@OMlM6Pm3ny z>VNX@*>=?{&g)!Zm8Cn~$dCW9=7StA?N)`q)3UjH0 zlZO808eJ#ia|YrGi=GEcBeiU$z#FIy(J0icjCrN+QKglDLy4QW_Lg8GD~IHKrlZD0 zDMLHu2}H8c!zoXtE25Tib{-3I)nh3x6Lp-@4w~dH*L)_{SO#g#sk{Hv#A=1YW>mgn zRF%XK$&ICQO*y)w^H>+bocUB5JIzTuU;m>V`_^A~A`HXI-UnHIa(Y(H=+ILg<$!FY zmB*%sXoa#qJ+P$Lw(X|3;>$6<9G&sC_I6*!fxnuRdLQ}c{{z+WBjM~$+YYk#7^ARe~LCe9(#m?}qC8H@K0IC0x1RH0GJIq_f)OBq^gRM4n-FgpWE z8FXKv7XsSI~(8gaT0iL(QibPAsOaqADfp5fz@AzE(v1j`RjCK4X~+UFSTxk93sPIKbIbvJPQ zj)|ad@!qFS4=kNcXo?=D=yTU^`~pw?`R{Y+i+|3_qxVuBKhkz#1DL!=v3+7pb=CX- zC-N=Z*FAQQN$h#WX4;C%VQ+N-m=lp8a2sTyk?wEHyrOYVFY@jp}>YS`$_@Q2{}r3S^|~ zNdp;}SqLk_!7%60!JvXc>4?@AHE`_vtYObvJ!U3iRfcgHT0=Bmv?p3o7bSVJB=#98#&q7^NxAh=H1EjixG9(K9(^EKypel*hDEex*sJ=t%9I^aN=|ZmrD8R!oMZ zX~oIqA#-!Hqh5iRV@hx_| z>1CK+zHzb0IkdG;>p&VG*-t*d1)cXU$blK1V|?@gOZVT&@bL$zjvk^~I?g3O@k?lJ z*mT_u?dNzg>v>*-3u&Z?@FU(wq7#eDX8NM9l2Fb`^~hHOD$ylZx&%nRk|~ScRK!&y zDM#UnL(!3pmleIMYEj*;DpW25?W2k4%?^e+n1Ct`DvOvh2cuB~&%Vzoc3yADUN9o_ zJ*?01d4&!Jqow3q=BxC=3}{7ENnmB_G;Sn9>ZH!JWtAaX8Tz&W4Rx%sMoV~2Nd$^K zPnDp_m=F}WAf7MUXnI9X?L10Bua~E&Pp7%gju0Zo7_wX=>(R6Uw{k9D=74(Q@~rom-60hh*UPUaU0un57Mq8HZyOfz02jd@Mi zgNua96GN1-t{!||qn4%g8bajIorbv=*7W89FFi+Ok!T}v4BwjlBW@i1O_`21@aQUo zL5&U>v8d2dh+P|Ul#zKvN+W~UtjA>)JwJ=LmCP#A25%e&i_#INN-~|LDwvphmvKxL zVWH?Vj$>x>0op_v`-&qH$gCl2BAKMNtz1o(8A6Qoik!+h&@d=^Qg$|ypp|t^ujrwa zqV|s78OB`r@#<-#n|uD*ud$SD1cIyip$~oQ3Q^#z`HR;5y;?j@ewyh77uPe$xlH8mU7jKFD>@lxTQG@N(N?E_ z6(%#7++Z?;wi=Tgn2G3~LR*8;7Bw4DgNW%VcE36@v)N*d#q<(q6Eu1yM=Q(a#Vf#D z6qe&(&!|^4%8PjvbeHBBvMrsE2|?a zS5lP~WmN%+aappsygcO+cgiotoIXWay!Y#q+uDrr;r-OhCvmGQgla6-mL1+<-^cDa zWkjK^xWF~#?C0y6x%4Xhc;mt9n_qDgd*1q9W-fmbOAmgB2mbZ{bE;eWk$?YBFYff` zB66umAx57%q8oo)Co`ZM6DUcK;-vqmUmV*(Ze2Oo;av6b%w5`%p41sE7zt5cN1kN@ zXatPbEUpgOylIx1*JpIT>+s>jjK^axzx?v=YjCk$ zH+nSUPphNY6vTiE$=5k~wO~W)3^uKHBPazrq$WPN_9y!|T@mY4QqH}oamPkfrET#< za&Jk=#ri-GbC`ALV2LV<&@R)&UWtwd8#1DGXqSNZ0*SBmmj^4xvQ?b;Izs!5%?VZ(qFLa4KkN$eCVlj0+-FNd@W~E(T$Pb z+S_lrh1;*ai4VNC^!DdE$9A0 z-}$>7Jh+!#@BH2Kq4W9TuiwNQf9uX^aFLN5GU-rAHW9X|C{aZ-^+JgU6545ki5NmU znoN6U#wGQsjwoLcGASRcAOqNAuEioCBu%TB)Fxvk#S>qMY0v^Ny zuSzf((FTGlQK6S!n51qCyL*(^kJ++o7O!iZaTsJcz0)2OGlGho_-Iq@>-7ddmYea2Nqk>`|EjkShxSus24 zO}j^({s=qcO-#{0Bd`GIB4_K3Z^n&>*xn3>zWA5yeB+N@u+1MrYLz&ve(rNy^~zEU zEKODGT-WRV%QyMfKl+(d{=ElqQ2d8K@V<9)|HpopU;Wj0bLTDh^MPNziQ8|vlXt)G z{rujY2f23FmGHq^;542tT=z@-##?@oKm7Q=;}0Gv84ibM{aVGlrRLW^^DjC1)?Z{e z{H1f-;_(&yziut~lQ#^{`Ey#?{d2tcM}Cw~KXmT*<=hTeflz@ch8ZJ`-eM>OB4`M~v$kd-?L zMTxDY4@i^R5He3~SIJyoI+krElM=0Os}Kc!YCEQ<1~QA$IB7IghI>D}!V7-XqBr@Z zU&&H4BtRfD%}i(kohp?05GXP$5`HCRX{#01rkP0!YBzDVv&Jy49D{yAW;4cBMZaGF z3OloK!8TymlAyEW*HvLcRWf|)k+TA%b6LI)m`w9bthK4z@o)Y$TVD10^N6bA8Ji?; zzvUKgy5*Lq{hGh^|9%~>`g^xcJ@>grE?@h@oO`eRUwQxa=T_D~e*8GE{>6XABY%1B z9Mh?66V7&B`@Roy|A&5c`n~u{z@-6}sed~&irRmJ07uj8*o=7f4fupWtYbT-HKwtq zwW=`Q5PeF6f+B{H-0svQdQAsGId_s`WwWGP=vHH*vXHX2{T*TT7 z``AZr{S@0@H$5$}JbGwDr@o8pdCR$^<~KD79NJ3?cQuO8Y$h+8NK504fQy!m8(aV{ zezVF%l-FtAk)nt>QEPlwp?#J>Oih{V$2d7a^Kug^i|A<5Yiq=8T1eJtFc^XgtRAhX z7Zt-t4GS-o9wDtPt7?gXnrnN8P*5_aZ+oD!NeMf8v@%i^3J#?;MP8&lPza(d%P6ao z%vx4PW0Z=L>Hs#ey;^IAOOJh;BD|?;*nQtx2P^=^)*Tmj?DtZ&D7YA95L(j~)16n;iDcTyr5Q{wwtme} zdWl*lQO?wD(ttG=9NG&<(~cs6i2-;!KPjLwjP#;JA-crIyafqqE|hNPTCb9a87i|% zPCp6ea)S2cCMW6|tt^!qk?A~Da8eN`fuchGt$ZoIF4QOj4o|r#nMq;mY5UuH|P z*1VuqoRcMU3&mNb9nZyTTG4zp&`$f=Tm+Wq7F?8` zgv~9$=u-fU24!`7(KZ<)S;So~QwexFfYDwwMczZ_ik|Ju?{bYP3^v#8?R5s)1hkF3 z@JDB)H^&B1%$kX9fkNYxN3Oxjd}zeEUn%gqZi^RIX<`f%rYC(vwvV*}J}%bOUMwTD zHj|VPm9#EBX8V2S2LnQkoE)xFJICX{^B(s8A3se9k*%BNhzgd6X;MInuB_1vij28I z4`UU*UPkrZPXn;+rnfQJeL117IPmF@Of~HZ0XwD~xwG212R`$W2`_PEKTG#Mg;EMX z8lHNd^V4kZTRABrwF7&XFWA9&=!<_&zIpq`;Bpon+8YwA4}SjQE`Kf~7dk54RB0E$X~7u!f{ZTcCMgwab!qwmUDl`hxWDCcf9e(v9rB49a;w@XJNX1HtWP8F?Jfv zUKp;WJaX`~zPBrTA3Cqc{ei3B%<6dg;!b}qIF}e>WX%}l7~=H2qA>aWWCnZUOqwwg z>2JZOf$hy8d*8Vpq4Favz1E$r9e5uAFV+Pr3dvlD5=$cG&>n-> zE;wDb5lrJl(}-h(@{+D-1v=t!SZh;?C6%O*45H96xzl;7x}?Z5l#Uo9(T@Z*k<}9i z$TCYYw~eS2<4TDN(dJW8=?`)R+F)fLalFaHr+e&7xCcJ4Xj zm)PYzLLJbV=HdVFTfFF3etqNHCriucl}h&v)vN=b{s_C@{?q66(8m_{vvq#Y#ohkg zMlKUi*+v@QoWYewcn_l{<20IR#x$IaL?YJcHa%)1l1%uOeld_frA*;WDYvl-V@Xc> zK_Vjq(TbB?+t;L_Pz58slzeH!gqT$kuWF)lDYKDbWuid|)YK_uQDoZUd^J@Vi!n6q zRcNI!+A!$#G1j1zW>l8c-V>D+o_h;B8R;1*hbzsXS1>au$TQ2z>X*B7n$fcGAIm4o3vv)HKX~UEBPo@g|A>%_!1COzNlcqIR-?0Q<^{I8ORYLJW0lVK zDsA27or-Y$>M~|9hZ)SC z^Fi~-caHP2*Y4zzJCAYwo1WgrZN{aXYK7n#S3~@^EgU%ZDC26(s9IrVbds`KrK(5N zK~5oFO*2g&G|!M5se0UbrcR3c)8}6LV&dBgTNGV60X# z(M)DLr%0<-6}gi31EnS1(T$^?0vBs?YjM#Dc<9)1;ggg}5yiyY2aHvW$}#<(oJngh zZ`xWTsa9k3-&|=T5+4|iMVvRk`8whJhRWOSro8Rb%)j&p$>+E5_=o>L?E8!V z2r=-|-}qqbak9Zqol@>L>Cu@i9@bZ~L@8aB4wI28VUE>unNhjIxEeC5Rv3+ktkl7x&&gl0x(JN-oSlOvg962S~dvSfQfJ+x(robjnyETRh;H>3h=nSoI zykp~94yW~x36hc|zJ@4z8R2k3JKQ~n$cPa=2A$X8CCb55A|28_)lWJWMbuFQb*b@i zBBqNi4}(_tSYwmLrs`UKHup;^+z`{0M?jm2jio}O6dwb%tI2GZdXc6-)5gpwo11`! zcL8J9%jeH!!{7F|Zk)hVjJ);_CKd~oE7PVQGOmV{<&d!(F|LNx)tDDudOg;+K zD~gg4J>6@~oJz*@RbQfy1}K_ojLJ~?lEU<)Q@SB*I~-K&bCV(w6JcdEVs_ALfkLc@ zWwRM=u!WSuLx8fbu*P&!p>7`))MHQ9+xU!qZg!EU<|}erklTWVnQiOHUw~@q1o@`T zFn`HewFn%1e1*%d-oz94pXBmu7tZ^@JNUVevg<8Bb#Vv&S5N3}bgZfg$h2p3H4)tD zuDGs4?8t#afu&2jp3R!=G$Zc$iC;P+`CAW{+Mlycn>%TeKjU*<`XZS@ zJh!Dd?}Kjm_=C?gV42KI`n})1g}t|bjQdZ*7w@H^A>wqkJ?paHWQ!RG~-z-JKblM9;aXQs9lXQ zy7ORNVCga`4gVb}Qk#Hm;)uOKoy3oQ=-=>)fAW8w(|xkeEF%T&EM{fwx^{vo%Em_- zQ44I|(Le9kJafg>=XTg1e1hJtXUBNy{U5l6gTR%*$?-1u;4SoSxkY|H8_R{X{_Ved z8$ZVX#_;d{@wt)ZPwXM=xapj%8k)6w;t1v3j`O-NhyIvX|Kr~|ulqjo(ceT}a^+ca zE*r9VU4oZ(lXQQ#mW!FhN>^zhM9J&-q7dvbnC=jUuE+vZ~opPGS#nh-<_{ve9cdB z{do*SxbmI9%HB_Y@SN{g*EN^Cv&OHA8mAb>2Bt`njq~tjY+%Q@IL*mgdEJL{AkmC@e;5Ut`FURc7Ry|6zq!{qhVh zI!0>5CbNlJ)#N%y87W=M@Os^rmL=^F&~V;!+ixxMn*XJbwFYCfa6O0#RFUT?>XJq{ zu@;!T=Qhe}KcbLyGZSN|X2w~Qc5UAA^mP}H{lWjq3;yQcdsa716S*uOFV8D2I{1Y@ zW7nI0@|^E?;In_q?zg_@B8l-|3!!_;G$~G#zLAM#!>KefLgL2OR7s(TN_=NaHzv~= zAu&KYYKp9Y5UE{76-#=i5Y=vwsd_O;^CB_ws$Us^ikJxXafR9u$(ckH4XD&n0B3Eh zL(nzbUy{+!dz12Wnu(odmdaHWnVf!dWz+i>@EnyTgFI)->xxcjm;Pr?d8c z=-*rrU^(=KKV#>qHv0yKQ%y=VGk@-5I^62Yc>&Am>FSH?c^$#UbG4q@C_Oq&1T$$V z=(H6CnQa_>kcdTRZ5f&%22|sEOl}IQx+GJUksC=0g_2f!RC??{6>2O7j|Zh%VVr8l z(WZ%#BAP2ij2C5)n*2TWD>Ys*30z1Org2pgVqj)4m=sjf`>mX#$nD0d5Ywqf^Os(K zZhC0?IjqP3UkQ2*Ongo4x3*5@{7Cmdu*M1;@qhs zo$fYWu3~y*2@@Y$1$maUx;kzZwJ3>ddbTH0d}NS&-}FRF5**_&lDJ68=FLrpHY!z= zOe_1Br<+{wWnz~(u18`|sdZZc)2&(Xw5~%dO~2R2Xc>&&PESmi%-R&0sTN$*WFtU} zI$1)NRIfrtliv2JbN=Y}{ndZDpuhrf{2PCLb_a@1%3c@F{W-q%<)<~#aqb1zUfikQ z7vOR#py|w4UJEem^drrE6^u@JzWUEj$ebTnQiYPTuEZ!ida25^M66gw4veHQH8lZ` zR=O?OKrKb9&&zVE&Xo02q-Hz9a)7rt$ee~>jhtK>em;A`jU+@E9>y2+ZNh=O2f@nY4>8zvDZ1!i+z}Vo^CWWF;LLW$l&OO}N+|-3akdb{{k%W%^G!Mu zt-+*DFJ1z_uu)9 z0t>+2|NJ}L{>yLV=p7Sdr4x7E{Gp-04`JM(0SZBZA2Hm7&SE~ z_{4$GawQTu_*N(<;ZGxUBSu!-Dn-_3_b>c8TmRM{v(TF(QGQF&hAWmuOc2K*9Cf(5*qpgf`Rl=!gE$;qZNpoy30y?@2TpJS`EWGSS z>ZKFh_P1WcZGY=E*xobWd-I~d{l5^LW6KZxFi-u(f5MMf+5F0zo)$Rl|I~-c7oNUX zaCz+D#a;US9=V(|I5icQ1T>?1L~E(Eru`tO(1|+aeqaCXibwx?%$%LUhmZ(enRjfA zp~y0f(Rc-g&1DQMkx?~DV3TOqf7X#d`4{OjoLxP%}2&^OUG(9N4J@5G03-a2QAO7yeUHUz`E+|u`)CSh9apRQ8c_+?q5vou! z$Oj^nOWoB%w#w%8!IPzGgVLJHm%R9$1q+uO4v&Xy=@(SdqqL$5HAN=MT5B`mTYQa* ziXzJy^ad#k(lU-U1gtUGER)KVR*dVCey>N2ie4d#+z>^<(>7l=K#=t)%dw0iLF@;b z2xXEgZ9r0;Vcqy|Kg;Tq53}jo8=kX+WA+SH8efj^<%oLeB;$imp-d7g8p~+kUiuqI z!q0WNP9N08_5A`aigi6l=M*yOlp@4PX0p_Wl*D)KEG035YPt_YlKAE(XZH;f1@xoz z04*PIMC+N~l}|`pEh$V-7s(&j5kpgwmJ)WO)Rk5OPjsGM(Z_jDB$8)E!pOJ|L}LP+ zJnvD~6-Aa|P0pxXWzZo)!OwlLbw1t^VuWA7_hHycE z1)$iv>*6l`9$n{GEm{+moU-2tF&1hoNU3Tx8m-dH#7DO*#}p=)lp!`AF4D9ZQY28h zk{Ba-0-;u3-^ntfiXAPDnv6;5l$t?F+kjHkp-xdr;$F~gSz0A4%f*!?@+@aCGn?Mi zq-m-dNt-5YOC`&vict({X3`@vC#6(tTLQ1zCYKyUUX4$`fRVa>7Ty%Aw0{=R<%qUG(l_$l+tvI95F^h31-uV#1sI~9&jB^gU>y;ywkcqhDz%KHp9Z$%Gg zFWq^sFRteSxVQj# zkMS{is;DW0qn39GqD;-_w_#^yF}*%2E5KwZBl7nPM&hm;oF3betAscWG8@bTX~vGU zQPc$*zJ75%J1YdJOE0Oo6V-MIv6UBS4JI?#Tt6)XtBdOy2A9F^OYx%-ZoEo8T183i zST=Loq^9VT_Xp_y08{iO4YHY#zg82`7d}#HM>d8euJg&IEPDsT%^(JMfNJSNOUl)-|E7#3nOY zG|FqV=&V3Dz?Wr2V-x7a3E03{4gb2hp5+wC)wnuRjw0pQ;i`yB70K8cr=*O+T7}6p zF4uS$3EoijO)^WrxSluQqOx2p2(v;Am|~nd!#CCgq%w7*UX`>%Pm{M709c4Yq7?50 zNXijzb%lCqk?1SY;*k7t8%~Huj}uWgC!gDd9?W2hKG*`RNl}gNc&uCmnCA+7xhEWFL1F2qG@M3>#mh!N{y6K)Bcr7 znfbKI+ZZR$6D3l?JEE%z<5k?s64i<07^AR8VY9p?^SZoHXgHxp=(l)`aPm0${8sGj zEV|c6XE{WPyjl&;MSyv303`&X_Yed1a0$PtA@6q~oeU=EcvW>aRu6I}$D zXAe}oOH&^lF?d2%;+9Y1hRgWX75sRWP?gMtgDk3>sme+85)-=EOjFm9qL+Xr%>_4B zVXeky`eJ(Yd;ymhER@=KlWp`pUBJy4JHQglF>Ym%^2kB5+>rG$Y_7?y#aa>iDXmkx zP$zOpz!H4GTTShJnoaGg>k*^F`{`}ng`J&4(IZ-whTLC_V4j^w#S5son&4_kKfBcx z+{zMexFr9MR*2=8;2oR!1dsD(>eAur*j9^drpOAZ8pc$XwwaTm72`t6xo2;{ya1Nc@&E3 z`WKMj`PjuT@Z3jtWv1FGw0-DckeR;EOkk!Dq;gL&A;A3@c8ivHyYxG%hW52xaCFM z>WY|hE9lMM$5M3_$?f1M=4Ei3;M+@wXX=lvuS24 z{slXzM-OYnvXt*BaOu3G7=oO|MypiEkC5d?K&8l9fXT9y5^0lCo%QO> zn8;|E3YfSV?NXQb{L2%h1YKcyw7Ue5!kzsR5g|f_&SxcVT)KuAA)b##W$Z&fi)<&Gu80|Yi#3VwA zV&YVuI7-i$G;mF$4BxW^Zvz^q0)&|6JjEE2Cecp`3L6!3W74Hm^BLcmkBr7(T*>HS_Icw-27FDmNR6)%BoGj~ZFlgzio;Hs&nHG}11JE5*cmBi=E z!6cuxA;ut;wPuPzhnrH6r1)wooR(-Lfk|CT#8Q1gN#kztyUZye2S&z<17x3vRbZ?nVi~H7!1pMhwQ#;C*{I2C`JFz?)bjv)!gpQ z6JR+_5HNbr&Gi5DHW3z`H@G}ooyJ`U{1~NT;41v;GDbsY1ypj|5V;0xBqh>1dCh3r zuI+ZJV%k`SiT{iV2BSUJm`TK=^kk%vR#f9vsuRb^0mH29v*&S%x^cqu-VwZ?a_fUM zB@*ds*G4QqL+}ZVTmqZW0#b}&YBa5Yil|&eQ0U||7rkmVM6pq;G3oO$CIPtx6+@f$ zG^tRiN)s62$kCt42qCr_m#h%LF;-K# zl5sg?dG$CaSB}vyX2?uV)t_hEo4(C((#SI;|wu>`+i7jY9N$5SyqYsY4s37crNG+|Pf9IaBFJV8+yA#QC$;988Cl%HF0 zX>BU$khN<$f>fF|29rwCM(YW|s}%|fkE_uN6_Fg!%z(|(Tw*=lUHu#$lrctpN+G=W zay_Lvu?;6kfGcU9Ho{Rwq&y$ICq#*0nh2rkcyGW(0cEZ6l@+gHt0)G6;GL*oyWoYtW4`lvS(P#VS z*;YuWG!oSonrh(@Ru`UvvWcX0>!jEou91n#{NiHtlQ&I+iiJb3oBnLJ-W4fMcJA{x zZl?byUpqf=iLOcZfbI(byW-prC^&A&$G z2qj=?QzF$EaZd)BsVRV&-jMBm&4jBF6K{=HReQf`JfuA8DYouF_h;qpcLAo83Opyk zQr9?F?H}SX7EmLS5sV6sa0dQYP0#E;XdGw9X5%xdn8V%k7Qg z*2^Q_|GtcrN#JR;B{Kz?Ey$~aJnPdhW|$jnCbI?BW(tS_{(HB*_vfK6K zWE9r}3&62gDmLF6=^trAW*EQidU~I^^W2}#50^XL#<3;!q-oL0#ag14PUG0^&q=RR zb<>@0`jbGVDHjvM1XxZSgQ_I&r8Fqd$ny^Gl5{O5h3Y05Z5yq)_u=Eb?CNb8qd0VI zm0jCrCm_SbAUlK!$e5HKsZPbIiGs?qWPIcR#kO6T{wyjd^&*+)ENTfM;$4laE4*_p zzy$A8isV{LjCQQHlJ^*_khogw6zTX@3)H4m>3gcj1;djD?y#g@mnf zb&XHJQrA@nTzpD%XgQY#T(tKD>oLX(she&u(MOlmg%by7sq0$6gYElA|c%^_H#z>y_x3T>de@RP4$mUGI=7x}KLP)(om8UK}!}=<`7vgw}`;u@mE@@j5 z*i5T-MT1j2FBLsErmDyIP|GmAm0H?D=9h75M($VJ6X+ju2E#VA9!uQ)%6V6N(YavXU}&Q(>~8EP#1N+5}=m z{E1yaoF-(_g7*=VNgC9qMRkR1xEJpx1Z@IZr8Qa``F%6NG6r1QxJ~pDqNKoe1>>Qo z8arH_(hQ@?@jRVN6tJdf%WKM!ry6@v&(`83x5{hTxyl&PcOZQoDeg@+V(ZK|p2F=f3<Q={aK0u)DbGtP zC{;$&Ir)VcFM`VpcTW90w>PqK*_n^y{clhd$0J+6Gfl9L-g6WAS0BI}Jb7wx$qTzq z_1cJ(LL?pNO4N{6;l@MC;Sy16befjvy(3m-OSoo9htPtH(U|nJwIb!WDFvFy{Zskb znp8qosr;;_DjHJlQT(SryPNmF_j*YMx@l48eJC|?sxz!7n_G|I)~i*{_T^ZHtLH{4 zC($b~>S>FLHUbv04hZ5;TsJ1@0_qaEG?zL7OO5%?S77lN(K|-3dV6|{O&V!h9!zN^ zHWUq4lTxInj9phSUahG{(tR9LROkv#jN*$-jM6yhLVMCtTE0`K16g6@wFV7XT^(bwep_i^M1_yFqgYO6VoqOrZTmVyu!Um74MRR@a${^ z451UXwPkr?dy~|p&Js_OsYP{Xl&wAvdl=N zl3UTZSczDyF)abxa3pk+ohFKT|9h`b+7&fL(sp$lF$(cGHQRVfkeE%Xh|;q1g8(=pT-3 zPIwZwZKC|4>nOf*-v*IOZr7ME(b;ej6ExmLjQ1EHa3-ZmKD428H@j#mJ6h}3gGE4P zqPESf!DNO!rAJLP)96u*Y0?}$t;B6KIH@ezq(WM6q<3i!u!z>;1+39T9WhZ8jKSJK z2o@g#-dkMm$-O1`h;xBz@i@JrAlh7_7NfWj-Cb*e#ns|jGVzR+vwb--6tg~k-bw4? zYSeg0wRntrWr;lOq%KR53Z%-M)`q3U9^;|o@ZNd0UUsler5Z6_i~*C?csEa721Y}N zcY)r(N`=U2s` zhTw$6Z9rwB-j%YnLNVhEJ(c0DM8{2!kTn@v8zK3Vcd}NKu{M+AU}AEno~v0}shAX6MNV7KVU+Xxkk>TO%VGPuLWE>Qtd`L z+eq~VP(-tmH5DK`NqwxkRsM~q+PiM7&;v%jNxGGHjuFJt>eOeABB)y8? zv=xpX!ej-DH@_QIl}Yk1;9gf5$M+W~YP8iUYH{n*BY-WJ9%l8v&65K^ecp8$a8->m ziqT5V>at^QA;)`B%G%td6Ocjckd(Tf7$nuJ%fNW#CFLqTN-45jKKp&eo7s8%b|U+P z@OKrlOsxXJi4f3cyz9I0`D^=}u#?sVrL=&I%`w_0(m!34nY2Kt35ox#%L!s&^y4=| zX4a)9{XhBYg?l|QGWzM)g6~en=&XJ&1gusY{~fsWbCLaTn0`IiUH!x~U*im$W=Fi~ zb@vd0<||*j4qZp~y+v`!=j3s#*Im0#1+BBD^SIm7lf-OUHYpG1nGmpfCgf||v79w& zjcLK8t@M}%JdA)!HmL^LCKYORC}xdKf@)2nrqsAvk!5CT3`zqmODpBN5AV+V4o=A2 zP70;9Zb8i&jkS~4CJJGB&2D88>Pkwbof0ljgCy(%OB1owm2dx*YKvSyzJI2p+YvSO z=$h9sdduHrF2iQHC~YF1aIl4LV6z>bijkw7(a0zh?W0A@g$zj>o3o%2p2KUaCmkz=&t z7_HQl<78VI0;)JjjAdJ046edgWBhnTC`VGVb~SH#NJ!dYxx~uoB;#_GItf3m$+4yZ z87s%1&alQNuu0&f^s^eRjNWtedSGe)b`vo(7v_21d$Rz`8B39;KUVjAar*C@=0>Ny zt=56p-~3%-R450lyE=i=nzTz>BcPDk$wi`yX&`9-p6SGwn2Cwgl$y39x9_Amy5(F< zn<`Dl$IASfw#jg!3Tw}(U0ur26T=k2OrHcc%@$K{u6Ca5uiMoLlcyserPLHJ)bK&p zG%20Jmt%Z27Pq_@E(kf;q&_ZHQ(DfY3ivvRkhMr<5=a&spNi_@uVm}pl*h#Y-< zJL6Tyc-2v^da6}NwJJ@F-g~J!1xZW1bNISuZu?O#d&v<7vle3%<;b(TTr(buQIpN2 zVXz!I%3)1C_Bbbc9Eo1#x^sbY?3-yY(!&&J-=8Rolb$Pe#y^#hTdfqy+b1+->EKfj z)Fe$8DS4_|DMe;;GLvIXhS3>Dn-*+zs-9&$TMAtPk29_DkNx1&IynK8H0Xkmy{G^4 zzu5D2e*cOuazp=U`@0`{&AkAeytZ@ad|FGRyS^!Hq>@Xd(h#jp#Ig30HI<(PFgk(A z%E(V7_pNYECoxb?-&F#L)yU!NfVSejQVcA`z+!VPqUWTxj!JQ9)t}6lG8UcXXq$DWO=x;q zpV{6#vx5bStS>TuW6{b;^kQ=|D^W~l3v2?JIcMm(XDKC$fzeOhboSuz)31G+XQ*&N zU;ggD-WaI<{pDX~mmL$L;qPs~kL!EKQUnumPEzsM!R}~uCoM{VQWRMN7SWwpYdgI@ z4KbT8y3%M~kyy%K8DQz0J+{-%NW(|=n7XhG9j-*VwHZ^)0k&CMnu(*Irm7==xDW#C|Z(Rne z%28K=(X!(3V|!XHi?J4)WfZ+0SuOx`@S!WHD^IyvGhX%7`I9InI6THXO zbz6yQDrU++Q5Xg(MKYP{G$<;vTvWJ|w3If&bakLAMK>c+jx;?MeZyeZQuGaZVUjLM z-p6F-R4$jIk1l$X`BTR5?sUTj1qUA5hN~nBN^&0IRq9AJ_Aszyg~s+) zaaDzL^`vvS%{(Xby+=!ZiCBW9A2CHEHcd8^GQ5oNkVus@>P2qneIz(=>G{i%fJ>Ge z)IdCoSC<`Cwi!QjGxuEiMao+9@_UBl^8>alDNK+rTp5GTa*WMT*7D=~dVKN4!l&d} zUjQcW^NM2`6eb8;fM{{mq6}5oOgOBXtl`q|!s&tMJZD${y9uWOiJ0W=$ z+a`60k;%-W7*Qb-RqSkf-^%M%cZN|L1x&h=x&$grD{Q-WZPw>+f1J0z_DZpN32E3_ zI_V_)7IX(>Vo>rys7bF&cWvJ~vpx(RJF?6WB4nAx`>NGmRCSl5ZSs26{@0F@r5V2x zpVp}(_?SjCCBdAV2AQUU)aYJB`_jzsi5z}xs|*b*eVVD9RJtY+)>e`CEyl`czwPpa zB5JEjjIm@zfw8u2i!er_iGz>s#Mh3xjJRZ15mN=qX0mZ(jBO+XN(kIqPB={oy;XLn z=u2x+@vbh_co$?kqPmu{{v_ja$XBjZgg7L>tjF6Q?=e>i5Gi9(S%J0^#k^%-4_y?P zqK_&1=putcPo{2anGi~fiefX$SLsPrMV*H1j1ki4*!ndursl<<6?*@1@^3tfs;6tV ze&;;ZYp>mKbMJpsauz`Pc$%{9g;i3b60Z^2Bx++3}6Df6T$5$Y{G_X?f7f zxqkJ@AL8F!dV71D|K{;GwAYWF*o3vd71aUgPC44@X24lY`7^QAoQ04Sv9TL%bSou| z@laeJvQ6f~H;}VIJSQsPH@)TxLX6VJL%;`(R#76PAW=j}!3zlMdH}(0{mmlRv-*h!gD`OtmyTog6xP&|I+Rw4Y8lqy$j0H*o z!;}iCcsiBQxunYt5lV;C5EX0-E?ts0RbPS+5ET(o@-}IRt0bn)azoxXGSerD(9PyL zi5m^pX6QuLd!^7Zx#%~}bM0I@saAHkGK|gJZhf>7V9^Ft5<8|g zh~_;M*@Y#KH~ekqx!sIH z`FPe5%$9p#-<#z60}t=!>K7hh6f*wS<8R<+79QmzC$GY${K=Srwep#6zPAH_i$UU=`_stnNgzhx|N6*1{PN#;MJhiB zqEaN&I06%w2c2pKL9U=%*x5*>39tKs%jxwjCl<$)wWr9Wsc+}DS-$n%16+OOR_135 zh9k#oZn%^aC&z4>%en3Ldncm83oIWG?b$uFQA|^DX?lx7swO!nOBA)7BC2 z4npcL@|{S_SVeC}%GxG5)#W`Sug5Beo9<~NVV$Cj=8W;ht25rUS9;f)Iprpo2nL(U zzs907Ntu+f(tK-diefAn8Q-h4KC2UeaxmU1Xa3^kX;O;Qlz#WUMar`qt<_!7KepyM z&od=z4sJEBiM{NU=?#GEgQ?CEuCzouZbotF$Yx%0^*)@}WGe8{#VcE20r=dPUxCqq zXs5B%Jb9#Tld)P!_@={z-mu2t*Rau3CD0&e&US+|#zkT$HR-MnYD(?fTtW;GG`d5n zy#J?OD*Yl#qjW?gc8gJIbORh(x1E(b*;54F0L+Ag>4HqJCtz~q_>ikETWA~EZn$nI z&N-a-?AhL9I2^Kga*53gvwYsM10cZN2lR0SsH{1AJYJhuOq{g z6;)q z*F44JcU?;GP1GYjMAoXwi6j9Ysk+y2a52(}x?-z&i7h`R-|Jv5OV6)4ucMnL8Q%_^a3b{*o_5M%!R;=p1<$ zV8

    KSeKJxb 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ʟY+9*Y$Tj+P{i=vOpz1 zxlPq}f)|~3eK(9%gw7P$-(@M{BxlP$R{kLU=e;r7fJ$7W64!7*V{AX=(bb5)e)c|n zFU`IRVGwiP6<0987EGo|4^P7y|Ltiei=?_iwbb7RM#dnVZ71ofv)5?c`{ZZ2{=yHR z{)|WnL=YFCwsR2&NT(-oSx7KY!PXb3^bPUgvtQ!stskJjwuC#M_Hg0jLk4Sviu}f435R-JjZ4aF+P2Oq28se7~V)J@}sV>*2j`-+L=W4Loc!K ze|?f*U#vtj@Nboatb9ARxqz8*}nK0dc+8qgdf7CB4=BS zw?+d*2DhM!E+j&WYj|yosgrA4a<^3AMZ0&qc@7!PJ1Z5|$QU6Yn-;j#-%o@NSC`0= zLj<6w{m(8D2qUpYTCXJ<&Cp{Jgw9tGMAqAzV?P!PmuRvVOE?F?vJ`tX_JwOh+6#;4 zL$ao~aL21ODv$^*y=XV}U_lt^_ZRxxxrKnR-+5sw(kIX=UnAh63}r$un2j=&3;o1J ze;XW6pB!WIO(eZnxalgmI+mW6~?=J@(?+P#bQuOqNK`2yOvM|ppKi~2){6< zCZilhBw7;&ek9>VxU|FQ3e3`CO4{R~;y9m=Av3Kp#!{_Rx~CR--FC6huCYeD#1TZ7 z`=qr!yz36G*nINPy2Y1vQeC$NXB>xL-p$C8rNx5RSjY&2l%Q1g-wBg-1=oR(x}SXf zeul4lS9canr(PrvfP6I|0erz=Ha|l&u!MAW5@F$RI>GY6HH2aJxT2ZVnO;0b6qcw` zC2#>jZyDWKK&lWK#Tb*(s#uUGiSIw%HZ^~gR40rMtUk>X?zR$l6(n|S>0F(#R$}6j zyI6ANyNkm!9Rhzx^ZRIa@I2pU?7vwX9uwV!N+yEHL%RJ;*p_;KHlDmH)e7tJmx7 z-@pINfqbRH>eZ{?UeUjYuuB`f;Mt1S8JIl|q_`q_-*z`Xx4Md~!{#m0HU~e} zcxff;wr<;UCK)`~aa#Dxg@Gg}K##S~2h9Z*x1juUi41m8y;9=IA|N zVCg%55WUc3|DGpUea<$5N)4U)ze$nI5cUmuXURz-<&WO`C6-+O0pH`(%4e~@vD`D0 zd8Uax`z)2B|0axS9C;Z%&_|jz8R}j3%7DjclBr`v151!WNY<#6IZYUq2vpepTwWo_ zrk*VD?7oK(LQ;uq)JpxVUV83Xy_QyZn-IQJEL&(0R3l8YK~SmTtYz|{Z!&yM4iIqM z|MVBRZrcy?^h*!2X~l&FTLEzJOaF`N>J1EB@D8w+V-MWH$aU=?z=L1-OM1@PM&G#? zdlt9@JdSU_lOWfeWub^?P~X zMGk-cGxT406~mX^c-r^OSj~KWn&%Hb&dkC%tCwtM#gg^(RtDeFtI^p4mQ!s~%GX#! z@b>oB11~Kgkh?XY)ApQS*O3Y1ZPF&URCg3L8rPli;#yW|ipqdiO+ZHGL*7z}aXIM0 z`b-uh{r)W;ylCM8jxea2K~D!h+|B`^#^ynGs$#KCzo43heC%cX3Mj*zA+Qh(SoEA1 z{>pw!G-OB)1U_cJ;>afR#$)MkqhcWPc{4Jyz8@$P#OpHLqC`&w$Veb-2G>*w=a4mr zTl5(-(kR4e0<$4%MS?w2fn#RBR zQ5bp+jLv-0ZlJIZw9P0*QAaLI3&eB)l|0vlg255p>!oauhFZBTjb_t>FC~ehsJPx( zOS72}1d1q(x_#kupj_~Y5f6G-r@{5QtVrs0; z;AjP>H6}~E$n-c-=8-%9k&$=(5W?i0M@sq(5WpIXibAZ;5Gpt;;F8Wv5cLnE7v^x* zFsbJm9em}pO}#KjGC4+N^`_HUnjK^o0uQE&62*?&AD(=X-3NEDe%V%5kDMB$Bw2$; zci+ii&r&w8zO0LR@+Uzi|4dYVnZ;%)7=es^apLiLC?;vJu;&^2wq6dvb1y&4rWF@4 z-6BBO(voioMLB3|>T9jO?BK!i?>Q?cKRqMJO z1d!`iIz%y^DaZj1!V5%&!{%BICtSWzImqCJ|6v)}7BF~eE=U#Ntn_B20fu zyfhJ{mDnUdxP}f@HNK@fmA#fk-()65w`Lx1kuVAw8Sh3kQNbxnUqK)ab=CDYSKADSOTgUEGk6V zVkg6P&WRHc7^p{ne3d9Dr-&@_(}h?g7i0hambABj$A-W}#ph!qjdBVbczZWO5E2sL z!Hp6=fKCXB&XaVDOgHc&9VrMz1j3TKl$Z!96~_sc`bBB^pP0!fx)oTU_a z@vSkMIEuaYrLa18GA_lpu>-7h>S5aHxW~tgR4Y}|G{acS!eSk541ImQNU5k+tHo%h z*=%BrrBsSfC}adsGGuz;7}gr(aTy#!`QEE+p-xYwRA^cbzA(q&Xax}jjNg4b%ii7H zRDI-||H#mdKZwYD9t?SEtj`qzRf>Ga4QDo%aXKSgoG0uZz$OVZ^Wy|TM6EW!CCbb5uetjY6-o?xLq&4nAUrxN$Dd}uw(ht|L1bB@C@ z*KBR;M$#P2^i~Ghvib^?@@_z#S+BFv2}p%CO&~mJkeiCj^liPI`jLG&tvPSa6JNX6m;d%ZvG$++5<{2YKsGf_H0(z?vQ$AY%yo~v9>0&} z@4MxsBd%lj-+@b35Dr4`mJwuW&FL3Rb@I=&Ikum}U;S(PwqC)~cYc8CnoVr_xnF-@15*i}&cMY1F(`mS?bjgT;Su_RoP zBAv>e&BiC=7U)Q{olQ=lrzOrhMA@Or2AYEH&3V2)KZnwir6TeT%+BY#h|mYlwHlUv zhJ}BT0zXQ^f$BHdIiJWYg+o>>Xn|dj&;-@vaCJeDGdkWjEJzQQ(K8`ZYGmx79zau~ zDqf&0j6fKH>^BH45cL2VoR9l=$`?gS4=9xl zKw50*!|6gDA%#LHuW1p=p@i}*hm`(037JeNsge)M%f+-pbq2}8w4|sY=mI~P$*7jfz7oJ{k}M&P;-Xx!uq}I3G2}O;C7+HAMF3CYl z6vqTXKxQb)+Go6q9{a4Nqzq$QU8gH;z<804vg<+u%}z6P(S=K zl@)6_`rKY>vPtiT^I4cl=oySDRYU6gU!bylZ6OW?ICSS{Nw;mGmUyvdD-$N0nMIZ= zsK^5-)2Jg$r_UJI^#z>HutsBa%4BnrzM++r<0?^j;(eWS%ssyYtR<-S67>!c_Ya@3 zZe^h{%Y9FM4x>|s`j(?q$kKsTtXi^(P=;sMgK+#oMun^zIfs#fRY)mGvy>e#+{eMG z-7H_S9;HGuE7|wxA*S#AGC|2u8d-7DeT6;!M16zIKK~>tj99*WGvD6%H7-B*-8}g0 zmsvG(4yshaWGTt9!_?NC!?B0HM$h{5a5xrT+(|sNl*;n89#o7UAt;~d25THW$gz7K zqcl7~-?p{X)@(khKIepmsOedw=J;V=`d|M6tf8`E9bxYv!&mr`RMlMOa10=+Vh|de8NCcpyYCWiF3tX93YY2ab!JX&>%kKORkg^fL)I)(3&etNhZX~w zU-TP3Cq$h?QGQ=v23mi%+lnDG7iM-N4bQB*dpJQW%1t};+Wiprf@kl;S3Y2GaGM6EQ#8^XI zD*G{w6#mRwKoEo&>${DLGDUeZfYKK6c7~y4T9ayx1C$I1l+S@tK|q>iXk&`U5J0t3 zrd%p{t9F`V@*q4Re1KbeY=&sCTb~jJ5l_8%KWj(3-AKvNgOo>CuEtnH+#*3-rCjp`k;jjGY?d&)a|c1Cii%5=hL@eR#rb60%ZH!g(Wk${ zK+g!}QV&sBV*T=M4D~HPezIJ!N3RCJbe{CI#!=Q8mJP3E)sjspCrFLuzPs-w9h_s^ z54<1MGs;unIK;6pd=;e+Qdzz6gx6jg9z~TZOg?rG=U(`3W*4VWLh$$tce8%k`Bavz zVeFg#NZ-~=d@$XrjbI%MFYTm%>*aY!o?-fl2k1Zl@~-37;V*s$mz3z)yo}y+wzh4` zonq^gd~W;x=0B0u=cujULRjr(=(2ZGS+TC`cG18vGtWFsdFjd%Mr{Xvj72`p)?FyLRnjVq$_U%TBm%W@hGf0Wn989C=+>r`H?6 zWLd`Ko$^Zil3sRugL9y?%0pk9i$M2HbZnI zrb;1DLSUuF<*Y)H*^!^9%fJ!FFmSo1_o5U6JX=t5o~@AN0bcp-^WSMo&vb->pvU=_ zCIzY_Kta&!pea2&BmHQM)aSK`z~Y+DC-5qV?DLs0!Kg)*puDn4|MfHUUOtNw4wr&m z1QA$N)q0U{#aAMTl121s4_uncyNW6nS27-agn155CG%G4a)wL-T%d8~#4ohoNLAc|wkQVh!8$$x6NOl zym|V#%eug6{=1R^CQE2E=CRU|CR0>bCyXv%LLf?*G-RxPn6Zm0EV=$>j=tRBp+EX6 zFaG6!JD~~M=eh{$kKE7t_xvzHrRR088`yQ*A9Cxhw{q*Pw{qLACNP%&4|m^sD~xTY^)0#W)?17FZO^aU zG1I-jeKQ^RJ&DfcY_>nx(oU!T(1-r=l-HdOyqpaf=-ghs?H3sbwru${01yAc7XSKQ zqfTdbcJ_qJ=63FY9iL`L7qWerPwzbO@n7xhJKgq`hj$T0|AwilDfZm+b#~qM%Y1!m z>PpGT+LXeqfjtH-5$wWpdB3~@1{8+`|6IcOUV30c3AWSG`pAHcvOYa3KvT6`b&*%u{ zM@{x^d9eqpYa-BjB za3YJFQ>fTMpM$zUL?9!9n~}(}Lo7-t8$=?DLPD7;=+U6Pz1jtav2R6~x~HW3wr2EI zy?#cfAvVf9d(wz~BX(dBPGQOkfsPB%rSSG?q5SKx(h`c0Os0e)_JxK5A4rEK5Xyge zvJF0+uw*v%U`66VO^!~b2#_KmH5pOPDp)MW8Y-nK2%r68obRhD#c^Aho4bdUl&Bym zx{MYZi-4e7DWjAk$_o#TF)S?9iQ|YU^!D#crQ9jdXrCr`*rqGhDp{KPtR8F0vWy_` zYz;tp*&y|U6X=;mf}Xe#@h%-$#a&PQ9ixM5+uDVogtZ1cH%EE-TIQxx)^8igyS@xE z^v^XpxQ}PdVYW;M4BU73+RP;`p&zApj@SY>*;k3^~D($rpKt&hN<)qBcxz-*=w8o3n9F2$90VS z3h?DwI^oNnUU6R%NhnK1p}-~$dis`fRqyxn{K3b#>xsW(`Otc{UN^v=!w1-X;0exI za~ZoguVyEf!EBM2zqB9w>}T2X^FKyussGHD-QWed=g(CLHm;_zFwMcg{0|(v?@JuJ z|0{(~3+H(0ul|4FEHW+=4Gc4M<-6JYslR66^3|-q<>r&~5)(%_@DHD+XY+-O-ta-f zo<7d`h2PE@uoR?3s(>Iab7bO0UK-y`J(*|I>Ps1=M*XE-jDP!1L=bWQhVvMG&o59v z@FMhk-Ph=iAA~au#(Sdxd_jZ0w#~Qv8*bU$J(66TS16YNMla&-?fdxYtNPh>lKYo( z2IrG^kMW5cO5OK8{IRNhbpTk`7t8dI_(7WX#*zrj5`$up3*ZkF;|AC*|0zdaAJpRUhS+Fmy z=ThnEdDH#|fA;2I<$?X5?b&=d}%Ji{fA2{%PCV{U`a-ALB? z3>RyRm$$U+)+Wz+Y3kH~XooO6hh&xG-_42y_7NO6k-5&L3AR|io7*Yu0OYf9#x?#nxq9Hn)2 zDr-~hw1TQdmch+<3pGx9HmH#^OEv33&|HA%*U0(6R{*2|u4bTY5wnr60dRt&Pb&1H zXFdkDX?m6m?<7hi587glFusonDX^7<%=D% ziCY141$E|V+B%h})()hTqD`K)gtIwd%}k0Ajwp)r7U6tt5RPWrL<&KvR4y#r{_o1r zOq!I-CBhcnD!>@c?CdO+N`-Q{+#VqnBT8`sQ{Rd~G{(?O5`=(qIUil+Y)h$BYL6Q_ z&Qcfm9wl1ROW0E?&ZPGqewxAFQ3mq#*0~p+rm}Pu_xy)H;-=sHZJxSsj0>(CW&HlH zvgBHSww_Lm@vY~-%*E*lBRBfYk)vOGlBMrGpU&<8=Yx_8ur&VQ*XUWdg}qPRh1;@) z^H*Pa9C_g_zSY&6sIA`g3IaaE)WiX7bCH3i>j~pGmgcq12J*NjW@k(RT3lw3(W$9) ztF2G&4JEeOc*U0G#blm+N1o-#)Jyc12bozMXYJB$EF36tX#4;hS8ZVK3wN;bedjZD z)paD}hk5jue(;0nt8u6yT*rFN4eRiY+4a+xado&(+H9&!%-?24lR%+7xZlreKy`p6}AKNVkBE z(XHGUjk6Ae1ue18U@^!{VKKf>$oOs|GB4V7k;bO2W@+0F*=vRAMHZWSfv!uv?!{$3 zqs1BFQ*z4=yWrz~1t5AHXuQo@fe1Yvl@+gdelEYOpM52(*2m*)g%^;HmX^4xg9}8JWU?X3kC@rRx z5hp!JAyGk2pC~Xv<^{V_qGXVtakeHio_#SQB~qp0aw{yxWyJXyNOYDV%C-)rGi5h5 zi62u1zJ<4Sxpf9>EnyU5tft;vq*AUBhPiVJhc+5x3~>~DCZ?N_r`c>GmGoa)A@aXF zi`E+JEKwK{DAfgWx)_;`FTNDQ&!vx}*k_-5nd*k61l9H#;DgV8nX9+H-!Gc`b|cF@ zJpMob2iN>x|CZg4Pq5+Kh=qeM(s%AfxHRRC`##OZc7)OQ{3zL6gXY*YwGB&8SU7E# zfwN3Lau+Hp^DIZX_VOR=db+x?$mB!cVDR!APMQ7+uvnjA^3ZO|@O*5Pms5t1jtTkE$U7vr&ao6d#MzX+DFFnB6)PA&U63?vR{Dp%Y z{=%PwkgsZ=A_&>`TYpAvjkkf%)u-5Z?0LraJq0iBVOcY#TJ5K{;XIbSxaUNBvoz@P&ux}UDRU1#fukZ5h)mWroEqHk?i~H>CEaT(j^!NAE*Vp%|9{+Uv zK62#9YkIwJgq!NE0AAFszxkWDo~#z2Exyf1CHXmUOKj^pZqsg{ZV7Tbn0?p2yd|Y6 z${RZbz(!<9=WWm;uU~VbqghEfgp~-93y1@YNCZR%Y4h{*{5k=Cj1_^fzSoGzd8d(d zu$bSb;t*+jVHSZG6siypJYtJ*!UL0*j;8GUkEHXdyDe9dBxhkpHB2jH#rYAH@cR|1 zXa~!wJkuq=kFXMjLRsmbr}R<(E;c9|psbJlccH~ZDar+2%k=^NZ!Xgr#+qWR6h%=X!tJQIZvWg7RHu|L z)N3@GgvZ7AmzMT3_uN6k{wgx?&trCRlK!3%lnl`I1+1~mzqAXr>=Fi+l$pHmvn;v# zW}MdC{-rIl)D;xPLG8eY<#m$JY?sE@JsPm$PQY`3RtK z={mgpN=LA7`II|5u<#|CRH zHd!Pn*G_R{QOF>tpy%q?Mv4r5X{cVDJ1syvBWgd0SUJ3r&8sfuywz8-vKq4cKmOWl z(}7sa{PR!JvtcXQ>=gB9pJ2m9?`Ff=%V>Q0vuyk2KccqbJYM{Ze@|uQMpRtl>EHf2 zMsNCX_iWrcp8ma$GqCL{Y-5q<{{6pV=&~D-afxUD@E6f@vy_&tMj+Vp>EC7e>i6>U z-~CrqTqYV?`knh&-{dU_0&2AyGcz-1@ez4F-J1nmS|hG%wMuVq?^!?gne2Obc$oS5 zd5ke<^?EmL+Qi7n$QyHlV$AF2sCt7Q_qT%LjJ4$o%FW4sT+%_%3oqJheL-7Jr1n^$ zB|*q@VREWp3WpN{E7}%nDFhaqhmN(7jw=Mc(t(?J9{b2|p#Z01xbl-YS0Jzo@mzzj#h!n=e2jb&;Rq%EC{ermC=(E;Wt?yX);BH-2Wi;!;d}(dwvwNCwp?O4aO_B<6+)oNa2P`A zZN*&~EZxgc$C~AB>rLIH99KxQv~U%pzT{c}W}f~wPNxi9d>!Rwt0*sPr?D<9OtSrfzow@;%;i`7 zFhLZvYR!eP=E8qci;j?rY-W;p=*$kBLI`9vLI}(J?w6^Zv;K8|PW6K?p53VERQox+ z52G_wN+41wB8*;)^>eEm=V}JH^De@ASaQIjU>|$ zn0fXQ5Rz3N`WQ3MK0@F5m*b3~Z|h|oz55IFtlP};_uazyeP3nth7U6F$Xzs#9l|sg z+lSwiy`M-p`59+7ka`PjrBaE_n>W9z5z;Gdt5>h4Qh96CC9GSwu4|lh?AWmroKAgx zeJoqHjJLNO{C2HTu0yQb0wpeQF>Y5%=VKOuK;melMJWZwmv?|0Vf@c7c6@*Oe{i_G zi$1x8{$!bd#H7_Xt;)KkdT#}}nrz-l8LKO^|aL12f z3PkGPW|NSbgi5Ighad=I64S)$lsGCQWr%eNVd!-*7JnK^TUFVTf}MV;xDZYiT9vT5D-E8pNd-6{s#zV106$%Fv0SZvB_6W9rd8 z3|_W@K!v1f1M4iRRAzk76Z9Rs(E=(qm(!0g?2{~=Z78*qT-OPwkc#Z}59^A!@NBFTM0qankW>w+$OMyso32H+$>p z>7geV$$qECH*YQQ;!a#NI&qD30!yB>D|~mV2PYlT-?Uvs6fM$u)=Lgp@>4f(CI>Vw z*H&~`Fv( zz*hYIi1GltDu@J>b~u%X<2Ca4L*X4ptqz|upe(X3A!lP;QR z$WXBHLz1l4@K$LelvBAq-G3OyX&>$;%NVCoBFx7#wrHz%`B}2dQK!}!nbVY`at<;D z&Pg(z5l1l&L8Qt);n!N~iJ!;mOk=T>N@bJ^3GxF;XHSt-Aqvn|qmzs{F8PM(E;2fbQ2euOJ;`U#d=%hyX^@Q1pvsDL&d?m&k1AKmW+w@1eT2P(MEy0gg;^H& z?xHz<1f0gnki&atnO}@?K}_%H5{A~TV_m?*H~%tpDj>;o#@~2T}#7QW={i-3Li848&#$5B}8ET=`$W zfzc`H^aO{#^j8R_n1A6J&i$p|@3?(?n||VcgbFzP)xRa3I>z!3{3PlWOyT#!*2zFL zn@tWKI&{*kmCkKoV1T7dm%hE4e~)d#8SC2la<0&*INR2*w0>{>taG;!*5Pd4Rb*^& zJ8NCuObw=WUt^0_YTGJpYzc&oC2@13}HZM-w^G^pdhTkgc{Khxg*Li z!s)Ew=z~?Fe$DXZ3%CGC+h@h#aAk)G1+D>T5Ix}L{b-y8tLJnOeL=3D-A?LAhkr|_kr-YabaHaoCJk_!%1+;;iTp8Ju%I3 zMbE~JC0A;sP#Ea}pPmZX|D~{l#)or16cW{ZTCNcqDZJHOiGV=)az!UBP70I^Nn8TL z5y~hJo%0SaD=dME+M^w`*RH4lZBvvAeFv5Ev&kTckU8K69J6`r|Z@?mwfmcAF(^{Mlb)^yZH+`_#92;{MNY;m`a! zmAM8}JMLrj-9Lg*0Y{EJ&qMeAPtH5{dNyBp^J_||{mvp5e-JRn6yoZxW@u|5uZi$( zLXFd!Y-$daLEtdWMP%Pn7AEWLdw4hV3yw-fvTV~3%g*0K5Ub+7w^=UgRowt2Z5od3 zonvyW!RE`CQ0YDK%zEmvd!V|6owxqP8KvQNzQ)R$bJ+5)|3Bg-qs3*@Pd|*Fn_}>a zccG#)Kl{}SbFWy(fO9(8&3u7_V1x0yAKdi9pml4yqxz3b5!|8P$|t7ZO@*pG7o< zPuG>6eUe(`t{{hvy^BlQeDs6BgbouJLK~nL1j+5<(Lpvye1w z63UPe-{edl@MnY}kgd{2K_*haC?JseulzNm@A(lL2ljH{ z3xCN)zyDX%54}XxKa46@5HiS9xBd9hk9wN^d#-I>@Mwtoyb#(iKo+PeP1b>uon-!Nd4vK3wyqBsSfmNiW1g$_iG{zZ}R$X>$=N!6}As1zCx#>{X5}-o)57LF~a7;ScMgi#5E8oq!I)&_SFHo zaMt5hgTdtO&@~SdWIoF2Y=0KHl^#nFgdL`zwgT8;Fjo6N%#Qntjv~fZmyvabq}lL` zBm${ahl5GB$4keRJc^U~Gzu|z_jQkc;)A3UW3LfJXtw^_Ptkw=<$h6_K1OAQ7o+-^ z|0-cmKlOuqDJ@;i{GO*Vi*pQIdcCh#n4cl+>1Xlf=V=_-Pj$_?=%hhq*=lBXJcNj1 z`p&xy8AyZ*nR(`6Y}RDp!fSZ)-+AzI{C4;&e?x84`BYbJ ztk`(bptt>>iUDeY4`VoX-nI`?h)|#se*l)w_hyUG*8xc7!GugD!Z~E>P%S2*$B$oBD{m{x?<+t= zK$?S#JR8MT{rD$5xC6EG*AY_>AOeT9KB`|?aKhk1gGwQ6DkwRuGT4$qIlmtr8f@f< z(}2i$@oid7QMqeNIRU~KGCJkM?;;TryD(3<)fkl#JKtp_im*6?78%;5SZA>qG7_{) zG1d^E2t`CCs8N-!LCKGXoFz@0EH)RtCdanZmNT7t0k?11 z%mJ_~{!RpnKt(hf4UE?L-%$HsmL|;3O*20~htY<(RH0I?QK?i3@`h)bFRTT)KH<;r zWO4PJFtVB3^#sY$L$7`2ssi@@+3z#^+~YLI4>Pg-n@nu~CP%;Z1!kUpnC6j}ncMXQ z;}3k5gSY<~$;1)L%hvMr@B9mz#}4DtgvWmQ!-T!V-~{R1H0iO!%sjQ7((={R)}4#f z3A)kXso(tP^q+qPgBM@V+^!vZs#IJmW-g7Qw@XDK+-}@}3mFIF`_Z&uh?MMHT66asDlyff| zJ~eR35$fb)_tH4BkNtZVD4qXa%C&$E7Ys7L_gSWQJiyu?`-LvxGJbFo70HtV7x0n( z^`kFy&3W%9$r?1%I?wFeUR>Y5^)gD!R-@|+j6eAG6YgJIw}oZz`H=#+G!F0M$k#tZ zGIi`V0T+PL8$ZP4BX@T{-um+j;4;7aX=a~$?Cm+yYuILIXNwM_*K6CgYu6j%oO*jZ zag(l7*W!vumX04pk?G>umV8Ah*qI#Iw9H7Y%Pf$yF)lA*^rBE#+)h|Ol4qIr2>fNz`k$T7H6-|gLX6j1NDHbiad8VoNkrX)npP2` zX!&%@0$T!Uqz72#9CQT^l{nr z$7vr=Ly;UemY9A0x;o6_Ec2x;9*{eWU2!$dWj7RQ)$_qdaF(GfZek+1f_b+T6~!cC zfUMD^XWeFA-X}S%xAF4PQIg@yu}Pgh|MgZtFgq8p_~LUcx%z!H7Br28jGj#wBEk>{ zXl*gZVbUf$e&xrw;J5zVf8T--n>ITDo<*LaZo{Nap8Cyy&V_&Q*C)Mx=9zC(+px9x zed#+t$mA0~vOVk_ptk8k4(zEjai~GqJA`RAkP?!~F-ijitU9On^g!h}c4YF=dvL(9 zY%`_NwX8X}kG|m&SjS6$^+|d*Y-Ql0YfiZDa}OQk(s!S}yQy!>r5t1vi)?=8r28r_U(2$ae~ftPN}M$$(-Vx{^*I(^-1#by zv7m43rPL3%0v*^P*c9IjnNX z1~`+S6={bH@m)r-*U+>GCSgF-1tN2}UT{tSx`cMv8i+-QKw>xi1k!vIr+k)+%)rJj z53lpWT%~j1BP{#$PU2E8%k)a(#5WS5{OeC*O_X~5hEWA73+QQ!FUa=DiVEU*}%;-E1PuRpPDhBejmHqfL^jab})*gvz?j zRFgpXrum*=rtW z?Ay1`C%wPH+Y2wea8_faGhuA@@AqY%rBaEtYuA2{gO}sV6WduVqAk{KffGlU1Bs5Y zfCmzy044>9$pMVb8IzV+*VhJ6IEzH?GQxsz5@Q|Gh&FIC9t=6>yv4Z1?&Kg#E&8k% ze>N@Vk_Lrx2?S+U*?BrIO!YaF)M3wzbPPZ~C5hsx7( zU6emxw>}l?xZ()eh@`}PH4WI){p!0Tb;WaYGIGhql zA+ge6r19yvRw0EWkP>NwE(>x)Hi(Fkc?OSgD$m35pvM83%Lr|l_W*ejw9JLG&U$7^ zljaD~zbDRmor@A7N;ps{r9nxlCqN+xLJD_W)nLfhR)vXucOC8bgcYb{B$Nf?ENV6Md|oiI*$_|KW$vxMQx zZ=~ie?W4%okOxs&y^-Y~_z9d+1l3-gwe0yHe@JO$B_mhA2b*d7&%2oE zNAE-k$$3Bi6963jhm=a#Wa`OB*z$k=5zqYIPvMLuxb}UNF20Uu|L_-3r84E^>p16M z{x<2%1WT^{exCosj}i9tv+U-N6mFISpZgyizTi$`Ac47yiy) z^7#Mxqhxc_to*=7S@q$Mb-w^>aYh%vzWn$9m7{mvj;ho+cK=twIYw{#VOG5V$9eMK z{v@k@^yit-TUhh4-{s&x{4tY{d=sG}w*Km$P#WL}lm>Wi|F_w;?iwC^_RCyz{`-BfWakKH*)nQ* zVA!$yzQ)M4?=OIrGm> zjJ)#)PWjvqjPIrr*BI*cpTVx%Ze{Z=w|bUr$L%yP`XNS7&24epE>0+9{HL^aF6zf? zPnIoPMql6A3Bu2|(fYMAJm;Kq&MN}4y?ghb^=sI*Yu6i64e(akgh_2dsuVQ5wZ+ec zh}U%3pmXrh7T+HC&vabwTt0HJ#XbtRQGOe3wIBc3{BaEEAVnsUOld^s1+_(Qk#l6B zMrPi9L*mz18(YX6E_BF-;Mh|&no|+grA-DeT!6%3OSyx{c)_g`dE&3~BPWORR_F?d zxIihal&Cr;G+D@CxbvsT;NZIq{Ca3wZtd;d)JW(+u?l5 zNvzCCFO`>DhmI&yB%vmB0in%ZHLWZbKnjHrl2m9E66F-B$_QQL8605=2=n}wcFxZ3 zuQafA!IDcQLmNv7A(6Q~)#3d8a?wv`ZGeyQH#pHkj{=J!4$DZXFwSSZ1S&YuBCTZJ zQ0~)pEtWWnynxu{y+u*n1-qX(IO>|RE0{2)QOicJ&dc0a|~ou8#|%f&3Y_WKDc zwKIMUXEdhSz$A6jxoOXog)w1IAF5pQ+K$|!eB4=whkn-izwLsy>Q*`1{y5dKGJd+ity; zTWp&$lvg}&;1l1y6)3_?!KQp<9)o+ z^E(ye@}Up?C4cvK|BMSR=zhJO+onyMUU#R{uFw4{PjCEZYzzGf?kj<>*KHfSjlW7h z#7E=LaT~XA%joH`i|jh)9rvT_$bNCIL!{fGV`yc!6dH#dxU`rNXY&7xe-5X;6&mAk z+FPle@ui5EeB_i0Z@tWNrbg$^CF3yK6*g?q@JYB1i&z9SxWwCzmz+1xiuX(~uz3M1 z@fw<@!&Uug$E6O@bQom|Ypsj&*P67>;RPbeUqdKRO;0if4gW6Lu(e2lOg&K$80kSs zUV3N)P&OYA34v7>8~LAgVB0w_fd^7Jhm(%LNdh5>ZAfGl3W<>xElsYR@ihwuO(L2o zCy_!B+X(G4pV8tZSu5CvD6pi`50fK^!JEtyGZW_42S6Z{m4 zKtu#G@?#9+ZS8?jL^ATpy`47u)+o_}L=puNrLcr>5@#*OTC~nsSe!4)J6*mIc1p0i z_E%sNk+)kb(lmX=P^-@E(*O7cmi^kDocDkI5ka*Fr!${jk~cxSoSkqwW90hxbKbB0 z7dCzT|D`m%m4%m{WAHLRMlkh7N+T-@3+>d72hfYNZ2nh&;F*#fxXkZ)hCToN_j&1W z{}aul2T%RYQ~^P?hj?%)J!>~pTepSE%JqbOL&zxhNz9#q!8x4HuxWV}n7#gjxcIyD=U%iwIu3gGc-+Bp~FI&RE(lYP;sZD1ET>Mc*Vs*yw zl{Yc>{1fc>w;$!HTR+C`KlyiT`;9+ENJ%4q?LnnR|D`vv_erlq+IH>I6M)P3_B)y1 z`z+`F!f(GKaM|_9I4V>gxOAXi=X^2b={8lWP+qZ?#^IL$xOUqI`PPnqA&S|?vnG? zTzOL9(%Npl^;T}Z^;T|q-$ejib=4R%O__t?-uH3`}SQxlRE%LFXHa) z`+ynz(t6zW{hPV{_8s}++uD<7az1(YzLQ@6s@Tmubn+)}`adAPf}hJ^t^H$IW3k$JrwW;O4_UCrfCYo~pe9dy6%FrpvBqJg#YPrU_lvn`fQ=k7 zcChFdNQc8le)J$h5DQ*xiw05hfJfGI%}vE&YYw#_+SLOJj4+5$p&DQYK+fl7h*tRG z#!$fcgQyojgIRMkZv6**@Y|vXJvIg>A+Qo*z(!vG;=&xr#reL3^r63bkAjwt(D^(K zBxvdTkU|?^q(!3gej=SuRYcB~K*>co=h+e~9GTR_#ApnGXfrTE2#hm6r5Ff>ALpc` zNT<+36UhiATdmImg9iKm^hEN`wZ#ope1GU|0vGjpuTKy4nAHA%+Dup<{y8;FTZ z(#O=-7l;N&z&eiI_eFZoyOin2?`MARGYp*n&scK(7Up(8O}u23c)%yXPCa%nrO{PX zR;(+|=#Sm|WqP+%&7E5&BWn4y@L_GLnj}Dn6!x? zKm_uH63x~&yYn%sYtAXMTJC%13tY4H{YasB@VPH@^?C1q#pg2h!~+aod=1l2ZKt$k zIptH>txvZt)MprcYe|BFwuW2VF>KJjt-zk`2P zoovbRW209yHhDE}pjX>wU8~htxpL*Jeom)*+)Aaw>eZ{?koWv8k@KRP?XeNIgJmfK z2cn~!y@Yh}4~kCQOn0L5rq=v-Q?iOt7HMgEI%WTdE6{!yan2kCD6yjsbtKPq$#o~T&jTc|h119k zID$!^t)eo4%LTbY_yk!~b*L0{*{{h0fe9>uRs^XBD=2|7zN)}V-$5ju!%9J5Rl&Ac z;X9Uu69i5b;|{H?AE_x&PGAH?F33kho-GQ5LSsmzreaGNk>{h}%NQFZltdXVbOBOa zKJH3MF<8p7j6z{?D4{x%ZT;;s=LNU1Ds?qaH*M3qkECpe)6r_AJ|3LNj$k{{{lDb6 z>jY_<>sbPCl}_`Hq_8y}Y5}CqseovAA^8cYCCL&hk0J|0S#-T62J7kZIxHa|l$euQ|*a_09w%hY4{u>L21h3QB4F!YXd znSbGFO3T*xyp((qKlZ>K3|{yS!rpeT(&B+V%su}UORl_$py%ZCdXqGm*nTIo&pkr_ z1@B<^iW|G4`QI8~#$q$iWXV#c0Fd+33AKJd9<(|`Hx{sq3+VcsXGetN$T$CiW$*b2 z<&5P>E02@6mg{#FA^?i_8JSo3SjcI?=j0$$DrTD!AmPq7drGS zbR^<>2M8TH7p(Ouxj8r?XI+ZRazJB^Ewn5x7RFjzT%PER(5Y^%jCE+GJ>yd`$Vr85 zjdzs8_E^NM50tYS2n|Gj>|}-Y8X28)nI%9wNOSfj_Kb^6a)GB5K8&v7nGTV8VB>l~ zO#_k0!|5DO`rliP&IkybegQURKMErfzT{AOh9@vS`Bs_y3^a5;#|4279I+1leudw^ zaI_f;z(|2|!jFxFMIy1%3wMz|{|2BbGh!Pt^Ri>#HznuY0;=Z0NG3E^cqS^6zWYc> zi7rxf{Rk?=GZn^pO^Ol{C%m&t$-s9|wR9vnGBP3+cY~KA{$Cc1iYP+pTGUA^VYhuB zsYHiHrJc~5>6ADw72u}@ShP;Puv>~EY4>>WLhCU)$bqNt8{>lOM@eTUv1yaJz0Wf8 zj+<#NW~5Eib=E$1=jRx`=|df7<&RU_cs>G{edb~2U)n>X+5In|sy+0q+j92t@z&-+ zMsE!B;+zAWVbTN{MmUop<1$VtnsrU3cKQWi=GjNd=B8Nkj+;;SK<$$&qj5UrrDvvy z0!#03nMz-T3<959qXG{=jsquFCqCgi2QgL~^jw2zu&qlv{I$Ph`FlT7{60B1Myi`E z8(fQXjt8InGS_VVz-gJ6lQIbp-$n1HZA3X!ci`9y)XKdK^qg5g&-ep(u;l9Z!FRc{ z=#5-dXJ=>6$}0V8z{_h9(;hu~l(kDI=?Eq|@W1bJIvE zi3XPvRD0NQ_Yp3-p}TVa(3k(374QG?uFJ;0^?62b{2nTRw<)h|jp7}QM$V$p1E85GhPH7xDK>g4@hOd0r35%*;m}Tnm`>1W$T8y1uY10dH zG>#oaNJVMMa<8vBZojPrYVii1tznFR+zxPLGD|u)LwRVhgOD+pMg!AWAX}KlEY5-q znA!O#tA6ljJV-qY79nY9#t+t+9dEMr>X9?USvtdHDe1%!RJ9kUQ%sg21BI(Q2xBTM zmvZE5|G={Mwi}~U-Qh^d+|w`B5g8WIJkq+ zXb5-sAcL1)f7WmH;ji9yTF2Gf;N|rlA)O6)86F;HczF1G1w?!Y!Aso~la{UyqZ1rO zIg{eR>9*#@wb++D>%i%}GQi{@Mt6*fI&W_bRy(xR$V7SpE`AXeslZ4>eO55>NSW3t zMs-7jzVjQP1t!%nLoTLmr-J6^Wge8c7Ki~i=%fBc4sNLXYz4}AmSxUci5U{m1bRVe z5HopHS~YjQWFG7YCvat7ClJ*0v|pExc1jMVJ%u7d4`77#06;ol(%8ysNCQjgycoB& z=sWy~N#!>2B+&U7NMV$vY$KcltxTRgE72H25t3O=iP(b=M9~25vtL4-5Hv)Cm>7Zd z@&Cf0oFW$GV$6deFJN@OBT2T$NG;Kcb{T;T5lVJ2D|9n2vOU`A1REa6w82TC!|eJ! z*U%Itj*e#1q*|$T7dDEH5mmkqp9t&=1(P&kY)_Mo7Y+FZXl8|z4NTt*j=bMcGvBUzUzlh_~sn>#y_y^JwF1#v3tKvJiL^}mv*t_`VXMz3=TnQ zxPpvJ%s%@FmE~&*2imR3$>dSup`}dkc#xoXfS&ay7yo7RGbEG8sH|L9j4;lKU@;kH ze$ID;MG--{2h?k4Tx`-r#-&#TMQOtjmSizTOs6M^22OrJpVePMOg-_#)+%Cm+)+yl{x-_-=-;zA*=0 zUdVm#BcI{2kxNKs#%V6j^KyMZo0puAs@4c=1EllQ^lsW#uxyLXIi7#{F}AM1ia0Ev zc&2^#7Z|?!W>j?MXV%B=`zj;Xec#*Q<#pIjHnKTe@bYSG+i!!H*8*M^jqBFAv@%$7 z$495=*0iWvdm>QLd8>5(vuz1`TVo^b_tVnBv_?n9Y0t8lHsG-sOrM4ZjNMm7r+#4? z-Z)RtuW_Nn3gZET%10~;M3OgGw}hd}>s9O_iyV~RX|&*T`9+8q?^b;BtEdAtu#xZ# zP0gXk1XLWd=~*4oqYwtvT+YJaYYT+(JxD6e7xoZL$q{A(8+pb>2tWF90Z1zg*O742 z_w^vVExp16j)(v)3`Th_#b>kl$MxD42!#)@%dBNSY|wA2Na@{3qDV*tzA=Z8BiTfG6_}UW}ah1mpW5(X~cgbe&`?%wf_+;Gtk7q@%hnJ;n8`F@O)j*l@hcbFq?mPpDcb6l0*)*eGXXbjRg|uEpjJvmIk3lZ$w* zw>cNLLE|z3xeeOH8fzVLQTS+o<1k@{UE&!4F)3j-f3C6hskg>K?5Irr9!mS7y|ni_ zlF=W5)F<|eO2PPN}Sp&UytokRt;7Gb5N|Li+SaoEb&@ZvILubi(80Cp`s# zJk^0|@)+^Z5^!D69Wso_<{C^t_97!UZsq=`KF>AVez5qQ?tA)n5R$9c-aupg5Vdu$ z-cEb?8-LI8_xx!0^S1sZvGqM%cxjg})$Hx(dtrNfF@O7U+u&uvbP0A{0bY)0UUJ=v z^$w0gh}!}xttM&R0bX*@Qdp%sSeRqGEE-GSYK@9PEQ*fNQir=qT5P{BICRDfblsu{ zEH3r^MSfhfn{eSFT&0J^y&KnG#m)IIxeI|Nh+ct9frhUGaH&HrmtF%C3Km|f(b(Hw zq-4o3^npn)v|aECzcRN$`$acjc$I+ACjv{A+mvIU|KdszH6tr(P6Rn|I#d>R4NzOAFsaw&DURLu72^J3RIP`~@->u~uVL}!Y3_XVAGrMeKg6n`b|~FLPkx@Q;VOF1yW}-L zpP6SKA?hEZa*EN`_=8_#_#HRD<}%2)!OPo^`_=<5wnMPn0akE1P-$hnXjhDsT&`!a zE#^hH*%;diRWRbclc3;KhX&TQgp4+mx8h__5El zXC6@gel+m zq9%QXfD}H3H}FM?&O*?XC@XV7f_&7Zyih)Wy!UexBX+IQ?5L!PFOMP9CMYY6E(1hM>2fC+;5O;u}s}OwHmP zgb_149$@H-n@;&H8oTqejNbI&_F{kc7a6(k`7a{eM7`UBh(M?0|Av~Yfmx)O8pou2u=%Nr1DnxR`kDk4It*&{ad6iJR9uCr`S&+C2=9sAbpjNbS|Cjz-|eV*YPe~`y_ zeUnWqE~3B3zmCbpV=O*%n7-aBGDyhgr+9Yz7ujh3c>$D_MVX)%qB=}qeF>xVuS?}t=)fwR03!`% z&lgEwygiRB76dD=Be>vaP)_-@-F#7ZQqWW>fl)q@R{B$9h4La}K`zqu;xy$H)6Ytd zKG+5?@e<3b4`~7!5UK!+Arvt(e;g^P2j$=R4r z4U6p5$Fv+vtx=Nf*19y4CgpOuJHSo|oJo;ER4m3V!R+j0leipE0Omj$zp8XE@afD1 zQNJG}9sb(iv;4h3dfE}h^ivOYX=A3I+D`v@my(PhM$gYO`S`u8z2z7E{Csv1Rf>>t z_Y8f0?@q$L0ZPN89DCraEP2Pxr*z#|qrDZl>oVhk%SoT)*|+u`yZ6hCT>r{}Z0(X& zcS4dcII@{3RILY@$LlY?yqjony5{NX$4-E=`41m?`$$U8sqHh6jaalZ$_OAbnk&^g!5f*51H zJ|(}d4M=jqu5IgEob}lWg@8A|t#JmES%eWDco>J31~P%u`D2)lx`Dv>@lfoTezAt0 z^NUPnb)C{c-DjiV86!~zGj8Zj{tH36hcvj5g~6Xfl!2xPDkzCs32sJs&5Llj35kfE zUsNN9EX#JXuNGh}QcG`(Ho23f=8%aW8M#64LQ;vu^*LO&?AP2S1DELu!v3LxhCh7AXITEeA3Npt&MW21}`xHC&vij)#{G`c;`oyXxN+M}b2=E|_*Xx}Rj+x+hVOgy@cmrB z`!)`K;)Cpd+s`t6_!vi*Pq2UQ9hZC^s}n~!`_R2y_3F3bR?f76otxn0(v7vXHBOy6 z#lpe@i;IiTsX!No9yEQS@a0UB{^0^I4Or;6N+*DV#P;TvU1gJKyf33FG#2jRpcOKn@UE*x85atgl&a)vfxS}h7{ zEa)8y_oPRUH2##Jm*Q(yAKQwX7A(K&6sjtblNvQq=p6zzkxf}l3DYMvY9W=6vS@mz zW(qY)zAwbCq?jzNAdlMJuoNw3OsSEPphTga!YG5-fHX{l#1dApQJbShVS>VlA?T>F ziLSyCvhF=(wLpwPMn zCrx=tCx_xrw5w6Q*69wksMZ^Xp5~=tcpC7c=nU~9os_zvs*=pc#OYJt|0-Kv`f85+ z!SAy3&F{mVJ%!z}16O+TamTvUD`(I)!}Nr%jgIB%#_?}_j;mhvmf_@b`UGy}45MB9 zm>znJg==r-?1SH9>898rA|W8PU&q1#oH_6v?BWvjspBl(_>v7p!R(_cQw5z3lFlo=zV- z0yD>!YxZ68^%fBx{?~t(8-Mw~eZc{iOC1kzA!FYEWutDREnBv*ckkZk>@&~xx$xYy zW&iMjmor|Pl;_T%j;oj9S{k~G<7g|2!)5$*fqqpj&LNF7Nm$}4}S_!f?kg08=MfP5RQYIfVmpn6N1VW zVJhgc!t8*s5;ZZhrdU0^0||=dJ5Hdjk8ZjXU?%7#4W|@(H^^E@j<#{Kl?6fNpl4A) zD_L}VB?D6$!q|g}1tU|M2ud;!R?wJOrZZ9d;;HLlYbYE`H1qm(4AVtcf~v}KxyzgV*N zu;qsL7$&=P3V{p+<&%+}q87*4juQjZWEge1Mp0Fh{1ddoXcN<)6Du?Dbs30tbq8M3 zdsVN4sbOx+pln31tvjwq2!X1q38xNm_Q1E<^_HJ(JxR`$P*!8c`K1A$<&-b~%8&BKfAyv36==NwV;|%7x4)hD>>mM# zxckr^_($(g3Dy@k>bmB^2Oqqk$^24*m~%Prp3mpyQhfF^$u@c}nV262@G?C5WsZiP zOYm*V5^cKl`sEFl)nq-ILUF@e4cEU>L*aWu(|%&Tf?CD)=3IuY+W<>KIIK}ylCbzp zY*{wjW6)wK!96AT(-GX5t7Es1Khne!2zGDuS*acXooiH~$Zk<=d&_aQyyQ5_2dEX! zYfgM^2PeL}lWHx4U4lC#Q0V9Zvn0qOsIwZisv{dT(oc-CV_c6g!J>mfiN>keRbnn zQ7`Sns}LP?m5=%sq|?NZf+m%s#*vdH2VZGRG8ThU@pXc5^<6o8-cwRs)qtJ|n&R>T zMj1wCL=|RC{aT!WNToPwND$p>XL6HaQyQ`l9_MSSx?)z%s9i+}KDL3T9Yd)mrz(}v zq;*nEdyHz+rfDrl;%imfkF`>aMg_BjkF)#jKhrZ)6Y_~^flGb*1l7qS8ycxiuDJ!b zdiH`2zCG{!S&n`26NAUhXw2%P_fwxfNwIS;zA72--H$J)gmRjgM4JHAdZVm`{kJjR zxtFDzUdqaY-(%&G`!52p%sBYT54NSPr#|)@?RVMnBX8xZ*S_P@02h&{xv}1<1YmLh?VS4VS6gB9{8-+8HD_0jwHFP|*tz9uW_F4m#qa7?W|4({7OdHk z&-@Or|L1@3yaJcc{MxVa{`b6x*Pr?jhb{#R)&nj_Klzur=by&5^H2Wemuv_+F2xuC zmwW#u_ipf-zx9&0T++{e?6Jo-eEjEr?q8ns`vS~nvrGOP&So?2yYD^@95}#BUh-F; zQHbTU83zs=;J|nOHGlh_r+=;PduyD7oMF9HQs0sT_wmbtuoAm!^uAaY@&e(EBCMtN1clkJFk3-Z6|$-^%PJ-;PZWBK!X1oa zTeAnmLUxnJA5_$jE3mPYL9Q^lu;sQBY`OU)ri>ml6pFB>kO@es<7Z?l-ao7Gi=I%% zwr3Fqr6!C7M_}ck<WtOqLzwPzmmc+Bb67+Qfc|U$F%~Z4Y|!2$=D8)D$sx`lX(S1Ze1Toj%#Ntga zg&;ikoBt%*8JuGr{ldqXKJ^HPKJ&XQ-}3SZ!uDOy)$jYyE~xGLB5OJEWbzEO09)^T zJ%>K^o9jlauYZ@uXC-S&#t zqZKbHe`+A*w>*9DDpqN&x*u@dr=u~cV7rZVz0v#c{iko? zw|?u718n$xpR3ViC*AkY-obDE)*okaaq+V5M}PJw{yMk5{EzXgcU=JW5;ZR&bs5pK z{qM9d&EGzSFGj6OY@-f!e6M$*ZIc$)?>b85rbe6_qBl$P-e4V}24=Lujq$yX@u~kF z9Zpd0co$RqhftY9UmXZ11%Fr*rg1{m<5-w5djkHTLQLwKa+;MNYzGu}v1EMh8T3}r zxk4&IEkZb^kW$5Nr75T^&K-ILdPyOt1+`O97Su@%UZb`MYN}BSA+}vF3q~}Q3Rwu) zlSM2mWkOZM(a%p14?FJgY`Hc~=2{?+fJ7;U%PT@IWM$SG*2N@hkGGzn0=Z;lA!{P6 zqmUONmy7`pQHoNRcWLuGK*F|GG zHB5|_q@QU@KVG7~X_Sx9%Cw~+)6{`PUYKOA*cmtc~m9tJykRb_qgt>Ig+*W@d*TXSC^y&=Mp z&wqqnZ}|z_+F9&mDV2++=weJLXQ*OyQCWK{k3GQ3fp7EpZ~qIHZh9#<{mTEyF?T|U&IR3Ri;Hp=@?HK{55E46=JZT&D=82;};ISk3^Ts>g zcgf0P-TvV@`h}0T!tW=3_g`_%PyO=XHPgdSAg*F^^^F7xNbnf5exh0{SC|xwbIXrD zTWT)SVdcSlsaMai?atTnVi*^qJ-L)wLgy;soU42@nM}Cuy6c{ove9#?d->rN?4AR> z#8&B^?f(F%bX`Z{8)x0leYX+vMw7ZOiMkc~su0TtQyo7`2dIvq#}87;%Mq7HwnGbg zpC_DvutF>|8L&487zyD7v7On*3DO@^D2d6_x`^%BvZ7IALDm#@e;^z*ger=9bq3*- zLT?fDRzZ#?6T9uPr5X<+8eb{IYqDiQtALtBU5#GRsM5e<6t{|%=>OuPN(HUJMqd}x zOwu|9O-h%BT#qVrP-K!3lu+j-S;(XI#YEp1(-d+f0v#i|2Rsy&u5h|W2g8_A>)hLj zfL$sNH9DEN%p|r=B^i~#i>l5N>wUGcOwO{vIr0FF}w>e6>18dGXYVXiWV~oLAgVv_=nCT}u_qv7~_TroqufXic z;{@j}I4H3hhd%iq*z>N=|D_3Zj8y-$6$Sgc!en_{9=T8uaQb^+<-33L&$g3ww!EF! z{KJo49?;UnaGdKor7j9El*bOEi{e?ePm2iOd+cruhL>FZYC@=zb}wL_CLZ9Kj>Dh% zU3S0iClL{je(uBUdfQKR<(zWL+M_>U>DHI`u%5$gupZvmu_I60b>GRaoZV`q2RjCqsGiGBydB&E6EFz`Pe#Ls#u0u@W={C9ZliX zl83E&?&1L(ceh4Ta+bgIA!5@zd zj4mXyD1VB(Du^Fe6G~(hI!uSY@%=P)UVWn%ricYi?hFt6)}FoW4&{Y*lQ% zKEoP=R{anr@{g*Qg%{pt>(5fcFs;j}{gNRgPxf zl@KlnEUZ5HF!kxS?Glg{cR2QZUGM!RCSi8$8+4+*~Aj)N6EAD#Zi zPq6(}Z{qluKgE_ieuQG@CFo*#y0+_!Y|D1j6;>a8faP27d|EBc(Jy?Qop1W_i(cg~ zeeWY&zxy`!?YQaO1dXflv$ZzcDYzOlo{%j*`zzN|-}@@dx7-=?t{%RRtuK9bublD) zw$7C-LkR6YJCBsBdPZ&ws?atSdZ`<{ZxBm-myjXls>bmCGv16>Ru9D|D zi;IhF-@biwJFf#Tp#v|C{eNdtN84@GbRe|`baUo(O?z~3(!~cPkkSE`zL}jcJ1MLj z7V>SLVwa2M8;PASYex;UV-{Nk7OtJe<8}(N9Nl)sDWs09#q7}$_1OZutD+c{NF~wq zZ8c7$!Dz}8W0VCuDan>=q>N03x!Pftz#Y~2(xOx#-x{L0cr_Y<$ytqBiVnQhqd9BG zb3z59ot`bXRB?j!8kK{Z8H~~?^G6{Qj|vJId(14Ag%ax^TEGZmgHg5Lm3w&w%7&&wXR~K^hWtVi4E~Yx7vmo zitiOlDamz)5E7%IsX|=0ktwjocA-zizVR>6iY( z)8{^gko*ER!OQ07zWBh)dj2v^0-~b8QrZba5Uo&NIx{d$ypm7OwuE#QYyv@&6RnAw zN|AJ&N!Mkhf^hN?n4VN{*mBLT06`P9Lm3^*4qjn*IG7rg7XpH+4eWA+0|u4?c*W@E z8O4bTjKb~z7QpJG3OmJ%jq0XQNUm3=?osKQpry(4(gtLMwG}A}M*gRlnC2Eu$ zOc!FfqZ-G5#Wjx6&H#(Cdq-9bYC(`mK%LHD1i`5WqM#~^jBCuwD7NovK?;ZVv2#fI zxUEB$%;QjKpAn458BfrlwTatP47st1OOk&qi_qbqvYevrAftZPxjI@NX7eFr}ned1=mZJCYkFY=fv(8 zd{F6y#mJ6m!+78IZCT*>-Jd$ItEtLzR8h1BV%6yr!xzj=l1gg`0bkG1SutQM4u9^$ z?0(Bnv{_0LJnq!-r~Mwm`8Empf`@{I>!XKBefAW`zxrwR{OHd;s}qwMO$L_x(}Rz3 z^1EMQ=NsQmwy@kz>R1(y&hkGv!B;|g#-o>Abk)t0-^-c;ue#Ec^2pdD zQ$?^IIi-2S`NsDVK+`vi5BCmhkJ1%au?9R*cu)S?j1>K@ww zWT2J=W(vI}5RMx3Qj8qXHnwoLMr+$V1dWVCEb)kfJj7DdN`_tvr~uk!D4Qlz1DJsI zS+dI~wi7GjcPl)$w1mQu)kUxT5^w8KiAG~XjyE1uz=Q@wNV4r0YE|QnMC_+xq zfm$juokb=keQ&QkP9nez0L>WtQ)$VhC*1=EzHhbUx z(=8}D{0IM$-EaMgbs*);f$y+*!>#D-+!NfHd!JzW_Nyz!onTc!9 z$I6szeCdzB89l#!MOeJ)rQG>H|BL7CBq`o;_QCIS`rfaz{pD|9vj5ievSWun`5#b4 z!S1*G1W$eZ-?Hz=*Sj-M4?fNh{_)@7ra%4Hm?SW~A*16;a$9W9RGUo1=I5>}8?Ab2 z4eA=Rx)817Td*JiVbms-Z#V_7PKn-ts_ z`YygHs$f(jRWnltR*x7~9*tjcytib0Lm7cWr3q&gvX0D7^#FB+9c6F#Y@dp*!_T^wb z)<C7{ z`-AV0U$r}x?z%G1*$2ME=>y-!=41B!SXTyn=wJWuEbhORU2pk`i}*QGEBd)u!xxeM zWpgs${M-R}Y05Z*uA|T~FNm~>&-j>i(*TPuu(8vzv@DGe37m9pyzOh6lIkNcj{qjX>XVkUPsWPZcz4a>E2iyLkdz>0nzZr+eva9w_wCc&h~^HdHR2bgIf3V2(}cjV!89zz9lfyzJ*sz?TLiyn0>PMGSd3UZHj z7F!l5I`%^K7#1-;GDp~?hY74sXJm_tOyyWC(#|PD5KqWFR&1M-`A0@}E3dfO{uWlu8Vqz$h=s@~q2AVqWjkQ~IXA`*#1&5WV2a zDfR*_`pc8Ym_GS1TVM8?ZV@4H>bqa2Jbsit?-)Aex|P$cKKU?PZo7*kpZf?q-}IjK zLgM)={odb)e(xUky!)<>>G|Zh+4atspSRSp(RU0XbSdE%%9?D@YW_?{y>goG{*6D) z>SG5IV1sLZ?!VyrKk{EaN0bVP_}Fn4e6)jDJwti=1a9RNZsja)?JQxo7NJ9)W3mD> z9%CoVWQ)t_yg(NtOfklc#)PWo_}4x|wzP%uzWp5h-ou*7KB)l9Cr0Xtbjox|vFBc049^RoH5FIwXnb$K*rEZehv+2NiEPlFw=mP5Y_{i5E|c@VLP_3g;Nj5tBs|72|Q&kwNa;1OP#*L zqDM}ecpf)`EV{^^Ok+ujB_9FFEP0wmixR{~O-^t`-3g6JT|jDsDxwLN(h5~u)F>cp z8dX`)g5Fu7P8VPT%Gs`+R|~ROar6rr)tR`8+i%q@-6W7ZjASTpV!2C4=0yAGTq`;; zD3Z1Fuh%s`^JF2WIyc}&l;CuUB}=K&f~cm2+O~#nB!(quk495dw{6l&K}JTd3Q&#z zOv*sQlbak3I6NV33n4@{$r!A*>q=az7oe!r@WRkbzy(ik4L$^nHG~kzv#bR|KE&5( zr5P33K)_26q__|$>pGRPRP21pVvZ4N{)$v##?L+%$gQnhw0JetB}c#bd+dJePl8fR z4?lrlIZd(a>b5QT^!@j+aNRAO{Kn_m@%kTI=k0O9>$h4md*V3Lr%tf*?Jv7vA!kgJ zPwvJxdx1=Iooi-$bru5RJ>qJDclfF#lvApcN0=RX3Y_bV8?{OLJ%h3t+UA%9RFt)? z8?d$o+GeOMJ)h^OzJx`g! z!J3KSCUdB11T2zySgMiJ8I-y^XNiCoPCl%uPa8m3y52F`A~CqH@Q}rhB?a-ZN)u{@ zSx!J@xrUKI36vR>rk&u~F^h8NAgD4!I~&C!22^R0kwa=hi@|0w^e`-xXcrxFL++w( zCH*H#Vkc2iqP-!LJZVS*bv~u=3oV-=N)YYQVq$xBqCLE+v66LKo@QexVX9XdGwC!V zD%$va<*B8nroxgjHlwzb<)lUsw9=6!X@G>52%bXp@71YODL1j}sj=zTdf5G=dLA>i zcjVUMLu_SMMpNX;{0^b^9-SDO$+#yhZYitu9aB6&S=Eg4qTNQ$dukWO%A+DDzXUC@ ze!7AgKl9F;vk!ik`+x0Msg56s9yub22)o|;6WsD={-;Yq|DXBp<1F2A^@TGhAw+Ap z%?b08j-y}vI6L3)ZVrC(H`)7Rf9M>*w&v^u-(mVx1T~8{-hrJg#$)aoc+&LE4>!Tf z=I6f9!HaDs3rQrqNK*nxX~~ex$ddnrA}076NdeC?6i7CD46kAoph^HmsmKh3=xL&~ zLYtHjn?MXkP+k#q=P)TQTKQunCNx_|zLpb40m(dSW+Q`BBvjEbMgok5WRxv|#2Hg6%dyW|+-c3O zw+7UbkNTG~vNUACqC>CQwj`v)AXf0B8OoXHXQKnk8!Q%-L5D0cFO7KB+Y&2z>l@Pm7q4opvQgCAAc)4@Rw=A9Sd}qm%>AcN@o(;ZoQc)^$}4uW zTohPsC__b1LSgc@PDI+6sQUiknT5a*a@xAc1`QZWeF2eM7^w)8BcN z#as4WI1ouXnoZzx3HcuHIQ8wj+4;ukS93m3Af07wx#LxAx#LyCeWjdo_L2KJ@zu}Z z$|;k5``P)1cVicqpJpE`;ROy}Hpk{@hE=IGS4jdeI+l#$306o5C6*<$Mx}&ck;V&F zr8gwQu=JNvG2X)DhOg!y!9#po!EhN>VRT)3bx*oG1>yg zSqK)%Kv$NK*GS=`a5ey?MLdj_guOqanv|Wm#=*iYP4K2;27(rpHApJq6n26C%>Tpa zi0h+(7q4P@NHn|O5|C2{Qz%rKNAQx$G)go<0%Srk6-sNw`q&*5EMf!38Ei;e0TVl{ zwCb148Yn`k22nU?L{xg6l0cddMQiuK0+d#y7%iGyZh59gk5iaA4@mCj06AhuXFTs zA4X}z8~>lLZ2l0N<3%x)D?{uyq7moz^)F35yvJtv^;#H0DlZMXks8r&UmHWKb7>rV zrN6weQQ0VpeV@3yVtO*L?N-IM>$A43B?N-;QJ`9-HtNc>&!?F)f|p)GHXS+9f|~AP zH2u9$#p!XDA={>?wIrCa0c8YL=7h-%Qx)x`rX_|NDnRlY>vGVFU@LU6grdf}QOm}N z^{Ajhd&GF0sZmNWA;X>2Jo=H41jKOj`z91ylBI59$Ab2V3JIJzf~r&WfNdO7K*#T2 zGG(F`VyQ``f>i>keV1K;T561r>`v@HQUnASD#}n(n2b?Yw7{i#ukLp&&t(j`;9{ng z2uep!AZrZ9m{xS_L%@gV_Yx$qR+fxL1-Z?L4y2Bvh*tWwbL2LUXKQ!amSAL%zul>>I^s|qB<@Y)8_x?)T z>GZ~b^W}?r|Ll>EacIwb*gt{~{o1ebvngEh*^fiqeP|D_-*ah})@1+m?ea&X5&QS= zf6jm3g9i_C?AS4iqTr^RZi>3P&GOCj{ke(M?+Ghazl$U}#46J{oGQ~irhCsv9}ZTrBP_B(3!$y3Z3cr8f(zGMrS7e%j2!dn|~Tp80^?^{oBUe_R|w~-Znyy zU{=?tv0!pTrgN+m=!wL3-icreg(*~Aey#`0p8q_ZX>_JBna1WCn=5RtIrVMB;V;3; zLo_iGKE_}dE0_5aZpiFnkki;QtKHrv%;D`i&u_X&p-<~6ACrKlA)DNZKBaF zH&Yo}o4EcemM?@@F7qnJ0ysR58l{C=O4fW#srC{Q>oQ_XzR1Yt%<36uXDiHH)!O>E zDdmlhM+vBa5U@s*=ax~CQRF$+8oUIi<&4VJOsg3|Jb7jj0+n~Egk+eOGuCD$d2R_I zP*pXfJVz;^tZS;WVpf%uRRtmxS;lCTw9$x(q zKEmyP@&9|_z@=B}nIDt=d+~L}$?vS6yn=Te`|_t)yy5mM61ZI8SG*#}nFHU(ubx>4 zTmb5ML&E1^?0D^uvV8li&YLiPzA@VW9%lD^jQ79){T$l=b^z|~B|`tByARC)lK%6( zzYpEbJ*S4te&o~)fX_V3gy}Z4u>1=Dte0Q-Ki%*e9((Mu=XCpi|d=J^C-5|A-j^G~;c zM%xG?TCkBf;6}GV#^e@jbC$M^u{LXgh{+6=A_5v+z(PP55di5tzTf5+liT!I0x}Iq z%9?d<)hjG5K^~J%o)$c8;@aQ$WZvOQtQshr~EZ7ZP}>W<#an zS%R0r#IfsY4u9?=&w5sG^id`+*!J?*@zn4A`}VoRpZze}*vpeL{S1e9p}l|#URqt# zl|BxB@`EhjdMEZAV(@3(o_~SkWq<7-^QK?_DzEuBU%Gf;@S$I0bo<+R|NGz1d$x8n z)qSU6_Q+>=`(1nZNALeY1T`P{!1?#*$mQ^BpLqm;{aZ)9$DiH!<#+yNC|=8-ydBDW z{wcrpP|07t_jAuVJ8Xz+I`A2lpMVAz4wFEgc5QNPsGncxir zAL(^3K{BjM=6Ez2O47As_x)%@=9ZJzEf5gp(ca>9jjoetNdJ3~%3Mt{Ve|f$w{9O8 zQc}e7OTBoSY-LLn`YH&fMv<)k8yDE7bkb@|8h?|3wER&49WXfZKnKs&susq_@3 z6eC%P`9XFqbsNR#1S=V$JwXRDMy=sn^I6S2D+nHklNwMMt;u!PvS@*TlPa}eD}1Qi zBxWz3K)@Ai< zUSb)^C>7J7O{4O@?_Q!M97Rm8-q2bjS!g5O2$o>l2X`( zZI@=ET|J9gxOAe(>iA)1#}Bc5>nooA#TOXZ2=Mra{yAG-`Wlu~rqY!tyBr zSX*0Ta!G`9n`NU*RW?$=iOd6l#?NKlWAs2x=)k}{uxLR^LN-I~OlN@C0-7)ncKY5j zjn*a%-_tCYZn+Hz3(BX=C56`xQ> z9}lWlMB0?$=CaegEioa-X@_Ws^&=2iJ5ln;$Ex;qdtaNgd`AR5S~5ht)IRM&Lm?B4 z)@`zM6wpeq^DBO-K=gp=GK(TO5$z)TqD=HkNub6B7eQL6u*Q(72o3@s1!TsykpV$M z1e_|Cm9&OgRg+swk=b?=u2mIAYl&{Cv*{+<$E?(M>jtBnn-{h7*^ViN#x+K@z3o$7> z`1`-b-e;LZbU8*4!Igo06g33p)KQG>6}`?!KJ&ZmN-5#z8)tv;z0?)9nK!gKnQwmX za|T{I=0#cn&`j#*V`0|)9i#^?*iii203(qhpc#mQn`G<3d+G9*dhZJjKoWW$FHq|l znJ*AgI8|YSja@Z^?=}QI4YR^VKqfusvl*ry;qo<%%P}F30Kqtv=qT820EF&|R_P{d zuj*(lhr%m|*EQBhVd>FtInEv_nQYD2`D%?6HI@P`S!7+vaJnL+KpAk9t$&Kr#1c>s zEd^qSlj$4E^}to^hwmZ>q6Q{Jj{Gjl~=9IQKH^s>@9}hq`s`iHFd| zn9+IKbFZXv`q+#uJ7Q5GvaE8&vMz4*EYpLJv2^oGFX;7$KK-FV2<7J3oXj^r_tJtF z+XT@xEz>c*w?AR4u4|>4^h9;EMWgr(#J1y9eo+Zf#9P&PlSP}9kW>jlVkb;Cl3uW|@GN3EtM2kfCKnz{S>L(JgRV$GY@bncfCypBL>=QlO0{ zRF=m+HN#J5-24-Z7z{qEP+qrYZtDr0xL~6c0Uxz0$|5S@Y)Ro4*nO8_y9s1rjM7l* z8YdN2fh9+Dz>>G^#hP*3?>)TZ1t=e!kTht)u&HRk7lHDl=uQKJ-0KKk#i9Z+t1s zx4nXA3S+c3F~N6(@{OwlHq#dcTmZ)V_H*F>_#e6T&;P$Re13N1NhAp4J=Y+T;wv#(=GiNFMm|#2^Bb=@%)fy97Mk|e|K&@sJEF|4ZV>s8fI*SSfRim+> zW0z6m=^{u3f=YV8Mqy1B%TILdNf}CVlXZ@{4cMUrx3za)0=`&;TL84Y>GHMwcQ0r5yhXi7)W%3~~oz+Z= zjMZ5zd#$XlaLtYD>*Lddk8=9nZ(@ouJKpfF4fAByF(6eL8G;n_=u&1^Ry?~266Njd3-xI;g>Y0ixH*NXoN*TVI zaq3%N;;PrYnCyxDqTd#T5CiAlSxi2c_MM>yd80Jea z&7C1wVNhOTUK11MCjOpCc3pXBuB`2M|Ylps;xp7!;GRe_m87f_db*PzMA(wF~Gj-Pa z#~+$<{QDI*zh@bp!J0Y4f^0!)70XQ$+kb=h2$5;gy<}>%5JGebc2dV~q1FQ>0-Y9& zAVWZ)qT{Wj#s$wf8)H+ewKBc;C!nGf1o8L~C^FmZQ7x4hL2$Q&OsA_H`6qvLupK5h zznZ~NsEaM_a8+ESTc<#@*J!Z3-BF{K|;4AEU%}-w7gjI3; zOCKkQu=ORcVzm33!SfOVe(fw(m{3g2B`tH@`@jDxFZoM4Db+>QrzQ;pn*>~fW% z&&sT0Xu=!|(|b*5OH}jklOdpKg}Bm|foflpsiIwfA7b~7#;#x9U_HBKR7}ajsCC{C z1OhS9xlh`7qWPG?QmYapCRy`$FLFeuT8%+r1`}?OfKxN9Do`j&y~c#4=&nna^e3tn z0t$9~6qoTl8 zt7u+V)fJ;6Z^2Ono-$Z22&caI|8VMS9|B*a@-bKa=&z99{8nloL-DfAMlFqr-A1h& zuYy@s;k>8FGjeO!CrS6HE|FLQ3qdGr$CjPXywy-b;Oq~+!yVsqn*b>z z77(1OqmHG=(L|%T3QJBV28` zb#$9R9YhE|pf%Xk<)l-YsB#{q72_huY>>np)3xHrmv%h!@_`rX$}>uxFtejiG1|G0 zwI?6p^!L9;zHKMl?tC3OfA)?R5B#6+=a&ES{VnQ0`JFFAy_;>X+z(pw@W1(c?0fGo zQe3tBoXZH_Z5ZqqoI_hXSK?Shk0x9e4n~CUf8`i=yl!V&PvP+cC%OJ5+pma;@$3)2 z%XrUqPn#k1bmOUyet>=N{Y5s%=48J4xz8PVv2$npcEW8n6w?1&r7%2cu}XlpC7t8^iR^;0Vg_Gw>W4+Rfe4BM?bulWvPC5~7LMy5XOzfl?&5Rk#J0=H-3CR*5 zHw7WM*m8^MKu-t}KsDbBg?NWmS<*IlB4v@#b?>yX0)m#9jbwVkNl~C{fPhyq!CC3J zZvBFiCJKJ7SSlx+{6WoRt7gl-VgOtQphGoTMuuD$krVQc%w!#iP+(dyZ=m*7%qZ$z zrMCb|0vWb*r|q>fi)tf0lS{C{rZ%90JZ2BYXWQU2g~IYxQTWKy8DPH9%^8J9<@(nXfZC`_+~ zSG)&ca`k>DSMMLZr#^Fn)AxQ8KU-t#%U*k4kg?I&_L{fj*Un-lOC0&a$646-3W_~f zvGUjtSb6APZup~r;c1tljYYg$7v89?B{&zw*@=ZQqY1&)NDy?MKc^?A`@eC5+h5zY ztl$6jW8D6l9nb%aD8k`S|2DfXk>Gi>Ywsmkr3mu9_;?$9@3DBX5X4jain3l~R!zxF z&Q1HSY+s+vu{kc)*w|D-(Mti|7{qh{MY`9gP9&iN92)|eey0))x|dV}462{EL@x+Z zx~`;k{w&f10zILxLZQVnt)~=b+_v1BkVWBYi0-#4#PCQ`*G+8wj@I@~PG!5U2u2Kw zfD+Tr@d9YEl*}-(g$hSa7P6GTV`8}~@)lIgQW~^MU0UtNLtNnG{hqMTvUQ*8MN78C zSu~U*>R*hC?Oqy%(UJLyo-Kjg(Ca<3Ao12;jxDA}5hG&p2NqGktM$KO|{b1uwYrKKYwDAak=YTM$;tDAJULZg z@b9NI#%K)L<}9^2HpfQC$e?U=zBBspLS^0K^QDvi-A?l|1RP!IXMM*KbIi)1+o-p2 znG@I!*G<;B2A9>0+!o#A0i3U++pRL)x+WvM($C0s-ZDeo=f=(&2`(iy%dqo_D4124 zHpzJ?4i-G|3f_vLZgnu0O3x@5Q%Qv=&xi^A7>73fTY*;|5Uh$Ckoa6glEdf+sKSig zjs}cMBNVPeMW&+>omSDU7R|cAMx`0XNzm7|bi!p3VLF>J8I4dHY8M%qEYtI6>7HCA z1~XQvbvninWVz&>?`>Lad z$an5(*Rd(piiA{x^=&COG69a-Iee(7e2H^4bzM@2lB%BJTx|6}a=&56&C$WxYRjRA zOKyJYE|julHYYcuc$F8*!qex!sXD^g~>i7OV``-PBFX;*OVH}%fl+Dj=Px}`HUY-ubJPnXJmqunD1Z^nxJqMWC__^l!4TQuAcsLi6 zjjhg8#6i@`c<*8=75k=47!+F2CiX5LTn!^>na8?I!}@31HBBr)aj<%NHKKZZ8L8|{O!DS zB_*vk@KhOC66tmutb;=!MRJCUGv31`nvNTcvrpp?VNbeJMr}_ zUg_%`Yb}|{F~(v{PNowBU~@8)li4CZFHnp(?&hgZ9wpy41Teu>h^sN9OEUoo4JiNlG*Dm&2kG|WfLQ4B!n z!u5#S5rd}0C1XF2QcXUPwATCrNFm`;uigZ3oCqMrLdj z4tqzQWyz*c82+pqwV)XhbdKF!Jy^o$U z(O^+yjlpQ0^f?=ks&wRqCC@LuBShH@nN5L92VSoK#XrX*zy9|&>`)Q!x#s8pG`C%M z^D|z)pRR4l+~nJK;%8HImbW?pGC|G07;ST~IrZ67WJ_D0)%S9Bz!rMoZhY$KjB9V* z^1MubM?UvacD?1jWVda7PL{8-=Le8onla-8_rWjTekr094{`UQJ-mL;rCr07l@+ws zZNAawc=3*B#=Xv!5}FB3^|E|6>WFDueA}ez#+xL0do+pF{Y;?t@qU_huY8fr+BSZT zN~y^@b?Yd!f+8*P#Q9A zK}!;=_SZKV%cXKp%mtF(HcTOo3JN{KXhTq*T33h`g7S!prf%&zKs3l}G`+3w3tcE8 zLy(}gCeLyd8W$XuuP|xy)M#=WJ#9)?wW8Y=9ceZM8clgerF^2Ya*Rh~jImVC4|fjL zuS@B<9ZLL_cq-?ZmSs1IyAYX};#p?sTwp>^(*|V zZ{2tKc7j76;NKmJw;wok8TY;4`m6lTfdkxk-+df7aNs!tFXsX>8-STXK;Z@;rUfgy z_xwBvX#r6OQkZ|QP7`$>%=BN=zBiT{Mz&y9uf=+L;uf?5t2HvSeD8y&ICH;7=^m(P zmzhEgHCSz;y}wl01b%eNG*U`ol_97)ftd8K2g;%eTCbF4@V!E^p=Z{r6CxKC!`> zK%w&jarN-wVhjjj?(qu(WNVI{*L0;Pk=S;w_2o6kJMqmgqO*c+cRsg{x3hzfGP&-S zA8PP&`!D|L0KBwg>+O8#L-)i9$1Tfmq-FHWL^MUt&VEyyYa=dI$WDT<{ z;}tv3L?FET4VPt`?Ao=9q9}OfpZN#;;{W}~W%)+jf z`F4Um`|(o1Y{vdQmvQI2`bK<~0VRLxGydt%!55`@x!AFx4rcDLxsTsSAJQ)!$-3uy z)7M5?nZAo|^L`(vIqzbqpKiOCqSJ3Z3q110Gwir&%y_Thd`+Q?m~;%u*_Y(tTT_OT z1-+1T9?WTOgjtx8tH^K+{A!5ZRApUJ*sPrp9nr9D#*8Ji)G{X?7a13owG)0VHAZQy z?wPi!j%^u~l3-n@P*Yk7PFS6-v9z?10H5H*Gd=Mbw8IzuyGLYI(w$cxJ++asi8^9OgoWNwXd}&*9Lsg>lXI>M2_}}~* z*Zsn;JTJn|*^wtv)>3TWxQ%-wL%aC6+fYz^u2Ib#`KWvS*;5ruTXMKu4MyH^?Cwvp z^G)x$ET4De^B-l`o8Qak*c_YVIUnk|1uq+d70v-x)^{oOm$6~?(1t)}u5+pH?%PBP zgidrjEmtW_kp#36Sge(6jO}>t^Q1Myt6bT3Tv#&dP%|>4frh8~tcZ0&)V`#QrT#_; zPI%&LC0E_5S=bu&D^5JM)OZ|AHVQ36Viru_s7|W^P^m+e7?dQoWj!0#M>i_v9jzR# z`T9RxiC6xw&$;y{7ur%(SK(2^E+ZBFR$5(*);*0=a@-x|gCD8=e39tY5&~J4B`wef zj2`Dugm3uw#=xa{)oAI`8ljylobl<#Bfs(Yx#p+;1a{&1wZpGYpP)WKn+nTs{N5gCGBQ?EUfoWOG{C9Gl|>0bVYY zfw=$xv+lL)+;ryvOjr+^Vs29CI);KUt7jB8Z~aNMGAUqD+Ca$`lt?3Vt;uyBTY}wM zG?yd#v>0VjGHlo$FAewThx-rG~D%J+GHxC}LOk6V-u?%GG2x!x%$VS7@cMDeov+ z^>4IOC}vf~c$Bl@53eo&xTpkLHa3cG{~ljr@N%xn{aoX*5B&@Fz4Pa>OIxm(qu;Nc z6PqxLmMTWVKRn4$wZJyRM95*=g}SS(GZW#vkYGNgW>FS6Ho6dv*7ENy1+=gPb6x>AISGQ3QjMlCD4SDk+rj489Gl~X0$$Dq zU@oA9bU^^7$BH1F(*O?<#P@w*VibUPfzSP&Lr8#^{gLf#yCLgd-_zVw^^8nsZA3xy zxj|x*v(cstBTtYqlkJK{bqvitNffVCa{T z+BRmT5@>?bmu(kOz(;por3Nt&Q6wzGcII{Fbe+Jr$rx&0*KjMdaz-&O@ZRH`W7O-} zAGFrbF(q|fqm&}EwiOF+1Y*>Dzy3LQwc+#QrEP=1-P#I=e*d@F@tPlHwENO`h&=U) z53=hG?|#-fIhSi3{`Bv#`yD_1oDfp;VCK0P2S4$f?ESIl&tK)(mp{c-uX+1r4`bXM zn`0BaTxRfcE(YeJK+HUl5s7AUYyeYPND_{s5uP^U6+<5A+b^_u9F(F5ek^OG8&qtP9$_=5EngNIwnR90Fu^f z$Qboln6fI#Y#xQUJ$6)^r%i9 zr#yLtr5j%Iyl%V4fAjz1+F$rnn^Vf>*c>l7@N!;|az0>l5iHCcc!>by9N-1o?x0yY zqp(GnVBM67e2CsB%0%{~H!*e{Od-VxloY1u(x~YHAUfyYnJ+0+-Z|^1$vKFy_JdDw z=1YHn`2DnH=P&*S#^xzkMfI2#-LWPjIARE5k#&KKs@K9i2w`lTYY{3}k=q>IBr_)l zN0P4%s9|gHK+KyGt3$Mo&ulixCF=iRWi`XvER_#r7|hulv$CYf^WpmkA1`c3=L~iW z8SGb+En6>YH$8RF7YKFD_8)o61zk;_yyx>wuD#`=gBY)*QJp@HC#W9$1a*0ae8+7p-S%FB(o~YlDkeiIMUVhm;U%E8W|ZZ< zWMUGlr+9JTVrvu&_g#H2x!wbtLuI| zf!gpluBsAiZKsovo~`qI2i3WD;ok2s+4{_dvc8;g{O(UNzV0R#ue+J=|DFGuli&Ix z*_IvL_{aY{7H_zn@xJSS=+6e<{hNQ5GxvWZ!b9h{`M>-dT=kl_VJAy-048ws^B-Z? zTYvI-SFApl2qFC-$Ow#TU!#?38Jbpkk-TI2U+~ny3U?MJ*Lbin zG6f1KrKHf2m8nDYbjfwz)3HQGVd`fDqQkCDcK#?8+o@AGR3IetxeTk#!1txq#56jW z_Mwh(X@E?TjoMaeY4Vf$Hog!Aw?)wcp}|i*_XA6B+c@tC-jnC~2ETpEp%O_fOfL&- zzHG&?4Z9E78Yb=8fS3NH{pCOTHbPwucE)S}(4XeopL=1H41#w^Riej}!FCK)#md9? zvijHo#=Ea$@uoXCcK0XQ^Uj~UEbCMqKTL7eZccpT3v9dV4d^S#hX2%ezRdD1ccL$0 z*45_N9Gl|`2QL={V9o zI%?K0NT3e&u$yQg7>=KN;_;I2{d%1Iw!a*%eWy^^92YzbcHAZ;*TKbD010HqQl~J* z%-GiHS5O2IYH?_-W3Z&QDZ5Cu1c;>ij3Bt+@!q4fj=_FS;&9&}x5vsz12RIOD2fi? zq~%ww&^FsJ>uN|mh4odQv|VPi8KdUp-(zh;2$bcF@nB+@7xcy&oZ{SU-DKOPX;D6N z|2O&0-~2OiyNWQm=0@)N|9s$*xc2@qj_IMt$(Fa_XKRG2B-B;BEvLA(6~c54@8aX) zqHCrZ6_{cHJ6S|e7Ri>D$+uh;wMK1OG?qf|{^d8OY>kd;d;LHA3_2fOG27tDkN!GW zzxS6mr<2XGIW8l3v6ufNId`MT`JTH-K$O~gHh5_)6-`D9Ex3rDEJE!oio6GC7|x}l zHH0uoX%0aM3Y6%Wo1-O`ReC{`fe_o3bnxFPcb|E1jUZMSEOIgnFHTq`PNr#{>GbQb6iI3^8A4pxN!5jX8~SX{NV#t zT~g$u&bB{<1UQPeOeAx@F!3{nnMG~3QF>WpR(J9reHp!b%;HbofzfLCo_U>4yP`ej zWzhON_?fz=H0#Xj+K|PTj8FrkIfw#Z7d#?Dp2dL2Xt<|RMv-Zm9ieA>mzJx007^ud zRWpiW+zN23s>J58Bgz=l<`(r@xLPo?;cg%s6KKvm>bk-hgM@%cpmsH*ViZ3|>p{Ur z2A?M_1GWiXp8pZNN1GRx56amGzC*raH^sJHn?La8*c_J;yx1#hZPd9NN1n}lLI{+u zWYpBj6*%Yc-cb~zSQZNHv>yWtJ1Irm5hG21v+h1rNi=H<5}5qSyD03O)qP)3+H3n& zeTrlrpY_DBLy*$D-&+080hM)Ew~arGA#VXnG8$H3j7A&H10O!i%0b7={_|y&X-xQH zDMrsRKMl)Km1X;xSzaK-OrtRKWLZuK9TU<3E@N!VL^Vv&zy8ugeE;BSe(sgm^6Kli zr*vzLR*^liW=DM_!JMtY%z zt!2J%tn-E7LrM}Byz}_xF&`hxmbPLh3z*RuWplL6z!=b`bCeyl#PHl&cW#as)OhdB zc5@?aju*u_{m1klmd(wuIbQJ0OI>@s4rry(Mxj(ds}8WVj;?HcrPW+Xw;4Xkv@PC- z1Y9D3iGs@JegrPc=Hy$JFyjSuK0@0JWh`P0Dmlu^M!;orY>v&bIX1`U*c>lT@KRL{ zty9~rR>?yo{?mzp85old&`T#gZI~C4kibjSnnVUBw4kK{E@(}*ycIK=po=j&%TOjm zSrfwt6B{IQ4&bs0WH!g<*c_W|4t_u9*S<|>DFZv)NGE;@f;og0;1YP z`QXzLJr@Yu+*PSNQ7eTqDqWwQTSvG#Hpk|;K=3lza}B<#2-OT%mPlPC!?ccd(Q^}M z|L~MPfN2g~W6^m*mKW$ef)!;g%4V?~WNZQ|IvSd2-P+w>acs*uL;pH}qUHcxYZQ}S z6C{4Kw*NYn*ZSW{(c}yzsMFIL^~K84dc3FsG#YyI%k#h8Hpk|8p#YX3c$Z4vE+B!} zXyDWNFLX@{gPc&+b@&;h+O&3KG+IXxqpijmg*KbV>E_rR7X@C-(pF6Hh!@_l*YC+$NyX(mT<9zF}G#R^fREE*k)r zj!}{BzDQ?5-)tWV(ZnwJ*jnv<+-AvOt;=8<0t{&xue6<%ie4B>MUa=kp0wpO&AwnD(uLo3I$E73OdTnj z)FDLg?|zDLCJD+}qiu=4zY7CCofWXqbgU?s$m#s-{-2OmM7xSHU63Zkpgw~>MmRKv3+Q)4R4#k)VZklbZdbe$m-6oLP9Gl}pkN@Cm z#Memekl+v>EgfcI3%*W3#)k-Cd;~KRn({b<#)XzN)k#CBB4ANkVYEUgpwa*qp9$J3 ztQCw^*xYO$qMKuLoEN;LoSJrG22?|T5`*`iR$Gy}ky=}MNq|JDUe;pQF(l{G&|Cp5 z%Q}XoWlRKuk5^gVbwH&`DY~;MzMO(c>e|vMC1hHI1*PnU7BxfTw$3{zgbFDu{A{Id zKSyayF^XO|S%J&au`R|ZY!>Y)Y^L#dn!dm5ECEY9Ghcv%z+owQ1B^z20}f}WS@Gd`<327*5GiCe*OW=(=jax zw9tSS=OMVrtdwO0ENf>`!J~~PvkGIf4zL)NGI{!K=Uw8nZo%9V=*!L6P_*$g{b#Ed4Gyg+3cG=_iDbaTb>Uh{dIAZByC0MSZY`VPT& z<=x;@CA`z`g>n`zM9Nt_#;X}pSNOU@>ME6hU3_ow2(U#y&cWiHxZ30E2s*@f9#;K} z5meN-sB~^HN#|ml5>ckfyx_ed>j9V0Fs*4>UL=AarCa09&9ON)!OJWauz>b#Tbn>3Y}$Gqr0mqo$hOu{^^0yUjts$hFx1t z!nL&QOG81&`$-@eOzd`OTQnQvzkv6O5IpY8DeAMQu?tI>(E?^vptAyHV_6AI8$hG9 zPIuSm5^VyQ&GEwqSR?_J&}z^^3t}Yn?zgOq!YESJQxL}t|nL4p}rEGQ+M)(620 zY8HWu)&^@V*5qU+C$k0CWE-E1HxJ>>@q!00S2Eam4jC6o?aPvY%Mi4bgmQ{oUBRuM z#TZSN8>}@L9c$Cp#1fIUs!KuEs=ICC6_Vy;P&V3NwWOyxYR&!Ou zzy#vrB^iGb^(~2Iv6;qX(t@1M7bdc`F6m-U=l2oH8Y#QZPNNKF099brY2S3tV~iev zn0oCj`O=oCi^&s+u^CEqE9~8nh1o14y#NmdIS)^|LHhU=3|hpy&c-3JF0Hjg^LI#k zwZyoz7b#7bU|r(NDSozwpG^tnlrUSvHTSDo3t(a=l1m#%ql{ta+Hdk`@zb~}v}Gjk zBLmZvjEq%exoH7QPN$`B|7nFYf!dzpuzU}H#zlQwDrakL(8`e69BVQ%TTs|Bc{XNT zEHKK))NaBkUnH|JWnGGl>Ce25@o#@+^BCS7=R24P+m|5-^~wpiN%7Hdo@7wH~wQJ7RJ(!Fe` zbwb_q5M1lKj%1F3kwMughFk``7rgO!AM4`20WrP(UvFmd)V|sJ+&J*REUqaZkHQJ+WG_G30 zU%O*CVJXPI^$7NXr>+<_&%V%qsP&9X&r~k>SkF$a&h^>TgxM-KivT6dI@ZNnjkPvj zO(g(hlGY_gE9lnGp$}ZzV9RC#K+Rw1u3P6p5nI6dLgQO@xmu`P= zzlOAiiWj;owJeL9yX~83CP33LE+Lha+Abpr1UFYg@~$(F>@haMx#;)eqIkFIF7&fC zf~zt42s2&);HH&-&i5yOfnbsdR~j8$67V+{H%h0V+X!N4{juQ4(kGZzt4ym^%6dxW zN@^DY3@EIzWVT3Uq6tgt8m2$EjUPO<%Fb)Y?7w3x>iQ#SG+P$Zq@xx2XTG}$Ts8*) ze&2SgH{J?OM_iDLIdOqN{qpN0J5xKxzx&na9mLp67ASZnO={;W6{YTj##Am;C4M%= zojFOUrWk9;tj1Uq#dVp*ng+b|OGgH+RLi`y0^Q{6(18{BcV($NckAHrYb&TMhQ^A`(M5>m)exeAWL}_bhOri#>$amvMj&2N zRGY?RskEFaOs289PU2nARxz7A&a_%(tvt(gw!*YtVLDr(tfx3%qm(8y8AU!}QY_&| z9?2eK%T1a+H!ZNRut2%>2*!=6O)MGZUw#1d9ayo} zkY$ZH*I=8H(LkiTzEq@?8i1D0-=+Wj`fW65Iqz+Q*8e3N=L0tkXD?n3(Abvz0U0#bxYd0VzgpXA&lgdgqy#4Lg%IK}>g|NG67%)mSuT zo35KpT4tmNF6O~@16cZ+DW!X+XSxMFq3M!qoS%u}ZU(GNw+|_$dih%$9G|L7l#fq! zt+_#WQ54O3crmz|_B%D76~e~*NaL9}NUYajVw8Q{?UHs32`FE;rjSk9DEJM4j7#mz z-V=P?m5RJ?K~M)=d~y``slzbDu-M>YREk>!bOb+2p{*sjNvomJTF3mhEXU*p0u&QV z9t^>UuG>h{+W+fTv}>@LO1GLb|U`9*$qQtX|4|xKvV4ga$c}#8&{Qg~3ue{-DS(X!bz}lW8B?An@mLL_kEKs5r`vv5U_0483lMUln`1Zuq_yZ@kxD={ zS8`1o^lXj#^hvaYcm-wS$tCNRiMoKjqTYV|0Bm~141br9w!28uQY1!<7Qn>)PeND+USt4O*Rw9F$96QO8*P$#WCMuW zNDl}pKdbpHWUgd2M8?CTOaVbLJv&a`K(za9D=wXD|5aK*Tx#`iG#tV@ZScTON_8Nn z0slI*gr80p1TjV=$NFh|+zwfo1ZX65?aYI6lIv+=dSE8$UL=WkY4XQVn9;a(vJO>= z&PU1brEc@f8o_SJGw!)AV`lyXc*E{vKNB5ykz{VIQ7WK};^dA`AX$l4CY?hpR$DX% zW3r@aDaf-LA3O?0kxx)4a$8Vj6LMRS*&L%YjJ6n)VT?`7Gl>P;9GfE^ch#$Jik1Nz zU1(W2_*RAT@o(+>s3#t-tJf-4uZ_oUc3Rl=b&w5qF}Z4q=^uU*qu>1ss&tnRyo9Rk zQjmK|$n=bsdT^ktai?HFrJIbRUbapyhrtgT`)jp?y09cby_nxtVmk>$T0n&LOsZ=^LO>412>kuyxk~O|#iQFAc9X~$mQ4%m| zMZA3`ruo-rUK)_&T`Sy;k9ApPZ48JA7=s>7P{o)v?WvXHz;+ysQH*7XpOpWyKTkf<0dp%xoi? z$1{81kAT&Te&?%~1;ki)=6Li*5RdrK`6D!EqlQUH-82}BPQiet2?sPWS0^SPo0NV$ zAI#XXHL5>Bi^N3b<{~lllB-1s{fznf%emf3xPLNktSTD;U+|vbDneP})>a7REb3W` z&b!5Au{>l=0xc#!W=+#!q`GpEQf)$PlLXyfnWE?LTL)FOR_oXoV|9C?Z?|)yrV+2wh7~H4m`ttER-^0CnmpFBjockhWu)YM zn?MTQw^sg=E>h@=d3_hO7#|C*V87MFNEb{SLP*-;xXo53aNqWT_cdM|&L;p9JU&EI zJn5C~0CpbvDe|@JV%C{aEMx{*I?l=6AIF*u6C&FZ#DfHk$ylCj#|MY=by|MZFBxrH zbGqD)$g&7xM%jdMu^9j53yh1!%~^YMfCSu2uQ}(_$6s*~z@=XW@o@Nc3Q=(Nr)A@^ zhzlKv`Q5Lfrqy#c7uea+gHeb#psP3bfo;xdPC5~wQYz-@6a_jPq4OwmQ#Ol1fyN*W zrKuu#kvYAG^k{8D#{h+7)h`58YAK8>64S0#x^1tXl7B-3Tw)GU^l3msilf)q!nQsw zE!$$EK)2Dn7^BIoMH?M;E?TuB-R5N5h!|Bbpi(P6ARn6NwCd?!wBl1=e1vzu`9=gu z+lD#4OgytIhCjx-4iX`0VFKF33Cw#Pg}f$Uy}{XlbsldG#znTk)E@5wwbNLaSei!Y zTgNu*>f}+d8Trx{)Mx^Jgt8W88xTXAEH1pTd}5;6a!B);^yan*?3H#A6nmH4j^jkw zl!tt};%~r9pBV|EdrUR#L^_t3D;YHj?OH38Po>HPVsrx}djK{xcKE%?G%^j{e$!|6 zP9EGsT|)468$Ho=CUv6nzQuh6E|GaLnZ}rqw6GnZ?gJ$T7`G9$r{H}j4ZTQZX~&KD!o z)?V}^gF0=orid&|HX_f)Er`jp5xE_0PTZRVF$SzTC-d@bhZ1<|?ePL--yfU@#Ju-a z?HrJO^C9d*hc2nO*A}_$olMTr&fBYz_qBeFiJC}2$~D|F6*^@fY27g~-Uo~Xf{B_JYon;wrgD*W8s`Fa9d$9z z#oVUQ2Qep(q4E*g(h{bapz=}7PBO6!AnAMju=~Wc&ZkXEaO<&?Kw|S4V5~zV0>O~} zdG8Vf;#)v7uZd|yydm8xrCO$h4LgjI;h~P8MQe=&AGde%=8-;dK{~c)o_&#_sJ5PE ztep{D?FN8Ag6dcVrP`oTZR4?HGmW+}Fwpv#qTXzqhM@`@rO~U{QPh@-8s^d{tkF?V zlR^xG6|@O>6Pe5=2(d|Wc0LeX{9bEeLI}bsd1YiODB0n@*s?QCS*iOwq*iLzm6iID z0*$!8$Mo(!3=b7Tt?CF~e2oi^+Es{noOdk?rj+K$){nETdRNrpQ%>oR-aYt9K=Q~+IpTngVg zl|T%_zE9IMr*3#9Sl@L6^<6i_>db1%=%ZhM*7Jh;=qJ7+ZTG-AEbRLd7@>c4MH?d6 zv`98?u=56MD1*+UI$v2E%PBg^nxm5m1i?E8-r-$EsH^xRC>aQ0H`0ozdA&(%7)Q^C zMYaAc4InW#P6(NelY>c2OWO{e4CtE9q87Z&nRvA=(LK=DzryXnVbc<-+iKc6Lp$9q zYv}VaFY!sg0bTlZ8!6Cp=8ff~a;i1EG$XhO@#1RpR9OW1{_ zuEpA9O}xdY%EydvCVq1T2wdX++Q@ph3$*w4kQPIOau(7uN!p;9bkML<2$J zu`fw5+DxAL17AmGYs_BqhA4XPUybx9wWO=+3w4b#C}q-p+m?wW{pNj*O)K7Q7?@rJ z1qjtz&aua1K98>h&ZYM2Fp%G%R8t~K(HL1|UThv?Gn7`{`@%4vOU?cM1D#8waY;Hd zV|7nYlRnEvVB}rQ4{8#f8xZ4r>{z2uZjUJqd#4`*S9YCBJ&jCgE`Smn(=fJe##wh| z)qaOh+!QD!0+_n4aK6F?hflX6lFG_9ig0aCmJH^s&RXEn-kRn%Bg=BE&U@gb2VVMs zW!-!8_+C>mDHhd_=|8;b?((7qFP`bozwv2m;PB)-73w*{x?ArP#z#TBjRn5_bDchN zhT?PIdq#|mEsA_#q}I<4R729G129d?XPbb`APsrm6}Gwh^R6VgvVCpmdC@y@_wE=4 zI@3ddpoZld)u*ESJ}c>d12`I!DBUjs^%$52p!Dtj+uLRt{lG;vZ$8J|)pPfyRF4rt zfi)dVF%P=>6UICMn#TbmO-F_xy6GfI>nB1`ilF1kG>FE8fKvgZ1IBBd_wh>FYijLr z#z)HDX-p%UG#;Z>68?Jp+6q-Q!!B*Z`U#;3u|(L4ko39Z2Cg6mMw+~+1W>%|Cc);h z$ez&dDa9+sAe8ldt4=n z-3ToM({u$jWg=@eCfA79gp5|>j}V=n6R7BZ@?k=tQjw{PTK}#D)q$6&4>4Y1$uk&I zpfh#l@jdY3>JGp}kRBN<)ojDm#q_X#7kk3z$lc*NA+H;H$Fv~Eb!DT_33!`*`JLZa zeE9arObH{xDd4}Mq4rzLFuRg(oG3(D6p1ZqeP#mYR<2H+I!gYzV5PegZrD~ zMLCqgK6n^+)9!P>M#D9q6rOskLY@Pg+EceHPTk%EC>8AZreN3Rm>Gevb2+wKA3MY7 zvljJB zZFcWhsMpTo*H-b<6?`=VAEHL=%xUU0>RNT zFwG?2TqKy}vGSOGBYWiwjQwM=?Rg%!___r!1UC@zHYL3d6lvb`ZN=BGw>&v91Y_I% z+XO??p{bQgt;{A0`Y}nnl+I7BmrjqprJse?d%j^JJB3+A_Pr-CM^0`$*_ZVN=we{+=Y^xMik(CkI=t8H+IbqS0$Z0? zIdx`%AezHRx1g1vwXB<>LIy`(tJ<>FzCVz4jEwA9X8H?nApiV*m?Nhz5WM7;_1QaW z?u0KJ0+|qo-XjR>%0*p$KV7vp?Ud3bs}Aha=NN{D71BLZD?OJZ)P^GVQk~V@-^0Y` z{$m@ZLN|FuO=m~rZK31oK`Zo}Yp&X$Jfh~o%)GzL1%Q@j^nuIof9WB9^bI%mUel80 zD3vrC3Ur7*96^B!(sn|%?xvwJ8wB zNKL9%)cgEvU>a7%`>r(7uq`pzQrfbIZ$OOiF^et82`$rD%``S2k&n;zv@RWB@!sQI z3fa5%cJ%kY6vO^zQ~cUld|hJ~7ExPvQ7Hpenb?k=z9j)dEdoY3b99;6*#*G0lUX^n zROOh3ZD(3X-{6P7GY#89=v;SEHM?(qjK{uxZPJrO;8K+ySH+GSTL=(AQ*6l>lo#qU z0tuzS*MZs8Q_nnA=?EUI)np?>UP$Ar(1PEl&D!Zyj&cEQHR2_ z`KkvUFV791zG=iXa|DyOV6kC_wX#u1XEKb6Wu(TRMH`!vqLW99(kK;yj_w;0_DuoX z=lcJ8Ec1)SXGuIVDyUw4GqN;B7JEWv=h4T`kbmtV)O32qh6>JumHO7J@i*>97K(Ed zXwD`Vzo*@6q1Gt;_;$Cvig?Xzf*!fL3eWS2??bGi&Teqxo=N*qA z(!F-i?o$BVaqHuAb9dBUKKA5J9(;IDS1r)+T|p-A~KH zsBeDj0b$NW?VM+S80PK>t%I$|Fia4@4@8flGgoUL57FqdX^)-*Fn#u-uM3$6FJ=Hd z&IMTJfsGz8HSO!w`qyZ^k@bHPANClPVT?;}-RJZx!?Mr@j;haif*$@3eJxB#V$sk` zs%`|mL1IZLq|#8+MjdZmt9_|zm#%nyr-catySR;PaS>gNP_{r>1KOr`YQ0_q^E{kn zf9!f4C%7Oj>(VeS&Ew5u&1-^00ORMiFJUO+MFkeOpNK#u33t77NzCg~ghSHDteuT| zE+1QVy|n~oV#%Xr2V<9BYd~fU##&rC;n-t4T9&Qp)`?6F?7Qu7%e=Ivc|Nozjh(68 zdWYS|zjH$>%}8`;_RY_yTIR)OdYv(E(-Bn70<*Q6axI30X1QiGv8@kG(+ps&YP*R{ z!?+}`C1aC~zSYT%HXd)@MX*$t4S*5q%2AgASNWue=@OkA-W#@1v*H6$MzTSM0~%di8VG6?9P}z*FxypGm6XHLrYt@#vXtL#2ch zCl~ql_xBIj8RcN#=hibZXhrdfZ=ugj&&|AKnO$d1f6gz^`=9iH#?W&lU8w}YNS|@h zt!Y+QJ_=no#~`C+Jwj|+jGHn`WLqMW(1atJUJ0lJD}4a6zKqnCo_YY~zK2e5%l_>Y zW-e&4mszCM5VWi>6RClY#~96D``Yxn)}{$dM)1rFw*}!bb{U34A-^vpLlXBi`!2|m0IstXxpnB0H2Qt+O!@q-uswX z93+)FY`Y(d3IwH4qB;7=Rji#U5OM8pHZYAdipRgdgFQDNY6ZfL)33}M=1CYZs7fjJ zz2pIuR#a;f4nDA_bpdWPW8MknG_f4X0pFO&qS!224ontvvce~wN}#R-RGrwh73CU* z%_HzLnNG<{5dtb||t)vw zqtl+ZE)tiCAd`afJ+F-3BOm$-s`k(0_YtZ)ugBlKH=UTSkPa~&%QV!hH67rrRSVXaH>nd-5(|5V&yZbqFHU^uDg(u#rxcc|!TCRgozWXl5AN4hBjyN6WEuB59(Gh|>)kEL11 zy!1ecR&eyhj6FLiy!4ixJrV6Q01<-##`ymbgun3@-##=UdltZDZCW!Pt^e)TEvMB? zN(a11nv~F)fN9amEK3taV&x~q+GwNi2y;Sh6EtE1;sW*B3d&^Bv@nTw(IJV7RcZ^? z&zt_G0Vmz07uvu3tV>u2S~}rwQ%drU*_>w}Qa|z3GTEqPvh_p@BnQsRTD9dgC4vg7 z%gJdneR`sBfZ!}oeD}JpEET#Ovc{&r@n11cvv%4tTCBPbr&a?K()S3R>u%$hq&mmw zY_!64cRm;=Mq@bk$WB&{kE6k16;jzI>ZP)#+X#bFq1|S!ur`Tm8y%L-BM`PIf{R~5 zn|MA@A)r$>P~%_Ys_r+7-Ei@@>9ej1iH3J3S|X^%P}0WktnRgX!(&A$#k(Jh$3kch z7nSra^K<2(%TEU9+V>oQ|9EpoCINB~8KKZETM`=vVworc4byfdHQhuFSc!loGAYJb zbQ1;812bAj5R)m(C}_0TExYvsK`l&w;SCqZvOL{zf!R;K8nsq3`q(#~mq5YluKoBM z_gt}CeR2@i_CmFM;qSR)bdtZa=N>|^b9hMj^4d=R-qDwmsnCL$SG@F5o;tLR2Ortn z>R_JyQN=Z%lwk|E4@`gI4U9kdg$;kJ$h=$t>k{kav_W$Htet*qr0%mV$vHRrKm@c( z9S=&-q6jJ`JuB5rh$`g~F|bZosP^hzsa}?l?mCKe@5JAge>N%s>6Q*}#j>e&dDo7~ zdACFqqQ>tO(vKr523mz)48p!4E9fMbL4#Gx~2rP#N7Deh$B?1I^tSd!~J zW1_ZChNU>AqE}4N$tNaGh$4!hH9-qTYsADT0uvO$XmoT^$5kbvoT0J|V=_eh_`NzI zLg&o;e6XUuZW!++mTWwUeTm?tuYGAAAC!_>VQ=VkFbzl#asRDmma`{zl22yjqZ!%w zY&s_5w!%mYXrp*q5Zn2KG*JLrYt~L~te1)iFWVwYJ0KUzo4OKg*l z26Iix$CwVVWT_lv(*0O6%vxvNEzV+W&ZshE+Mun0RDx4>&=>l{Ump6o*R@yQ&j~D= z6jVQQ6ZtnDejZLlSNQLwq88bEQ$;=j1+fpx$oR-zQInH=L^T=!Z2#A9!5 z0Sv&tJtsMKe3{dUfl&cYycD+GH@}cT^{Si5zq$UmvUz6bON88W?@?ZH`_2K=LeB|Q z*7?0em2qFJtCip-p0Jz?7_ITdQc}Ef39W)h(a&d5NJIlIaA|o8)hin*J@8vm14c!+ zY{~$*q%xCE&b5tTR;&JJte5&U?WMg|p%%cXmf7g8*4l*$tptp)qxCFfMKWNSVquM? zoyVdzewq+f@JKM7({5VNqmS)D10fh@XN$J0#?^wad|SfOw$X+d5RVa!wUCX^P|aNH z`_ddY(#uoo>tR$XOKC$A;`N00qM4q}kszqVoERHFzhRV`GOUCMrlPJmA|7KDegD0N zA+o7-)R{kao-axX-qAA!Or20wvkgKF7VVV*qoyX6l6xLBCaq5hLRC7RFt2ARzmBWr z;{*}3v1uDcQ03hkIxk{MoiUyJZod?()93E-346C)9wzpN-N^T!K+WpQdLGKZ{V1~?%gEM+E0^=Ku;*^!@au- zRxgz2C8JaPpj>`tzt#0S;Tu0#C%(4UnswoNuX^e3b(M#%BPj79q4SIAw?3nUN1r^y zHMU>6dR8dK@%C6w!oqzYa!<-#dL|xYQ3fY;8<4c%YgB_xtm%J zl^W8;0imx7YHZzAuPUPkmKO6@Lg@f+K#;#XO9#vv5mPf^sKiYC*MH+9{2%ZCi3|Es zHv%r-y7v&Z5B$hW_a^2|Sew>-?rV?o?l<4aAV_EM4VpD=CWDB)RliH5ZvdziMnx|f zts>YFS0yX<)OIQ{pQ>AYV$q(51G4omX>~93n3#~v>0;+hE6N>|m}qbNY)w;UYP;uJ zvq05qOX{-V?D2i=dNdv-8P`cYcE-K8Ka!Z2y7ioi?Z&3d zMbaAGfC=5@j_F>6N2Bd}{JYnuZ4?GE<7#WoFSE22m&iW$QbWoO?4(o$cnSZLj9U@)xLG^k=Dk znR1FULedm1c*_kZHMboT>N6+FmbUglLMPl+#zrlS)+m!vD8oCR%m|sK8d>hS#-sAb}`WbR9p~!x4i0U;rT^w1a;K{eAxyuV%4#47*Ph$f2EQVc)Sw_wBl@h-6)!TUco4-3) z?@yiG#~UU`xpj2z_U5x8=lWjCVdRjWCy< zuEqC6xFPsf^U}Dz#(#Y?t2(_!-L^8v`#sHzQ3EYOUzpo^CZy%f zD#xg>>+Jda!rJxbbgBhHst1BvUzZ-(THhkAp4O1=)R`GumoGlEWIC$}A}ow^j-OnM zt*e<~GRoSG>RgNqsOoq{pJxj11BVWuVC&W;7A6JLX+=?FlvPcUTh^u(_k8=I*p*bf zF1@;rF1*>6tH>4>(W5cS=J5))4eM0vlc+CK8R@l?sukmU7ov8>b!<#zU7Gui)*`fG z-XZ(K2HKcjE447lMCu=0O?j#*12rwm?J{KOYO75nn4M!9noggFfyouu-0=|JMex$J zYzu<1Nh4viw(|_>zAE* zY0d@HpM4!%s75IPm-#Y|DA@iTVSM~Ky5P&<(3^&z>%Hb3Z~o4pUAkdc{>imp02LWq ztpbSR*N(oFZ%nURhiOlqUf{d;Uf+Ee4SPQ)O~1pC-Ff85#$_XGOs{K*Ua3fRI+Uc5 z2I|x&mIJ?g*-Ef{%%@eBQw;1xL6;%b)%qeutlb&r5jYE3YHV4PW}^V@yUlue@UqANkAy-v0U&BdFyMg=L=tZj5oddIu4(lvAiHW_S7l1 zZyj^pzO5-k=Um5SS5{P9$PaSa&KI3`i|@Q#+J8N8B4I8|Cxk(Xso#w>Z*JFbt8UoI z0sF3KBO6*4#z`uLGy$8t&Sl5ja z5Yp~@ojIPSo{czl@T$~7(;YO;Z|jrsq3Di9Y(%WC9+u~tb#8re~%XpM#(lnxlH2q7ByHKKi+nYj}|FRv|~*PLESTAPpUtdBC)gZcc1LCRHVn)$iNRqdak@8^VZnyX)ys9)v9Gh&)MUrQd3j9l3q!q z%|6jdr;>m~Nb99l>;j4J51cqtv3+?2qVP%*Fj2j^w^?ojVw#dr)7T?Xpa|$j3nLJ8 z=zv%we(s7<9nzT#ncQgnlmF$X6B3TPg?GH}1|EI#G{$INch|KnFBGUH#o?nXY+WAF zI4KLlowx1A=-BD?##dg;mMsNGkFW9iS6<6>T66s5DsOuAbv*XeX>Pi98{P+=JRAcY z&#si@dB${Frt+b*=c_9@gRyOk?v;1uTc@R0%JIF|_8FS)J)KsjVI*7`s2e80=pK97 z2OWxjM|&rz?j1WaEK$Z|B2MMe4cqpeVR`4t zjzy(^!J+XkZ8IpMX2q6W+ zqC;{Kj-|Smh3c2odb*;hxrw4&ZHT#P%@u#Dq7);G%|ctoYy4_VZkR4V8ovv%`^QQQ z8P!T-O_rEhgVnL?C$=ibw&X9}l=JRKOjo9907NP!=>~9U6MbMBFfzEEV`Q|68DR~$ zF($Grx&taIQe27gY4kR>2bi8YaB0c||F2kj%o45NmzU&X4i<}IWhHh zBRKqqRJOiY4oNPcl%h4GPu%mo8`x!EIY9j*7f?P@u;U(~T83k6FieD#~RkXgs8?|Kkx{e|E)9({Z#4?n&Ot%eu23r`4Jey{;>F`CgwzJ5-TvpRid zRr&^WeYe}@eEXR%Kg#M_&3oT=V=4_g z{Wu33*%RCj9dgaO(8a#v?x3}DE=Q;>1NEqz_C!cmR%*OjLR0TwXDp`%`ViF%qU*Z^ zGan#HPlv-W=y5RFod?V`3DPFDhW`7HevdcYbq#xVE)KS7ke;3+2|AnK#QSJC7mexy zK6q*u@GhoL@7r?~MQ%Cp;8UDEJB#OLm(&#~&(v40+S(_Vd zu9+;??7r!6q;L-|aP-kdZhpLUt z51S^DT6M;BMxir}P2aB*O$WS#l~X0-#jMMrN+-~!T-|Be=t5XcxBZkR+9ep;bvU){ z^PI}Rhx0YgSJbXX#NnlDMb{~!!Rp3;r3*;B>co$cukA~1+gTdcFgxViSnUQ3 z3ObdHj7FQRHF9hj7n`B2P2FC$D<7p}NTsq=zpSL1l9P$-PIE-P>{mA^8wpJJD*8KqZ9*3N0HzI6)VfV^Zd0avO8r)!(kuB`qxp>w z-_L*cQ!i1^3pME0EZ(*H#`i8j~$;#f~TFyofdU zzUE~fyj%+4av?Qy;I6Ff#JNrepu{y@M6LrTjTR+%X-h>7mqf-^f}m}MEiD}YI5y?kUS#+G7Y7>(eX@cR+8B;e5rd;9E*>4d)t zz^J65>41uzD?@d+jmvL;cfaxP|J~=cA6HD&o?P{9AzPj64bZT1HLUDc_^f;UQUEDk z3wyqBel|$ep3(1q^~#}$#WQ=~tC3ND*-BQ~S02DV@&9MarcS%iZB_cXvelN4wkY=!pK|j%asfBoaz)4BJ)9Dqz9LEw^!mv6}X z?mg39XMJlpfvAyaK7Iq-bz1@NF97`w0Ps-X$<=Y`wpJQ=kC82KY8X5K7H?QJoVyXT(f-)K?4}JQ2Jom~`^m_)|HqYaUXAj}tTeqX%H+cHR!`QuZ zy@XZ;%jAK>XK~YY8}ZT`$I)7ky?Zueb!8ciS6CfcY}+)4{RhurVZMjM$Is!DckjaY zfAlOWBQt$tRKBQpa$UORjgb-Qgv3oXYnNhMWN~jH*wtF$TiY_E6R-w&A#}$z_f_MN>k`GX zk^~z;OcKsU=EZRaHZG4dgi&w_)Qm?C{nQr>!DX0%nd8NeN@_%uG_U9ukJg6 z<7Zaktw&X9Y}q)6rPT&^-nf*LqY&0L9DuPGDhJW86BN zJiUs$Z{3Eaa-2pP0(=5^ zS(Q;yGjedPPr8&S$n_Q}6pvXJR0-9k6rvVwyx}HAulc9=0Nw<>ZvKVM1WrFfGjYBV9*JDnvtpPBGQ1xX@SPwLM1C3q)F5=;Krt@sdhFC23Ylv2Fx0 ziLEiIM~Rf47#q#J$j<~XV%;ZHm4xWraNQB?2&HJ!2xZ+g7MnIMqO}%F%Oh;wuz-`NmM}Np!^&zC z1gC_>#W@@}dF_bF>CUap>FdoxjhNi|=adAvN zOEIjACflzk!4egzzSHc^WIxiHE!9|q7UiNevk*R~P_?3rF=}KYNQsO~{F+UyO3AQr z8Xq~E|BZJH4~2ShJ@jx6x))d%BjH@pCBb1kUpBqVj4SRW+me49Opdv51Y>2#GtC+LwWyx4s2kjY6FOr(in~$I8MRfy=q$o3M0p9oP#CB%lS! zMqNf6L=8&pVG?_>bP}CDx{6IZ=OpCNcC|)+0?7HIuA$p4$%(=0GFq{r8_9;Pb#`dQ zpHD210ZwlC8#uF^1k5qea`TC=N^ABgX3S(@7(r3h3wG?j{OJ!2HtN?=;|!D%y-O6| zM$l3^l$0@r4n`bGNh8w{`-YCCHLmIZtH=KlON_;pcOQ9A`2HhzyfZfDU5up`Uu7)r zyGV^qZ7}$qA6y-7tc#kf0OL>Yg}-JK;Q7+gWhiT{9(x7m&13KEI?E2Lzx6rbO7%b~ zf`0u7>Yu*$j`vFdFPttq?73)v4o%QL_PG>UEwR&uvk2F7=z$60T+TW;=G3X;d=}$% zvR_>2I!ZY)n9|_n)@w#(OcDW-BABRo(Ou>xj*p~yx|_s%;?xN17JBH_dSV@&EtZ|h z&P<4Ir?f7r7*`d{OROm9fTZF@&H(;(vkf$aqA|@#<-7u{O9#9}_gn-owM{OZE-3Mdftk{^ zSf2!>He|!twp?H{JK!cQ*oBKJwNJ;lO^{^SV!=IEy$aRNqZ(}qLf8D9%$Q;hgmKZ~ zBPA^dfMmPQfGhwuo5S_;qF;cYN@2r}(^$XbWU3Je7B!Gk7@eCJ@vi3yVX?}ki2)$R zXaNd3Gi{{2F(u#{1(9~BsQ^LeGboHUbyrj}fTIl^oo!l*hqaLeXsv{yien}DIy!ox z2yBuDDSWN%AH(v(b08wrb_0ed@0M-b=3JgQ4vYJxs)Memudz|Ti5llRqf;^_gZg5O z6afmffc~g+Nf|OpoNF$0?$AGc?B97$H80EpV6G?&L()LJ`3Xj~dh!3pyz(}xr{BDK zZIBo9HrT-}&I4eypSXF7nW0llF#C>z&aQ?~(94&!+}^Pp_SRjOXXK{{>clzJKYa1B zlw+C$htHv|6*jFObl8_Pa!6pNXoKzq%yG(UiC{*w7R4P{XOZQJ1&k#x!WY_;;wNcJ zZ$xn3hy0STFtB*1DZOqF_?%Fxh~Oafyrjl5Hm&am5pEDksyvt_?h0YM>#bZVr4E5o zPg49n9o9uspe-Nba_6 z(7bR7TEf4LP9y=M@;l7@I;j2}RNV*FRd7@U>n2ec7vb^(m-rmaQvj}Hth)MzGBubB z@vD+jz#y7sMH0coNUVfo`MzhlgJ8bhLPpg5|o6(CggI z!h&hBB0HJ5O}&St=ZI`Zh`?_f4;My2OgSVkQo3BY{A}w3lS(P&IiAaBj%>i_+&b*M z?X9#e$18mtdTASMBi%_+&lAJu;`qfmaT>7;nNTW#G^4<*!0e!*Qa2MoXvZ$}odxg_ za|Boze)1~qt1?mnJfR1od@g1UOc)t!bUu%uCHW69NWy8|Kb#&rYTF@*1qo zp@afnA}CR5l&U5(VbZ8*BI70MV1m&1=lQ`Q@L7+6g*O;v zfw{wB^l+({4CgWUqsOw+{e!$+NJE_y#Mb-HGZ(%tUN+Q3sGdK7>bd=BZ@(7ywrk!I z3uK;q3)Ks6U3TWn?ApGN+GQ6PhFDn{V>E7ZN+?h;A%#u4SSYW(W($VHK3;zHAl%r6 zI}$EJD@q0>mh0rzMlt1V8JdXV?=UZ67LD2M$+^v10<^pjzeFLF<0W_!V*2BgM(|Wh zm(Ry>L}9jE}Wxh|f{_&dKUiEv|0(8hOQMr>xF@qIlorYF$@Y3g$!g(OzLWXi-|7ds} zg4L8bgjA83>siVLn_y+;nD|;N)P0>m3`oikonvTEYY1ME7GV&Q*2agvp}2sWTBTq@ zqUcCc0DLYVjLxSi%X5W8FWv}3=y^&SAz^UZ#=*7Huf(hZj-<@?1oxFO3aEquk+x`! zSl!%?9Y)rN9;5skvyGa-o6}sERO+_<3C}@%> ze?4xS1g$plLftzjftS8a3X!s z7vNbyW&I0`xx;cpxz_mSlAJ9@p?Y#3%*%&THA6af_W>7xCijC!jT9&#v_tHxA!<EH5>$2^F*@=42>`_gTWNBR?iykxcYf@{9bcyHWBrEr zG3p!LI)VwBBMUzj~|52iVj`+!gtfsbS_9VFq(hbsd0R} zOBKRgl_EePr4Glpvur3rOkp<*3IBO$eoI4r_J2f+oPD;D__ z*-t<_ar_1SJeWO#_#5q!hb>%2hp=;R#!yyi{_>+!L9{%Eg?B zLn)msXf%^sK~aV`k%Pk%eNV`h9+)VFR7KHUx_GAcYbt=t8u>G8yf`jjOB~acTBS}H zUzJt4IkV_o-@GVjw31VLj^Op2t6D^_Xbc^om~$~7aEuBEV|-7M#*lq28bzH z3!N{PO8D5IohoGUiJ4b`^B^cmS#~}!W(*fnr%5TWMki$#&Zk40Odef{`^BRUEz}eQ zwz?uzJq=@`ZiKp{rgDT?R8P2;MMvTkFrWYygwcrsaKLII+@s72CX(uuc)M!RO*f zgt3)ib0(a5asFXUKv}GzcPIo~Ibw^Bw3LR2lYjg>4Vw!LUV{H0ZR(nyY216W^ z?E*0dMDRkXJTdnnMIfW%cvUIUx#;*c{efA_wDNdu-}dv4b*gi~mM4Vvez(Pm)lXlC z*>`x_nessq<9_tGeBkAi_w0nV9@{qU1QDTaEk1GAb}X-q(X@IC=yzhlfAYnnxcAnr6Di2u==4%F-2pHii*yN4oMdYR?Mt^nGbbnO;XKSxMnt;m z0Y*yV(7CfznM=6b0^N%RF$M7KTx7LM2U+@-CK%|jn1

    j6U`60qU}YvD*ig$^uX zFc@CRn51nTnqZfXV;n{hsfKX4x?iWhp2*xNokv4$BU$Ksm;M`Y+X60>1cvRaOof%f zUYwl&0xS)nv@k6(Q>FwHy2_$n?^UWkh@(y}x*QVri@i*(>~k602p}?*%3#YVEN}c7 zmU^#ZS?>oC!KfZ~o%~JI<85HCI)QwNeNovF)!G2&iQsAv?{&ycqBKr3wF*{eq=Lr0 z@3;fNV)|Lx9-s4^5ZI2`)Xl+xG^u%^LfD&gbW|birD9}9nu-dAK34U$!hES!C|*gL zuf(ndU{49;>(mOJ97jKgi~$p{=^4Is&59z>@)-5^pNCproftvrk5=xF9-vdF&T(vl z7Pn7`>}LeaB$7ZkE_iWK1Ax{FB_0Kw`7S;GJ-U;kQ=nuCQtkv#reXPh(q0eeq5A{q{y>7UjQmL>qUa<_0ev&{Emy%s z`N0jY$ZF}Pz-CKsa1yzRazT%7hDl76ZYAesv}`e6u^6qi7_CT6fOCv~NL!7WAHAW5 zw?NxS60dEtMLV)HLv;dsPX4#>Z38$PbP*L)ZvfrvL-mKy{UO|72liKA>EyxWz&3~; z#Uqcg{B-q(vp&5BYjYP7drs$;E*(yW@b)$T6V5h=u+l7H+$;ki^y?vp{RIrG^|#f|xfB#MN2lC_<{%N>Ds@lj3aSUQ@RDAo=3 zYHg_KPs(2_h0kBj*$ze(W}=HA;x|h_U^V ziyIBm${4-Bd>Z8JM@-5`j|(#|o+t0#CtOD5!dQl!h0i&S8p@GH5RN)Ok@8vq7Ia&8 zBWSUXVKjBZqRxw7CdVnEB#}})J_UwCiU_0bKt!@!*lWx2QxxTLXPfwm_cI9~X0b0F z=Mk0NGz9Hb!Ng<`GZ}z4!7-&fWVsTnQhbc1gkm}6u2p@4WudA@HJF3y51{HE zw5fn9$Cf8SZgdnO$NpdOG0{66kL#F2E>)Rc0hSnW@ue#G(9a{ROE^Zf) z^3-yyZh!kXv9$G{z^Dqo>H`c3t|N`U-41Gour8-Mm*;8%2T?0y2&z}5(GwM&P5Jkh z*)e6&PZzf9irKlIkBO{fxLo_jN(&f)ZCZ_l~s2*7Np|uzFm(J(S zm41vH6RuwhukG80W5?G6#L$Y1=5B>AJoxOp92qelef*|1feQc(4qpJc5TW<&C!v-` zAHER~J8-X;#IEUK9jIwOVwf%jUdqzG1T2cSXJ3weTqyJFXexXsxix((m;ezj`l&Gt zxCAeWE$n1sa1q@%6Ugv1k_k$eq@jtC`NR^cL?o|G?$9Qry2WekjJ-MlF82d5D7m$! zH9Uc`4q;#&@Ines`Hl`|YJ^lWO!3Xe*EX4?+hJOKUSPe?SvxMj?hasKfQ%8AWiW)Q zdYNSjL0U|Ob0WBixCrjMT0u(*UWgPZgucNk7ysvVTaYd*@8KQs`${~b>osU_@Se|-V9^Qp{JS+WBq(D^#RrQLj z56KN_^m>q~p*f3PbdOXriyjEtHP<92{dO6Sh6Hw$}rg}@6yjr~w9x_;w4#$UYa;*xZgf;xN( zy@#Lwh>e;&bdDWA&3>XCdb0n9nNz+;*%DpqDZ1j$EdKNbc){ejgBh5y=qI4k0VLhh z!VD0yYv(MmQB_!?~pYlKA{$p?o zxU-gFg9z5PVmXevD_kgDl@``xyL|-40Gs(KP}PI(_0bHj!;!gPPB$5o06yE5!^hTT z8?*DB+JMYF$a!dOk)IMm>{5!aQK*6=NNWMGwsonTGLGb2>+|p7JeEz1dkU$OQBivY6oC@!#+h}oN8F%0QCXBiGpgAJO_kMKen&8DOOP|e!BI4=nD*Au*^rh=!K9DOe zVf8m2cxM#=N@4J?e)tiH$;?Z}4_w{}f+rU9z%syxgv&rfhxFYp^U`HurkMhC(sQRq zK@_6hi}?I#g(fC(BTf00fyFtKFJ3f3TF@+G3U}PLNrYQ$i}F>5VN|}jhJ#TS^!%F2 zjFzlZDQvhDLcHP(pJHByydLMzGcqc3cG76C5aV*!+MF%Zf$AL$Vfukxsp}9)t}|dM zvMNBiK|5_XntqQnic~Im0>9@6dZmO>@km13Qi$uF2yhcS;e4<^>q6%hMxCLH$62xB zSI8k}&W3)Wg6)u$-fqNwjMIQ4iva_a&~O@SYtDC=0z%@%QLT zfh&R`z$<`QL3x7r5O<(w*hcb-y5P@dn|Oyc;m+tsYXa*mhK?hhs6kV@1XAIATLZXs z${srcT_nM8W?fWfS`<=e(+5R=tF_1S$^ef%ek%Z=u3K!|dK%a7KAOPitjCkjUcWZ$ z0$_Of;<{~kaR__ER+u-AezYQ=m$LC#{l=#OO{jkSD$M?)A8H_D(xNy6Ms&l{x|X19 zW9Es_x@^NOH5Jot9bR)`%Q-2WGF_3a)Ch&qn{9J;^C^+>ovn6C? z^atn-=Art183*YKWTY6bbVYQ6ojTjCh_)|-X1EJD(}gYt5YogVbRKYXg|GD5gvH87 zkQnkyLQacQoIng~Ksm}9rvkXx*2BhyI*4tfX2do=HBs9(f6s?Lq?kkYkZA`r`TBlWBZ1a9B&$+^m3ZQVz|2~*;QtS9ebQPF-Fx_7!0c^K$dkY({^UB2;LKv6Gu}@7S^1>m+HEPfLt+> zo%-)D62UzxP3YG);xK4s5|&2eyEjuxaC2+;PkPloPZ%s_@uP_l9hw zwI641BFrDS7!rul-g`aTd#@Lf_-jW{KlvH}{qx7hFr#|vO|*CJe&^5O814NxqP_n{ zKr8hB;8BogeApglCiOui9SM^c*R-(G)OD3RB412}q{R_SC+lTuT0}XzJ>B(l1~Q3> z5g4VSm6|b8W>^3ZO#Gd*sP_W&fZSCO$uA>@VzGe|voJxP!MaHO6j}u{tq_ ziYLpvn8f0s8r=m1S-u$C zjeP(sw)GR^n%skviWY+?IwB6G6{^4>#BpV6LN1CIjnT4iV{5d_ufL4RkBev;^(X=d z#w4@P3?Dv^3v||OsN544+%>Uh$v1Jl6)QEeUWA#T0TDQmup(Nkq+KZk>tYLbv?#M@ zv}1Yh!MsTcyb{bOp*)cVN=dvfgan51jAZpFa1c~$R?wg#h1$#UM=B><7e$T~0ZIYb z;y7&*yim!~=;@#P`I>StPM%u84<5Z^VuEoIizNeR_W+CgE@g2C+zs2Xdc(HFHuV4E zNziI@)sCbudC`6OAl$Zf@LLw&{gXM5(XV|HbZQy>zj^9ICGs`JsyJ)CO&1NHqV73q zPtXbS&udWD&LFuQqVt7JE&7TW&=eL&?^<}{!YO-ae5&*@l+5s-oU*kt#j?#QFTAO$)iDe2w zbwQ=cDSWT6R3kDql&vW51(4}1LfQT-fQ38OV@Co?VhVP$_4}-MN8G-Kr0c1<4ph%lE^(I#SGT0o7%FN5Ize{<0DbhBxLIfz>t25s3A%!kF#5{JI_EE)Sw;V^p8VjBOo-5X z_yyQq8__Nh?EI=zhkcb@)GjFSxW+MR##PCE9cl(UcQ)G4Xoya0Mn zV0KA+L3NFKFc0eWp-h!SnbIi81J1$Q7HnI%@fdEr3fnf>LdsB93)@fUcaKqS(iduoFaf#)TrWTuc7N2uRjP4!7HAM!I<;3dbT^>isKIN|{4QN(! zy-+(vj-w<7n zA!sHjW#qV1p&F+cZ^YMSi~`lM8;Edp-Cw{cgSzU0;bC+IqbpRphSrs^5@8H!t;-{^ zR!SPdfUb1NV<9vnaZo7&s-6yZT!QXt0XJ5}$*s>8?NmWwGlS)eK)p$giPq=LqTz@R*H9vmTz5*`NTb?6S@3h zd5~l5{O)_RZu(stvHJDH_>K~=RdE|rml*3|b=Y9bg~u3lhgpsF5x75;7Ahh1HP8?S|qP1{U z0K6%lKc~2Aqo537hkFd?n~AYm7q$c>I8zWbg+LDs+xsCt3OyEhLwO2 zvzkBO_?(;{CvThf67-J&bB6#u1|}-!uKZ(AgO#4rXnvppp!K=@kQv;sG5Y0u0CSOg z7SFJIwxN3ckgRV%rz50}VApw{#BAlbqhpurFf7@n(~(N}ZWf7*5J-{)J9pZJ9XBmZ zD%g<~NXe{+VnljX!>!h6SC+s|QcqR5QxY&k;GkuQ8l4=?FZn7QMSmQ!BRH2d#zlUu zwULVTG_9cppfg%^aNzWah|{*}b`up^mIA1hRRq2W&O@iRKy*Y^i1DYG*P`Qyh|iL+lvs*;RNZ zRKo?B!2qgYi6V$0)`^K(lZCkw3{22v_|iGzSVW;=%%e0x`5^Z6PJpyg(Ck7NP&^S- z20B`$kx@#Xje^~{UBk$sQVrHEy#y~p5U{iGwuKw52)OS9-Wv4mVQd+`j5CAVihP*D z+FY;!9Y!G7oUduVfX3X8<8$A~=2I=MJ<-CqE!bJG|3iQoFW3JNY)r5&hg4{zl3OZ; zvxVQGgULrJ0ZU2~T;s)k6`WUXBd#o^08=ZVm#x|5Ekn8iy43xAkw5NQkEWA*lfxfN zmt7Vm$84LZNy_$br4>xftf_s-tsywep?k`QzNV{ROsQI6$HTnlxM$mA?|$1~_J>x0 zbw8(67JcbB?Swry{fy3cy{r_x($KL^ zUTfIZ75HWZRsjVX1D+oTdKVi z0ApB2E0KjMwliO003%Kx0l&&C8C3*esUc$rS?S`{-KRrYk+27{*fE?TXq)q3;@y2L zQREQ858`BTHcCT{DsbI{Vh_y>(gwOW2+WWX)~fE|8hjt);a#1y*~#`~ZRB$kn3&o$ z*tYU*a5I8y#<=$F2EJ`zTlvVg6*kUUT#x@MZTEx2uVK|}!x-y2g5A#Qs~In64)j*V*yjX zjZNz@Sv+J~aUK^&W{jv?FA=wE2@XxIP_T8;0%4apT+zhtjI39gv6E>+yi1fO@A(dmC>6*tN=*yTXs4bI?DJ~? zl+3hrfee&JH9s$7qMnS_NLAs2t|q9ESkn;oEG>M~z>Y_7t4r|BIP|!53nP;qlqTy7 zO7Mar#I9Q$3FNlxIP&tILEb|J2bx_u3pZXxHNOsKFodeZF=8P5#RcIKLSyw6W?&*y zqQy=YG!o+6q4HP_{YPDUtyrF&mAh{5RS2k4g_a{TY-RpWvN$V1H*+AZ;Y|fq_hp}X zpH^oT$}v^l!}a>RIMn;ae0)0GK}*(v+Xiktf^Wy*W-R)$b_|XT zOqipP(%828d!aU>#?tT(93FnTlN?>zg_RaCZ^H2>T}B+rB7@TkNXMD9XLAA$G0?Fr zSWE?qrWlPSYj@E31hK4+mgTS=$}E}K`rXDHp2nrHz!*P(SZm%;`deerJax?xF8p!Zi#L!Das`5YUS3z7G-D7&~g z69qk7$VDK6pQ(8%dy1x$X}xp7O~ioqVDCebAFny9wIS{&>Sqob?_t6DCPdXx4F2F3vP1+|8p5?i@+Jc)kdP(x@o8k|rG~oC4>{(UG48 za*CWBRrkbA6tqN?G$VN%loogn4k30CxQt;(BiPj?0TM;qwo=p$>7s5Ecc(CN%56oGZ25n$Xp_+|jMjQ|&C0cJF6Jx)~jf*Dvb z*Jiebi_8*3X}pul4mHrnX{=j*9xiB{;_-lZOte8DKOVz3Bl&yV$iA*B=(?X);)T)k zSm$4ds{43(`0v1n>H{!?iY_2o*bS`lFkxGGpYISo0Co(|I(+1gd#@veE|P7d)jE|V znlN@tV2FdOh+rG;B;Ur|o_6d5h{?^~0$`AsSVcL^E?UIn$S66gY7J8pyf=j#O(zyF z0xzq@M4&C;HDA#nJL}};Wno@KE1$mqB_S!S!m}@4i&JOjq4jJbD0$$>rwQv`X3QPB z!mE!54t$BAY`&B-$=FIYmxe{g_uq`(#x@zLJ43q~oG z7D{pG$U*IcjwCM35+>z4?u&_pm#Nt&1>nIp=qtPhyautBi<4)tVoar=aF_LAU`n{j z=NYn6$rmR|xnK{d=oN~EiIg1#l)6-?qw7csx-{upP$|fb0r;56%f2&C>1bP`8w*9a z-z3|DOk>A?PeJ=5<$PIyh%{0OpC{(aiKx+8$kv*B077t%$aIdn3W>|izHmq;&dtoS z5N1sYOLhq2cu2!phO$`?BArMojUy5`b&|%M8lc%?^XkKZYoMBy04ic+uExQ+U&E;F zg@C(|hcb#~noVbc)G4}O^cKc5s#-&9hA|qOMn8+mClmWCk8o4v1-Ki%!_y=7RkaoS z^smD%S?M=&*~MqdF-lLP?gu#Pkw#}_Ka?*RsacgAh%x@e1%Qdxf+kYes=w)AghQQHJ z6~HC@USiuAAL!jniZ`%!{R2b1D z20*2&6|>yT>*(T9N|>0?$gEUZK1it~5uQ8qX3sLN@YX_^Du4i`Kw7^bm#x_7-ihWk zR}^z8AG9->MetT;^ht|REW)Xmg;c>N4N>=$;A`);l9%tQ-(?Cc} zB`$SUS7v-9NwSdeHy1e@l+x zFrsl@_K_Ul!fubPJs9j+AV3P8_$TON%Zkj-2QOc-tUW|HN7jEXYOwsGQy z3h%>NpGH)^XRzX~L%Y(#Sr1cd)IA1R0tG3sUEY(hN6v?2<}i}>9^O;hXZc*ea*tbj zXP}7jvz1NgDYqtp!A!XQwgY(n#cOcl)O6ab>k|%s5l}5->rX_?ds)_54;=rvWN)4C zXAV9@xaKeU;=q$-f12`5xVoNpdJnj75lmCto^&d-rYevi)!IxgzQSpf^LGtS<0{taQ4@xc-gfAn~dSSAJY+c@rB1 zzfhNYVGg!UA3%$YJKSg$?aERP-lE_@n8C12k3>`o1k>SyBZ5EGy?9aXeJQ&LKX&Vu zL@p%I!VD;BAeIZT=zQ2u9)`7sA=1<+mxz7&(nhgo*K;khQqoJjXWa ztlK%k*JEM)FnrU%+Xk?02n7r}t^nQ#^dxSg=kaRq-$dirg_dfDZCqGnkvfE;Ks4*% zDO-VyyZwXs4A5hk-U@cCd>i{WEu(Q7ug#6ov?H|6qjfH5bP)1iG-^|$s(RRV)}UTe zAQ&j+#3kgiLr5}ZbOKen5Vax#I$!jmc@+6TlX|kuxFk(SlP%6N0?MpO+c-EUI;5&L z@SahzO2S*`7^FGm@Ngb;lB5AwJ(coal7>iUF@6LmI=r{KCl+W^YgF<57S`#gJu0p1 z^d5)4c-HtQ*E|YE7XRA=pTQ~Dn>hXn4}AO;96Y=MufD!>&8BGbz}ufA^pCUTzPyXa z{6V01nsM}#YcMbbYb&>@o~29w3mHY*yLn6hg};*2411{;C#(MBgWD5jJ~1|{AZ zX*GL%qzX%L9DAt=H_fD;qqG2XDo2dveLgojvri?7olE4c>u1*mDstJ%&3U*0N(;sEl3(|J-IhQ6DM+SDnr|l)% zigb;7VIA~vPTVaq112UiDrtzmj9WUi<%hRXnSs=FyTm$acyJG>$!{fv&|y1M*5S?eQT%YU!? zvBKfX-Iw~qd)K@OD027@-})?8{Ot3gX$&5H;+8c5OnRO%u;WLU$5!1e04MGNSm$E7 z;X%gwmvPAkB3fES|JxtXOcVBSn-_gFCbl!cv@4zXp zD~(=HW5c>32taE+e)`J30uC6shI?r`F;@J)kuv?98e6y}x3Rtb>kX&s9$ zb4n)1N1aiT>J&hBM7m{~E+#F&zOXa71A~SKRW) zcoNi10G!F^EXF=%o&}-I&FBi8QL<7KjLh__<08n{PqbhMc7vlJwg4~AL)AT03+rG8 zbD*jxV~mtrqoRNHvVoTlSV_*4z^;rX@;(bZT^iqHFjI8@1op+XKI>Zw9Z`(Lk41{? zJq$*;@yve<*Nnhz3)ha|n+9+#ymL?zk^-uvYC+XK9G&|TPE_}$ya&0{7ol#v+mFts zsJSUIL0MBqL^wD1JdO>1fYEpvtL+NL;}wkCRWx=4fY7V@=+|@T)k6&GA$s)?{c4Cg zvl&~Ce=P}`BS0c5nxnNO%IaT>F9z3Ll&@X>`h99Gc&aW@OQh!!{57M+5|S zkxC<@Hh>mqvn)A|cq01~ok6D3sCtqE;(|h(+S*|O7_o{yr!QIyhO(P-`e*D^wn&JLMg`gAGy67PCDy6*T9yaFzR!ca{o1>W5!|K6>WE3tqL!%-%-v zck)EXRc;#hNmyyaXd;4J=NP)*M>W3)-Jb*1HB{A;#XA;xMuu+kcfSMhB87n2DjVbL zWjy3z8^Deonh0VVms~2%NPxR-7)|5g1DJ`=7hPiUSki`43$iTsU2*o!OaC48=%{3^ zG$Z(C3~tBCU8Z}Io~-H~blr!lY8+ksDweA~AYDrq35v#RU*x6)urP58F2l`m9)c+fTe+*Su>;a~>9OtX0bzY? z(D20ZPzu!Q_IGs{LIPf!zY*gVi}9+J?xX-tNrtk2tsi12*dH=}2kU1ej_S zD^^RPM&Zd(3;R68X4Z;-?9gnv4KPFgK+XH8^I?ne=kJ2wwqfm>1|p!b z=>6qWP~*#ETQhNN(fL^ZNh>!&a(8*n1y3o0*TFZ$3ecRCnM7Vn)51knDW0j(=#;<} ziLY6|67FCM@FIzt5wxhB3Y#)qFgs|i7!k$0FFMbeo1^@rh9G|=F9Bv0M2@656-Sou zxm?(pXU}s=K+ui1p_xU?08cO;89Xtg8yt5Y^peL&U8bcJGXr_V2I{&e%Ju} zPkJUIg>$_-&{kUjqj9qTKp15NE4w2&>yjwg1!jv~ZXnN{7AP1td3|2F#4v0+^5wj6 z8;_-h=b)G{8oUnD9_z<9HCS}ZSXez3#Ku1TfeSX_aB~FbgWJjnQ8^dF z=7}4$aGdQJzk>1lo8W6L8X-+$xh5nnOWl*3oYF#GGEVGy>KaOc!7WEXN)yP%AUr^M z1r;L&QeT@2<&M(z1ZJ>N`Ez){kbo14AU(P&L)MX#n;BmuD_`!%Z|!>spPdsoSqWNx zw6YC-lEuYbz%t~Vx?}(|-bi@sOTaaM^**vNS7QSv1LI$~9e(q|mAC^#d-wII--m!c zHX5T}`$T4S&(|--3{)E9uYL?@Ee79u9PjoZF;f@e@cAqIPGZNFIn=d2Z#DsyfFs!% zz4X99BGn1f!0Smu>9~lypM0*|pHpPEC_pRS0WnIc1Xi@pfTimkq8R~eaUNcbh>+vJ zXAEo#Rv|dDf(X)c&Uld~Yoz8|^Noq98@*2#x)myb=k(a7`}MWh zz4BF*+e;O8&;0kUEp}S(QU>n%4tOCe&*Ny)!IasXcKIBXHgI7dGl`g*6(nhyLSSOd zyIK3qtg*Q~thcbPfpra9+rZi;fSC+n8aslu0pQpM=hXACa}C;l1Ls=ki1)W}I+kW=AqpVBBU zF5)5{j-yJkfv0Fkl0GG^3FLC%Tckocu_A3zfz2`=JL(viv0rE(;=2jfQqyb}h|yU<>xa-((J2TDoM zrB`J@#N~SomBmk2H&1;%0+$Oe3fkd^kKG2PF5MHYEO7Jz!nQ{l{C)tKesvjyGne<_ zwk}*5;1Zwz+RgAU9)MbU?*jVV_6=x0bIa^Lr3*bOgVnEm41+&?;$4Z34N!uKyzty` z?fRsBDLZ(&>tAd0cyudtS~Bnky%LaJ91-sf4O;xmvD0LLnhN~j3@n-(d8CRitQ$1#}+ zIp1QO88R-?csqh%bi0S9?WhHlHfw|wUq|s;N=B$7YDO;C^NJF9aZdhy{Fq!`WQ&eY z(M>gHPQe7mK=l}^szAmF1ITiGh^3k?Ik3)o2Wwkc*TQ)V=UZ6c!rCSQ8tWQZ+XfI5 zn3#5q#*Gu;Y1Jz@w&~gYJkCPfc`!3JpZX;XM%QLBs^fIWucD5CG7BQMXNJ;Z;f+G! z=wK4Stx|uG03{Mipi+6^cHL|m?}GltdF1kGNq=P@HDjEa17tzAClb5A*U~){awUC; z03c16UpWomIKX)s8?_?Xhx1@7U-M4#dN_`#1Arlxe4JToVp1VD%E)zK&Yr-{E2qSn zs1;t@e0vcR$SK<2`4|=$M`k%Syae94H9W`tv-c9n8ILWF^#F2?XTYKW7tRgOQhnhS zTx3uJ$fk=d$K_WFFmCjrWob zs14lab6Q23paGf(-yv{`k3kK;bv@Lvv+sg= z@e>PO0bpoiVe}}+9p#t@$yE^*>T(%W(o2KTZKGybf;)8XWK@5Vh#OcI6+2FpDx5?U zA#*X_|2$$-K<+l>LITVUi;%T~MF>)p09vwsM5TgC0csRjDp!H36tYpUmVw`*w0CNfeaCYIJL#@*=y2i%Uk7MJ>hr)L z&&9PqW#5#E$7zJuxxnU_1*HkF+0w2x!9;s=RUn<9Npg-e_z5)+(XLL!nO*UcSVpo zEz%P}BQ36>|40!Mch1=_pqw0w zf;}jKg4VgCW;USBLRlFva*F(qV>U&Q1w;kvyLg`wz~pfa&zNpZzphDUXo?Q%xQgVi zp5bA%nmHz#4O(V{kV(Bw4yBth-zsBiVlr?{{iQ;%92%J^FmNK|Edi&?<$IQrsmM7G zx3UD+j8QE(=)n+RFGZB`1t^_F?H2=JQs*~&c=&<|^hu!VV;&ECc=iHrSip_|o(OJQ z(aW?WG;WNh6;{T352FpVuFx|MC;C6Z((V_r`|v-4ZhJ6>lG&zQuv1!qR?uF?7lu_@ zXkz-SiYFK)qND@1l~RGN35%xVoB)dq4k9ouk4eJxzMa-s$z$7@w?Yj<1TE#CI7$j4 z-WfoKlbDy&>n9LM2Rpo$rb=ZLNHfT&R35wG%-c9J*e;{B7$#`toRq8=F1nM1F%io; zCy_0C#%RUDdq%Hs(2EJWTEaLv2=G-j7X(n^V_ii7P&#AU@bie*1yAYc5ZIPNKYvAt zmwc|hKaVqe3BzOW)95H_LGHR1?LB+Y|C1*`qvrj>E}-{loWl!!@WKFeZuQCl7Zia)ziT6fKJ?Ck3llKjib~v&@tPs^l47cNf&o zcqF-jFf&9>@>x{Y!F24;C`7tQX|dh|)_M&3Cf&^o<;?-KP`J}j=N-qC7i|^ZZyJs0 zFhYu3kb|x#U7$*L&tzvyF^8WL4Hs#*vq84pK`VuS_6N`6w}1T(w9WxcIC5ecTQ&|0 zVQ{%4*Vct}M?e=w`SNzTyRsz;JkJ1>$|JWD#6;~v9v_j6Gooflxx~yk+n_mp9Fyj9l2x@{J#z#gbf|%q+3eGHour0Cj!)QtSj*J@z6d;{k7Blx*~c*f{U z_Y~BGC{N)Sv^oZqLiO}M(76%Rsij#L|JhGF*TeXi?!K&IXt!;hw5eVKfMG=#{racm znqyr6FWhyiOp+~(^N4kk1$HPX&^R)Y?*;K%aiS8k05pncQ|)~Rtf)?me~c@qP`a49 zL<&KvRuVQ*S4b_t)cN;`CG)^%cv*PHvFo2=p{-Dr7m32_%$Wf)gD^ein z^mU~)v^MbUptXbc6^str9A)5rPwvc#U{nR8D^#XNt>&=d^n+QCVkgA4-X{=}LeLDM zG9=b(8;c@2*oZ^$TH4(C7?(s?VQjo(u;G+T6ss6gj6e~%Mmm3tf>@>UNK4L7!qS-r zNA@k@_>RrEr~eGNU6vkqOG=e8Rw=74!N#Rc6OS~!Kf~gTQg$u1s z_qbs2%nRWxeNTQrvT%YGR8U44@}g}BYj6pQJ80c`*mGy3CLn-cMGCA*#+Pyb@%is2 zgw@mGxHHhohM+?Or8N3(D+WuO(2f+`7-+{iS+^a>YJgDI=sc`m!nl4LM>hN^ym#q* zQKX<%1!F4gI`R)db`X-Oy8tGBj6hx+m6#LO`K^>4KwR8u*w$mbDq>h7gw$7srA?1x z-I-5zBlwZ+_meHnWe}UBS<8)4>g4JF8Ll~b7H|$X?(RdmWwe2fr@9ATxwA{eO$x^+ z6QCp32`(hTAac@iC^l8%DVRD!H>{k%(S@A?NIU>df%PEhK;uYsLlG7T0b&ufD4pN? z^85=pviRp{Yy&^GP^6_2frdESe+|Rl0_LkN*naMBr6`9^|5v(6D#1}P{>?>U#SIMJ zUp>Z*U)?(m?D#=APs9FM-3*+%o!~2+x0JCgZuD1aM%?Jv9{?0#@UMRK-o@)*?J@pY zI2j|juJ}V8Id#$7#cf)c0xki(a7UBT4Ls`tnJG$r>RbqSJb~J!HFOl6%#bqiHWenS zi9*Gq{dgjDF6B0y2e6dxnNq`1&inJ7TqcS+g{UDjB7tp)Kql{dnyCwzJ(`)+nNT-w zf5y-8MDGz#1j13V4^^jf;QZGso*`)PT)<^k|sMpbE;fyLpSzXR4S3C{}dy29K7+5p_E2tYJB;P3WFw` z(<(4Yp*!mJ_5VItRbXR5ig0NA@8)9@at?m>bqDJ#*jj*3izcoF9;6t4)ZM0A_NKo3;|K|-a^U?JLc6y7+}8k z#B;{A461~cI=c8*SRS9l%J>|{%_{oU0K@*GjAu!s)iuWYESBb;$NJ{ZqP@EiwFkFY z*+>m48`LMRQFMi{OQnJK-G`P1EQtO|V8_D~V{bok=wAJ4{GIVibKec9pWJul8K2v( zfxUhAd(XOD%@3o{`_YRRW?q;>8u5mi&L%UNhT5@ABWFHLx>-u=bh)r53ZG-1L~&&< z*oD&0tSB=tQJ^~sToiR{>dW@$GDNN0O+?)`)5r@@_>=Fxg0Fu5 z#saudceJwR4bIx2q{~Qk!PV>~Zbo)X5u8`X&R?9Sij!O=-XSXzsvR7Kx0ml$FN+An zK12pET8W+57e0FSlC`0A1TYL|8@TZZWNK(_z{&?py2{-+=W!enDO9=!xeCh7gIb4% zUC>H|&MIGsFMVl24pjmnQMVaOB|z-10SKfkTyyxhr9X!VPI-8hMdIu|*d(8{R9;k+ zZpS+eNMJooteb$uM03&(y#X|x%~XLflEwk^DCCC4Qu^TlWbBRyqg9tPoFke?H` zp;qa9iU+zP0y`BlUv!a1tt9`=I@mK~0cpb?%)$WLXdsM_p%rdA{W4zNa7(iLdM(W& ztVIx>j0mw#$*};vMrs{mS!CrkHlO%1+6~_Xn9-{S&`P5+JyfO#tt)6{ptXkLZlP<+ z(BT+TXl1156u6RnnDQLTEKQ{7FF$%2{N9hkwaj6B=N`CQc3t+QYW^U10un%%Ddlx? zvE@Mz_NMKyw_lS1E$$8rNv)^Kuj5DY6w+ScH`#tPEbk z$qj#mUfYKvjXry5rSWUe0&cVdHy**;2CC|V*#%dR!I&N1s#ky}yM7S6zequmh8vCH znlacmq5awwtc!*+6}YOUgQI8-o*bBqGm6M=Kvc$i8UJgqt9yJ$`5H#cL$ng0a) zxBq{GOHje6D%2rJllBI88|GJUL*pGVcAfnhvwGq&pkt$Ttzjz}Gn!h%J4V&hN&9#u zr$$T~^>c3l&%Om7)EIx^4)CydMJqS1`iCO){`wiH)617-0d78a1KbVU3e|Raw3j!o zpFD8(M&RuAk_3IZ#)KCIhTmo^z7Cl2Wdg09;n&YYojFe?4STp7w*^LZ4e;We@74ko z$*~cr967O!Hx8V|{kLxwMgPPM8xz`w(xDM`Ess5O44=AZTUr291wf}9k&-AkQmSfV zRxE}DnpzY)0d%GIWomr1HXD+empDS=B!KDUr4)?I1rh#)#sxDNph*xj>v7L*+qDM=UV7sc zzVL}%SwK6<&T(M0hyqK;=~(d*-1;~+h#gw-cw#sg7Ee*TmX?pq2AppfMTR3<@C`$S zIDf4P&M0Wd(6vStqV}UWmb8SY`JPXiBC#y6T(lUWdAcZcv>{nx%2JD7U#HrE*q!8kE-5s%MpY}!H+!*T{6(Cce?&yZj`0gGH&A8_uKOUZq1-?| zRx&c$w^`%aZ4G?mCiW90@S>H0Yg%wBjvNVqk%BMix(BX%Qs)ql_xcFba0oTpB_dr- zl9A$-gw}aU-p$8i29KI*aUR8>I;|w*MF)+OmVmuQUcpj5mmEf%3RB}uSS3&&!9{KJ zK8vOTZyA1UaKq7m3^TCc`I9)i{wJt(g@y607@XJ(XFZl(lf=(y8>y^SGO<}Yd~}vk z)geT1s;i4Zq2Az%GYz8#{XhSiXryk~iuS%6t_l#NUpj>Pxih?88ipLrAZvp*N zxOiKq!Z(O+RiEYx6abY0kU2I<8$EI~XB%tHFNv@NI9qNiZ zzyLmZ_txTqn61$r;4;CQbU@3D0rA@5PBC;ovn|sM%xv&d8hZ$YqbHZKw9?@E-Rsld znHmwzxZyt^IO(S7PNU*kL3s&8mHk2JiXk}w4(6D-k~KRKXhaf#r(SdbFvV}}0MYQ= zM8FT9IE1}>Hel1bLAvw&qwl_sU;X?Ia189+GKU?T=VqQQQ#zyg-e<{bh>CsJG3uuU zj}bCA-oedu*xIwOl*qrL@E_oC&a3KnWo0VqZXVPb~S3BHRT z>%NG-n^lMLs>NtU+N#+DrdH?=O*ktIYTAKa_zlrnH4dw-P4y1e7F|&xlgLyWrXuJ{ zqiSV8R#r*Ijn_$oMrAOeA}HmddhelNgaCc;B-)SPmz}_~bTW{L_MG9uGufBR zalcOpMkj- zZhBlw4{mKM)d->9z`8c*+hVAj4q6X~N;6*DV6gXC4b7aG8#!(iR8;}mK-aZ2V4Dic z7_mLq8mub;EV18+b2#19#VLkND(a@~Mlr0`P)5Maw&ob#nqN$%jAhdBglQoM9Q_2LT?}#t`~L14?+N{WgX^z7ij$}2apKeh+SYU@ zAQRnJj?#IIe&v1){?#M1M^?Z82%3BLz}>WcY9TNZCGNuu zo@_nNfov&ta*bAET8plnOtt;L^?Z*%DlWo>BQ?5ka#54)OO-}J znaxln04UuBN6T~^C55pP5%AcvZ{rhpZVyGl9Bz8lL`YtD-<6!wWX6!6Aq?jUot0+> zX#;4JgeVm zcBPSYU}k7#U`&-jO0Gzdjwb;$7Dh=zu;|hhd=Tyb#jOgP&i*oXA0k}izgq})HArg# zEmaSys-Wr~R8^zxoq!+Rg8q29a4=>7&>;Z}@EALe5XJpQ1wn7_JR+m9qdAIWbKBFt zERQpuh<%_0NX3=qLa3b%rmK0ay>gs+aPpuJpt0*m%|4!E(|seKZb_mz(&2eh%) zO|%i0c?>1}%4^=e@_D|O7kcWX@J{yjOo5D2Gcx12REqEi-+mci`@)SF^v#8#$E=YJ z0WZCN0*muK?A&@0t)CYF_J8sH*YHPw{Sy8k|Hog#iPI~%{+bQ={!iY-{deuexN&&y zm7}=pmTj2pS9th|{kZqG?I0q&e(V%(xp6Zz0e||vSMb%(-;AF=|2Cd``6&Lu-@XSA zKmI0eylxXVuOGk|HEZHBV}4a+BFB+WP#|+)RU&|iKqPBmqW(pGjsx<^z)7CZd&d2D zZtryTtPNVY17Ny3oylU*2r7Jbz2n7daQejP&6Uw3f!`rX6EUE2*WL0raXqD$@spv7+C?y3{8X8mV<2Pn05H z0ZO^0nqzN|5f_bSg|iDk!RmMkqh?H=#4I2RhEQ=OubZ^w z;Xrl5{myQ93@>l4(4O6Zy~j8+C4qq++tv%R}$5*8mSV>D-hi47kC(TgJN8 zlih1ZnS~OW5EUx}f|a_c5YRn?s;4{qF&*~_LCU#M^)zhHp%=gj7p<#WE9i<6NOU%X zpOpQCI7a1e6ht_@4KHD1vkyZ)i+Ohj+76*?AKDI~UHF3`91nxjOu-wC1}^D~D2(eA z>C4`G1omh?dGi(1X}qI{br}D`?V`z{tIZZu-08o01nsBxzPphT1I;3E`Zhv4|L!y_ z-YcwMCrP=j)mT~@Tyi%RGvSt-4q*G%GwHfr0+$N{VXv?-H^Kw=zXT%2Yx}n2;M%o-WjROF7acs0UP~r2aN|FO*ElX;tIiXSyL*2&b z39EBQld{J1d(ZgwFWr3JlbbFAeB64&=8N7@L~D$O!slQ4!p->VLwmu@SXya7ig4_N zsM=#=b!8NmR$KhyXKui;lgk*5EJouNV8-g$rbWIs3LAr_gaPc>GJhVCP1m*^Q-=TR zfAKhe;p5lh)*Ck^05jA6T$US_LPX?|Ptwkm&Lb+)&DYF;!31c@Iw@a@#6wKHv`-5g z=)&LQ=RSNNN<;UCpfIX{*5Hs26oUvmDZ3YgNGHHme1o2Is9el^kx_z#*4airmpk|j zilhyiI|icIW3bLdwd4hClj&%v`3rpSAYs-s2Hwd@bWb1-fJ!__^|?P6xyv^a&F z^Jqp6#wa+WQPq@KMIyrW?eD|u7OFjix#c&3RRdj#rikhR%wPcBAHw&Cab5(a4ZJa+ z)_|%S%2>c#cxSP~V^G@&SP7tI62xewFAFo{7lslWe>FLdh)_MX@2Una@;Wul)B9lW z*!_+fk~22}%hymEv%J&CH9L;uhCN5SL7)JhfB705Ke>2OpylQp4r0f)(=#Wx@07W@ z;kqN(y7>&AcB`9hQx%~CaT+Avk>@rTfcdP>d{N~qk>geY`xn~N1 zZQd}%?j3Tl4Yb17zOWYnaOd7_xO49|c+VL0Dy*!wIB@tZ_FliKqfyDtv79y+hq{^n z;NSRoPEWqLkmLfu6v=#(|Gp^X5= z9;)tV=7kixsb4fD{9W^836g$Nu|c>;JgDn3otOReui6?pMf$JY`qDG=f8%PY7d|Y zw()?;;eM)M<5Hx*A*^5dIL>bVAu3bDdl$0ll++cNK0JG9FA2l4;ENbH?yF>z)*6}w zurPaAFHPD+3OX#ZMprm!WYn~-Z7{cL1>iLfE{xWq1z%S>=tCIBh1n-G4zAmS#SLR@ zI($sD3_%DTbuV0qcqyd|s+1@#f@k-M0IB(N9jEk{&)W|713(yhh{u|IkEx=3} z7;Ruojg4nMhmE7h06qh_V{pwf+-L=UBp>Z~8E$n2ZnT278A0`i;Qjz6R0?=oK{*%P zaN>yb-b)n*GbmJkd(SvyT2Si}%c7MDqq@L)k%CqNUQ}Sh-VGz8&MnKfbyt}R^lAq# zar>QK#zkLDC*L9i&AQ7l_Hzn1>^U;k8m_d*(c|mZYz*&iZpJIG@4}{yOQ@^ME3lcL z8{w9l58##8c6Ha%>j;bc__AdL8Ry&u*o*TET1yavsS(YjzC}%ZUN{Rn;d1gEwNdyd z|I<(Lzxn$ggY&%RSc)bxWlo+QVZ&lyPSTV$pBbPchIJ;R;yow(;{33ezVDn*T9s(C zj6e5IE+*SH&tLdtQH1;N+6e&IxUP@?%YXGZ_|O02hbCB(xG&;(sIaYF%sE!*19+DI zedeb;RoMiTaR-x~Sw4N<9R>Not}vW)61N{3f~~Vj^AU9i-FD8~7#! zz_ksSz2v6UJuo|H9LKfieg~@Vf$AQfAN)sPM{tJWo$9bFQ5Yg-X|`*omgcF`RX9jYl(P zG$Tm?u6i1Ezvv#)l)yH#LvP(FEUm9nrHb+9nLCEojnUdh1jw#| zb2bT(<7?&6B94Oj)!}tZU||KVD;Qm)@-2?e{WaDvdnl~JDJ}a#8?ZJYT|t=|Tzdgj z{Q*cDC{sgKHJ}ZYF$jfFq6LcETdxm4-fa;_8pl2cQp!o}zcK?U;bAj{}E4&2as94%T=L zPx8^@i8JMP?e8ZW-G8@dqndLu!Sm#ggDnBD@`4Mp^4DvdK| zmSGD(lLD(Qg65#Ec%>Uk7enSy1kr^A-bky1y3NY1^Z3Vq?>+%8opI7c2hfC`W%K$$ z`aB7O(M{ZqzxQX)y^W9ExwBY!V(j=dvoiTnbr!mJI_~v2esTrdw_F&=Y~DDB|NK9G zXzGTgWM6VDK2M8cIyUR+bly(da+#tWtn=*A(Wu1FBa74pETxtufEN$=aK{;ei-4C5 zT$~H~5$A+)vGR5A7-nG+W^NI>*9TSNXo1#g49U1Sp>EoCip2e+6}(|6FIH%0Bd|dL z0v@F0xGcN*XrMfZG6WP9AATsm5NfuAlluv@)cM)W;5l=g` zc8tc2(b_SrYth=VSgKh@URoPeriSyq1Q1RSp29l)DQKhME5I;7WKi`rR4A1^w)Ky( zQoo72SN{*FdM&oza0p5f+LjV1ip-P`i@#JsXsqtg7<ihT>`dl`E`VMrHw{h+bIUQ21kr^cE>Opjgd%8e zGT@CSvr#5knEh{`#kNiJ7!Iq6w%`)vWB|hq+;_*0PH@|-=l5ZujwO)*(6kP9)wTDn zjx4mMsjts^Jo>Y@@W6e$VYE6ga5)uOBurbwXR$9l1G6NiU{ZHdxO#GVUrt>1kuC9E zVQu$0*7|!_gqzuxpbv>!5--A6>m_DC0vKmKoEIR&q)=^G2R)dBuKR$gL1uz+A;KCn zyz`&DTEQC+!zzh!C2WqNeN2^Bc??DX$UrNCt{ATNa8_k75k@y!3vg-1uE;Gy(RUNh z3vI-592P)T*ZFwV8cGXDTN>Pnw|ZZP9ecRe!ucQ|4h5)jRAedzQ-zCc06?cUejn$| zt7t~!z*MyG-b(332%xKUjcsSXivIF-A~a^ksl`WdV(wAV{RAtubuAh@2H>GpjT#6H zfh%f6Jl@{*KV#?H{}#0I!9JV?;Yt(kn*S08i(?EH-UJ|k(Nos5h)umH&?EqvMtir zB(K{9z~b4#D;bX&ZIX`aqID+E?1y>dC`NzlzR>#lUeg##TAtkpDDjs)IOrGO6$ZM* zx9mOPa}T^QWlsix!^hX*l~;FNGH@v$%PV~xKDG{9H=n%>c$D$k4zN^TGBjIu~o5{2Ry6bMr9s3sChy5@AgR(h8vx7^IZ& zO|wQt7sHAXU<`%CVil~=NLKN1nt;edYgtsa@vxOjqbw&ba zWE+fm6{BVa<939`t_HUgONWo{po!KmUo3PMF+qVx)NNlB!EG)$lkq#OV?L(K5>5MG5 zy!}!)lmU#B@A<%}R*oKbjwR}VLw ztkGZXL${59mIz$JF`c@dv`%1DRW-P(@%q*ZUK4-@#4VJ~EDI1EU0SCK29;PB4M!Tv z>jYT5a)E(z(B1_A>IDKaBU4xh9 zl^&jW@+Q!v?uHqgpIRe@ml@U5Z(KTfxo(>Q5pewYahy1Dd`6I4nTImFG_WgPrI~_U zno*vp5CWV!W2RZ41yiG%D1jCZ3hs9VT#E6LsZ=LCF@}n%FpANJ&^829iA}jI zX^fp;D3~#ECy7Q%*S-j|3juenN3&|-J!92h2M}<)`rktv5&RDHGHz)95C$uFVeTJ; z8W-F*Bwb^4qg@wGZ5vbDwrx$BscqY~?Wt|swx+f<#k8Gj+J1T0w^ovs{K=EtbMHO- zJa?bHnV^cn5aUSd7w&Uu#Rl*RSnEs$eBIP7-+#2k zMR4J}B{UBF909pGS$daCz!IRl(=v2O#hgmEFmuM%Iqn@Y4>&?O)WTW}M<)8sWK6LjE?GA45Ba*8}Q0UupL|DM({s5ITNf@$ozv*bLDDoPf*`0V?I`|B)71-qPOZ zwxgkg3-0 zB(xxAQ-{Pc+GZG+lvHFtW$&#|Ir=vfz*L1;$*&A&A`Q?z*JU};&konesn*d!=%@4yN8?A2efq-Xz<^8=cZsFYv+(WW5!HA&~ z#1vCuWRH=`$mNVKOeNtX@rc9+fBc!$xMLx9rYJurp=K5kH9jK92s$a8h^c^RE=X)4 zE7F;L8N4*PFKid2GXcrc#q>u#70w$sxSGPKs|wHVYOv5m2EQ(5F~_7s1x#fsmZzhn zN1R4uCX1!b>5j>?OC5fU9)M3ibCfnHj2H_)AQf}~W=V5KiPvG9iOglaxTONng@=f} zA6*OT-_R3Jg2K}=rC-K44QpE0q#qyvZw}%jeJ@Eq+jjZ4H~eGmb2+|&o9W-89R+?e zem69Cff%FVWmQy^?5@o}Inafv_@Z+gy?vD`}*R}%bH8u-P5hf_%5fQ`6+%WqInV5u`+*)JO zD)3&hv8lQ+PpLdwne;|sAd{xFpzp|18ejzzZOc=##;gJyTF%$B;X|nBz2dg4_WvCq zP{e;Yn+@P1fusP`=XwU={onPdk1+{X6x+cn>6*|81wOF|c=OLM> zmFEwh{P=f&byWDq=D_cL9ORup0d>2taNX_svE%~F1KQPMmo36QPs0Qqm1cdBYJ$G) znN+j}W`hpekE1+%XSteVJiFggoD~bA#PTQWl^YpprccYpCB*tLMaZL#tbm!_>EUGx zC%uN{B8D)aM$ep%ueop9?K}g*U#IhTC;=Zr|89N?#O%Fo=DiU2y;2Z$Jmb@pvYZnT z3O2_6sM`w_e*dKJI9vVQanYstlII{8;$y!R?_}b1_q+M!P28vPcHc_->TZ0`3vch` zWb2;!>yh{0PW^6>=$_$Tkj8)RwGj!7M_PTJ2%j(f%m@Fy0Xgf?>-#)Vv^nSvv=jRy z^*^=p-|v0hV7#2n?}T!r^Yrghobb!uGj@ zqgAeUbax^T&4*%5+1fxWaiI;M&-Eu}-Se*zh-LKC&mGdBBU?MzsGudHN}xi2H0nUv z$@LS1*4hA9DO89$F0a^Nq;ixP!BaLUnT|ITL@jea)M~60g5au#YKR-pig@O-6($&| zBb$P{YC#eJJBF+2IffrK99sJsuBVgyycj=NYpHC!hK_mAtc*wV{op{5Q%Q4)h^Y3^ z=|@f?o9>1FLa%xh@6r@zx@qt;a(WJ6-wymA;?LTXL_f3;qK8)2_#q8kN!2O4NnWNP zBO?eXq*_zL;~`J^a@M334qT1Wy}~WYf!X0kTXuP*aD=CBpgK(d7fmMYZ@;zS-@AyG zd|$={a*j`*CV{FI{(qq@SKLh&E_$!*4~p>JT+>$@xf1|XF{{9Ty<4L&3VKTaQ zZxlX-LwF#k#ml?r@p1Ru2$c7Nv&)9B?`y;WJ=yma6S|!5;#u(5zKeRM)CXZT9KrbR zMnlwbg!jLPc(~c(#;a?Opya+gcX5-5eig#a89`fS6}k-~g5>-w4y~a1*>aqsgcX}n zP!I7AY(qhAe}|y`6YnE`@IOHXsp%aNETLV$EBEVOe|93jKLBLnA44D$r&>T@|A&10 zLBQ)O`+AcT(a-KLK9Dh7WX2v(kl>o_fX%zI@$jLDlnMrn)9XdOuM_jK|S_O#3+IdXJm8GV;3&uH95DXN`O-W#Ews!=(kp9scV6$VaV6D-B-z)L_Tk1;$#QI++%K5^MvM3whon339c ze}}#6)bm8407tX%m2*&fC94`^F~ynb$dT@xr0mbCUty6A(H}UwD@)?@CC(_ZAMT6TT z$@#t_?r%@R-(4Uti-rbQl<+fqSzaE8{w~^5RC>F{Cy)cpvGbxdZlhz;9p*DLgkkmF zB}TW?mIVr>ybv#f+dmRr{+m9Otw1~awFVVsLvKId(^jJ0&CT(cA25!)RDY9b_`DUs z8KppCr{ARH{*0f)=L^=@Kn-{jh;+y99ea8N%|7y$_E;LuuhIRoI*&&tuSEj&3dHw7hDjUq)w41!nPa~hh*3WO|DEJ#N;m_3{Ed}gVBJ-Y3e*L!f1r??b6 zicJRZYg?Qzec?>GK_iu=y{3sgOBmeW2h zI#^>SX=CE-0b_tG{bbaxhtm$+uw4ToC^zpDy^zh+hvY#panUI9U{a>|TtFYRW7c3| zssjA1z9XeS(H$#ctVu7C@`V}`)}k{!|3T_Co*+-R2g70iKji@49a_JO!JNDLuS?2p z$2?bmiKOc>HwXd8Th5o^eqXTXy{VxWu?$bbLaeME}7WX#&t~Ool`t1ua>_-8wM;41$c)n*z+>W=uw^;F8U*eee z;)P#g&YZ?~YtNsN-0f4Ug0*%9f+C34L;7C^ZC>8{(_2~o^KM?d(HlBC3V31?{H=*Ig!30HY9!(PyKhI~nAH zQo*b!l?dcspH&tGM@|sm{5p7`x7caHfrZ!Kvy5?{DiSq{bX9vQWXA+X*K;SNT~Z^h zL2Z%X%}PTQOYqNmpUeeFqEDlzHHflTATEupf`C&{{EmEdAV}L{R$h5H1IVT(yRQHg zFGR*Rm}CW`eJRb`cOoY6o;PXshbZp+;bi=BLBXXDY!9x|4{WTiI9)S2xDIhdDlId! z5cHjHXlx_t8D9(VR+ND=N5sw;#s2MgnsGQp#HN=@wf(j)Iw=D;F7|j4uHa0C6ZPFSNCbB*D*SM>E9cFYR5fxLLW6>46@GnR?@op(zeiiZOEG zPN-T=tx@c~7Y-9gHUuXNa2&Gp_V{A|>$GX_oibwKPqJx3u3gS5yma&Iq|~inMJ3%x zzo3}RtZz&`zfrlerxcVEeoO23;c)l7t`vVcEPo#G#vUti#YoeDY?kP^feoSt!$7-x zVUKY9((B%R3b)6P=<4GrdEFtt9UcT3&9Bw|aC&Ck;s;ez6cZR>;TUh|x7|jLLLt~T z!_sF)wTiEFb#Vp=KYy%E8s9U;`>M~iRM>#go^()0GlvjBq{wy{edg89;UPYl^%cKQ zDc;_gGIP?k9Srob*b-cV1+P-NBX3Zh8*DcG9_q)DB17=&q?sxqfkQ z@A#rAyHU!3lnDylp$~u+)(>-#x|{t^(%pW{(T*ILRDglzmw;T{1^ip66L`oEAPTII zvzx18Q%QsN79`XS&|@mJ)dOd0T$|hi9|#4XwiHkJCME~bW&9Y9yteJn5}V-M76U&y z$ro7NY0*bd+iv0|eBb+e54+o1M8AlSDbl>2`o7Q$<{A))jmoDPZam}ue zghyu+DYqB!ewcN)Ppu!y`r3Q#V}r2E*KzW(GcvON3L(%Plw`y3j*%_gj`m%q^<*Ht0#IjQEj5=&RD^K&S6ECb@-8-Jz%qs81LmJkDq!o zd~ZXk19$&V!dJ7y!OzdVzI>stq4K{97eA;7`Xz@kZr;J)50dS4u;W&c)T!3_P%ORy zsbA@8vC2mI657%d+I}~&HSME6{sZ?8F^WEqV0C^b!u~nwq+G;m?5+%x3+tFQwdB)J zdoIfu3&+bMCF+Ip8w)@@w}0p<&rqT)+rG9d4HLf#+J!T$~krc~Ax2s)*h(_QOLB_{VgGu));;P(?IDjv5E3Er^AFLR6>^ zwq|f|tv{T7;yz|-;V7fH3$zK3*V;K9vv1Z2uI^;M!;828_ot#d=nA88-QqkhGjjg8TtmpEJ7^E-u>|s zwYGpNLGLQ0d7`+#-O6UI^RC58F&Lr;&L6cLtT2Bx z3CD$eOB#XCA++s)ajs4mitr<`MzJ7QBvLMLTgU-ZUK8yWa(49w?neIzbyixj&u%h9 zt4=tluTG~n(?p)0z=XX{2n?W{_E`v5xYOMPFNhS-PnCGjFdCWhMiYdfj0J^F>Ua>7 zZ_;JQT`f7qRgQoxe@AviN=H)f%+kDheEdf?vkmULBOg_$B4@lD^Q#>} zr3?PD6`b&u4uZaUPF9chIQA^K45iRT4ovf8-RBH<3bn@!x7>_)oyWSk1ci>7g%;#- z6HXo&^&vwugK8El43bwHc67sw4Z6kwNq<7^{WTpqWY{NM$AR0lC;FV3b*zqyHNZz$ zYYRkCu(d0&hOo2IzA7|vs<3I0(})nI9BDB~gRGJJ4)7Km1Iv}N^CFO1<~Mqs0hgM- zGNcRp>>2K=JzMzMtnv{Q+o1sEK$mD&s7s(`Up%1gonWj@m<8XJEC;3c+>r0R9tJjt z+ypK8$N(c@n9T$Hl5Ym9>*nu z*Klaz%H-Yqd+~LFLAL6jKvdSsb*w|vpr#UC$Qg2^M<524YfN){Qp8i8jGL;H9!U|1 zspYV7)c2#E;*uxa!^x7TY~7l$?`#m<5Zw>`EBSVD7*{X^cWOU^>KywP&SjXdSzv$8 zW-Z$A`;_VDw?(S5VSyC9^-i|~F+gu~9Pny^L&^W^6}hd5!O}VC&~h|4$#iS61rz(Y zRa&wSzyxlIzGa*jD+ca(zY0+%)$1gV?vY%1Qm3C&CuLSUlUAK5>m|*tA1&f`F!Ei9 zVT7nHj!X|lkG6vgQ?8BfY>Nln=X>C6OG@`aRO)-8E7}utumN)Rn&ZE*<8>BiP7W0N z(tvT0km5~HZJMyCE4+DuUZ`L*M9=2Ld@Hv7cA(ae^)%LXZ!o41`0UY931CodPd(D~ zI7|K>)asB#qvoN#(yz^;2a;)(De?C@c~#h-h;yl`OP7Sp!B~T>oO6U5v1Z~GH~~of zQUS$94SRs9NK8t; z4tdg(ICNy}!eFzb}QU&)^(| zA6^EdPZG_>>b-rCK0}Ckz*i!>B3nk67AtbIIy$Spl6bu8gi?2jQTfPpv?)=hDce#* zj(+z7(BO;@OpsZ9&qxFyRDa7Q$IA$X)c@`RfB2vu(QT%uz0r-dE4x=J)}I{DburL0 zVp1ruJ>=9^=LaRA3)mvkWt<5;E_^XfIBi4e??IYtCHVy?j8(IO(!=99Gg`nXPh2dJ z6UT#MHz)oU7lg5j9%0~^ zmcp@cD%JYH=13<*8?J55bYV&+4dL1Zx*CH{u9&h!9qiR`8v}XJhTn=-NxHouCtl)J z)~LYhkJltbj(S4e>@Fjd0ZL97R@e(gSP)bOUb>4G$2#jQ%J5YS3k@H2jFi$3%KOCx_FL~jpC1Ug_WvZv zC3hs1VAw67qbnQ0TO9m0S9qcOG7(MoE)v%=`u=FZl%E5Ahz*@ak$)2gUxtTsV z%MwisxZBNr<<$0!XKVR02xaq|@gA5n#azg75ju1kc^O}-cAg?6TTznLLGCu9wT5I$J4407!JgIPrIUSke6Y{AZ}LW8`2<2CZt^H6!7G2% zCSLbxXJG&={^v>{<&c?(LtWjJw?1@~vjc8M8Jra}|LcEX5JWs~Fbz!~hgrB(hWAKg zhXh$h2lPRdnX1Bn&>s($wPu~t2IWzEwz%1<3*~XavY7mCoRk!Z3d^4V`oEf)ha2aE4Q_(5 zPg_+mf5MC$m;7L9@EUIDn5M@~gDW$eEgHtFY~6;-c*yI)#&HJr{Is-*Coh4cPI5u4 z@;RTa4Z%ki$Cf9=Nb?iRBtr9>U`m(3%oRz7DV{=0LNejsLV`IqWt6rc)Q;EDSP44U z4MCHZ*2&?#GS!D{M_O;avqSLAaAop$!w`@^a`pu;hnuqOs0yn>>TwHvl8kAB^-4tp zh^JwH$oE4-x56ey6{c>FSdKfAzG~U-gJ^plz`}7UiB2i+%!;P<{)aE}8s?LQj?Kpf zZiIFB(`lA2C8Qlb@JwrRrFlQ1oa+=3!jMr6W(|JGA04a!TEguLBRvFX_ftg}EOKQ! zy35K3PPzNfeD$dq*K8|0-kA|ey>WPzF4#Mqj6@_NJL~$AppbUo*M5j-| z90HfQmA|&%G5{w`hN}KrnDHRB7?LWB-H}wNXF4xj*$Ygmuv{5aliOfrN;7nsvdQ7* z3J)x(dy=mBZ-GX6w>|T%gd%tXBm8r=(^BXsN?MSq1*MP-EmF^FFvgCnX9CYltlNzq z^5@?Ut|f{Dz#sHS+7E4~JVpbahS%<6es=m_{@V{;Ru=nV3gCuQk-KB7F6G6c!u}?j zi!+p(x<$*EiduV&?#%A27hV5)$Lmu7)DFd)6MupR2O0LnS>=!ik+O5QIfn03qBxi77%Ot~h z!t$*Ap=cr4t8q`CVeZ9E==g69Gli}VVtP-iSwyy+fzQ|xs~>3pm#T!i9_u=dZ;5MF zwq3~Cv+0$2tQHk-hM+hV}4iFU7oCaw$Y}U3VIq*WsB7j8BMz~L__<2FL@kw6$@I_ zMI&8Z__i_LF>#b@S^V_)1$Xoc1$etboA@B-07`0ju+Ly znez)TiK;rG&JPG%E`lzB(WoI%d|Pto;`1H3&!@7J*FXX>sI+K$YMl&ZN71!c=*wW- z#Z1>h9|gv?!s|sY>^aSbTBTRI-APz!|8}q(FqZlAHG0GO^V(dfcFn+;2XK9XGk%pR z6I`=UukUGNOaG+QOZEvzmTYOZ`tt&to1Y$dtn$YybOtN*lBBLcVz&42W54OLLBgbk zZejj{FyqLGb8s!1e-vx%8-d@zR(}qA`@qB+Bvc6VhwKcELGI@Y$lMoOs!U{kB(y@Rn=8n+F;YNjLk7PC#BMnC;ULh?i^%wXB>qfk zVH?{w5NtY~9Xl=tWpd92pWE!#z1s+j6=83*w{t697RFa=DCQY(UG;@t&p!u#G!mNO z`w$vaB*YRm`IK=P8b(pGlO3v&9p*gNi$>dMmevL0v6YZB zJX9ukEBCs-KEIE$EE*VXVgpn-n2KT3uDH15l@Q*YvGW;|@|H#pZ!0qaho7`6&S*^T$U8^GtJicwHu9uwAYRIriu@!%+%#KJD*Bt^&JgLE@s41r zfrNlY(0s%(SH!~iCqD?@)8~_!)m}>!sg~93#5X?8xIZ?l368|q&i)lU(IE6YqB7Gz zeKG!1!hdICt4Y%3YxEHSbQ!xL)Etp$C-)mGmOMF4Gjr?#wFcv8*wvF{$rG_8GAkbR z*+i2JiMC>M9or?Mi@g;M;%JIkC4d}MvABpHfQ#x8H!JmxAjOm3$UyVixS@-ZC)RmK zDw{7{WierH(qqEeHuuXBfK$rya#}o!GzFt|Y_|?k1D^LSv<|&*vhroN^y`=q{`AFz z8UAaXu(oKG574;!n2gxOQr(6EYYput_3L-chQ^8~FeF}Q>ps;6# z+@Mg*$mi@+u{8;jIR=TTQazzLcG?bv&js-FT!l|U%ubl!EtxJX#fPA7vDsn>0p~W@ z{4e>iA)DY$iW}8yL+~mJ6brXy(;&wSp@*;-jOYv`CWyef@_b>X*Zc@HM|VkZ_-6}K z#muZb44ts)8_)H;e*w}i2G5D;^x$j?>1_ob@Di(x(&htc8<2O$W-usFzc=a9x);d& zDl-%(j=dRLU;!Cg+T@d<_YU`X{R3a=qa46d6GU`;TLC8;$Z$gO8t-w zqjU=;MF5wRZ=SixPs}?Uikf!9YUu^J+XAqpB(I+?93~A^VlMt#Qw}H?oWk^^#W}?k zBx+$KTYvIugek}@I1;;-btX!UO)5f`YC{Q;@7Hw2IT`dnFweFO)jtwb{%%8+N8I4} z%vA4kfIQi=+ico_sth2@e?t;D>g?t)*mbd4i6C}7tO+=_aZRn!}HO`*dpY)21s0<7G%_7rJOqd32_<7GJHR~l$%!!Q zD;|@i3V)6p{SF(LAEjN2Xt^ zptMD)2f)PuD6pz6nHRB%gs8`uPd`*NMs}tN0%#%*_4eOh7mtQaQe(!zk$LVY<-=_|YVKv-PW0cKtASybP2hC$x2Z5Iuh`3tkA?SyV{nPL z*QTW$nG7|Wp_mvag$c}uPGykat%gmlSSg?&Ep??4of@52u0{c~yRdLs3!U}HSsE`#~#_Otd!%1ei-wl8j;m+}EQstc2` zdFUC#grb5x1Ir^~0%74z2`3APzVT{7vgmQFEN16O3_k zDIk+n;mych{$X020L8YjeP-3X4Nh5qp_)Paq3ktG7JiZF0ztI z6i{Vpb?EGrwsAqKSTgOF+&y5m^oUz|DitCN#6cMzqKXR}Sa-T#hpVI@MI54|1sqs} zcibz3PKoveGLUCz65dT3XC@vE=*&dC-_3U{hPDXV{L|;drF#ugacM2L`0oaUki=?P zxGsvL%m$_80;yh#uln%Seq^Fk2z+s7CJcnkcef_e=50ZmvF|Kr)q71%7=i<|! zzBb-~$3&C8(V^icKyplz^juhy9hfC}V$?nrI3C)4_^1Ykf@MveckC2x19zpUex}+E z-nUL;ilcAyhDN?!QWC4o-H0b6c(D%Sfj6*gCqugmfm)%^T%FZqj`vftHtp#9LvnR^ zYN@nwt4<2o8=20&sV$z-1*s__eTkIhd2)ep!UhjSk8jhf?kb zx_?I}BB|{gogYI09Dy<(m*7Qtz$B$$J;BL=RE1bJm4jl61X4Pre$k3~=4pvHfR%&)2%*#{(oPj>&`XyWF8ro6Rs@ z@Ot88e@&no6>XqS;A$Y=i)6GQT#Z7VLnalOFQZShR>!?_uA zIK-KjzES`gMr9|h@0?3vP!=JrS>kYR7Ouv#%F`MA0$Db;T9%!xpG1(+fn(CyMss%p zlj|+(RcS8KN#3%{>!4`R?hco|+DOB3NJ*H81H5RYNgkxnL?-?)L>ExWo=I zdGrl2rd+|3XI+fI?=+~8BVK0Kd52fUxZGLQn2Md%zSoiPf-*J1&5O;h)VzCO_HYxS z>;G^u&v#r++Uo>jRarQ3xC!XK9fn)m3Vi6)F!cogx>P|ufj=4wYo=+HmDZb$!lX=hzEm70Xus~<|GP{eG z+LF&e6QQ%rTHb$i*Qr@gl$#2;Zl4U)9E>NPu%4POsA)A8NtY8ku88N~&5>GkNn$a0 zfOQB^FpQ+is7_83rDKO*H4dEw17^E9Pd?MRGtIr}F|PJ7jL4>|lD>Z=xW%-Bt-Bb$`nT$;H1Oyrg*rbQ&?U( z(AY&oM8ZgHRl%mr{mbPPty@>qfnaR(t5Dk8-Qn9Kj1pn+CO(2DE@>>i*hn3nWm1F< zvWOkqLZP|>^~DQKZ-UtgYFr$^!&Z9oZDsi`3q%VC90;b?ywpKio(&~q_`F2!a7g#w z1rCVIpqzF%V9lNIIgYC8IftPii{Zzy_`AWsH~z8m`J3G?vCspMx4><{*x%&@74!Ko zw=^>aW^Cz;$nex`<7L{V`U`zX=g2=GeJtgour%mS|`YT1%0(Ff%}OQSoj?rRNARg43n^ zfLzR*kA7AJfn(X%AMLi~(y$p*-VXbB^QxD0@>N;6%W~p}QKr}1pk?Gw{22pqIVN3k#>x+@zOif8r1;fdU z%{F((UBqwaJBa_*+B{zUnuGA!9bFdd>B^=faS5n@OI3?ky!HF6B{X!u!M#65)Kd%T zQP>>C`bGEtnk#H?i|=5sI2sy&v@kUuo*GeFC&;xkGM7-=M@^(5y>1JG>&lD4Uibey z@oSTL0om_esLf#))J8r?MZ)_WGA-abnJ#?QU{L1QjumNz2#bmYKMRK4lrfXOBW|lM)W4Z=|=^*p_Pbe zYk_S$_mt-TxLdlEqoa2!Ah7!Q?%T)@NzB~1AtH?a+fXiBws@w4kVT}*ye5sBbMtxY zfjqG|O{Xa`JkqgIR0d;+C2$E4KiQ<$gqv~oh}yB4d=*6##%|fU6LCz^CjhPskQIg& zye+jtsEyOvu|^y*uKk8(0Re|QmaUQp)y;}7=DeTW0qao>E5Oc#)ziYD5GOw2&0qpF zHlC2gg55gPvy1_ou;10)$QWvi6ba6$^HOVtB|SDA)~G6^bTP6HZf_ihw>&h?slVj< zsB@c~>*wU2Do@}W(D>5-xi|dum`5oVqwZwyzG62+ef3-1tafTh55nTQ?qo%Q6l!@G zlM#{orl+ta9^TUEAudjJ67>+AZ%!&CRniz;?+*$0e;=Gric zLp_X-VT+XkXHe3nYa$%O2ZI0Jf8F=}w=wrCm+trmNe(l?<|l8At^2o;C^Me)HP>A2 z$ZZmxbW*JeYn9@$REZ>G2-(yNm$I)<+->GPULFg4XbPEG7rhP{#JOBvm#O#N+mG$} z4_qRz?h|feUi+;g=>)t4N0ET@P%u1zZqK=I)F2Sop;g{9XbT; z!WCb?9%sWA+q_vPH^R6vQicNj=lt3NCv3#<-K(!m`EtY7?~GADU3X|49Guaq!2`#d zEs6Gqh6Qj*9G0%GF2h#f59%VU+Kw6WjOjsBHd#iBxvMu!Nl~Gn5x=a%cI?-3Av^up zvO-6VgN6?*aY?{RIXa7IKtJ5EQ`fP3XTp??20O-hsLx2c8=w?jG+^GGW)-%|pADB9 zTQkIo8~U8!tF%%O7B~jFvUW=9E_Fz{D_`wvA5cscGgE=;_~AADxv?;4dT9wgdX!9o z3S)C~bM;C58#0VqW$Ni3TNdKseMiT+E?VZSIS*lcw!^6|Q-mWAV*g%%j$VVe$;0Vv zc6Fs@OA%Iv0VX_@X|vAyZ}($o-o`2JEQN**TQbIa7_OxY4n$}OLS*UTqi{q`9{cHc zP=r9y`7Z=Hvxht}qhvLjSJCXAU|c!Blli|O3B3m-uW~Ke@IY79X22dfx@Q{-jLiTI z`dN)W^u*CUNt)c??>^tDvsnRNfypZ*AYkCcxz^Zag_iCqY}S-bhAM@#nFEskz_EkW zoH|d596P44w)S`M_l()-+8^z0QhzjC4&5**#d`(PGct_Yw`{;kD7V4{K>ydaZA^`m zWB6EC%}N*)V$Eu-ECuK=F;Rsvg?h{|Jd3`%(MzCql{w>$=O-g}%nMOkyl~F!kSW`s zEf;y7Qifi=uTX+57eaaS3YH*I!mx4Uimy=gXwi%PQ_pR3$2@N*gpKkJOF-2#_tR_< zjod~YGdr8WBKh%C-eFViCG^Tg& zAI9jlTvqI6M~*y~(2QYXV3q3dmFjZ7ZOa!mR>IgZl7Zip-jE~2|KTD+=kj~h+2(5} zOq@L^LNGyxh~~O*sw`y7!_)Vk#g3^RnZ%5$ab>V+NH=Izh{NX1pBXi8Bu<|&$^NaP zbF|VdQKOY0OVZG%M?gT(*435Zz!wy@4;zjgKRVn~MEG}Vc4)8ydp*@i&~g_HQtrlyG>lkC1&8h6qz zkQg5z#*18lSOfa*dmm}(@hZEMg11f;hswN19UIa83}c==C094MR;gQ1Yfe2(=1=kZ z8*B(%5NlUNx|pN}XgD`Ns~M2fOU!QK1|IZUJj;9hN*gq$fmxmp!q6FeN^7=ZEB>@2Iwp{DK|8i;& z;(?gjwp@b(mLEHy6~F>rIuDvaDww5ZlCq3@^grjh6_E!XRA?}#0ucf-gfkS-`-O2P zK{HyZ{Cf)2)Y$`PfQ4p)UX@xz^gtMOeX@71f?Vx@WFJ^m2|pj7AqPH`@hK95hyX0` z-I@b75x)?S#n+uWqF`rdha>URm3K_Ufmy8i`<>RhdDCryZ-k*`4v~$-proxPmjSE^eZ)Md1|~3k%*_aL<4>B zlM3AQifDd&@B=roiU9^Cwr1DT7k2PdbSC{IBAADVcex8}%_or? z|G>EuG)|~7qoIav`I02^S&CE`+xE|NTm^Ul`i$udIiwm*`lhgC^Wmd=*r56%8ktfx zBxXmQ#3kER`8v@wXxj8&EP4)|^&IW0C$2?Q%!^_x|7zh!x^r;O2&Qb0dKI%E$H`v7r%I`;yr6F0U}_JzD_eX<8a(8o@% zYvcL>{yr;;fUyYq8bYNY4hVY|a2Q3ns#m+fECd+h7iNW+8Je3{<)U3&JRDi>;H51Q zl#PwCtRTGjyrc2Khgyu!J1lL*Tx>i9ni>WWQ(1_c(SGyULp2v~&LqHJ5oUh>Yf_ee z^j$0yKbHo=aF{%#Hm4zqG+`99rGk>pt1pqekJZu{%6DmC%$zm@mFDFNfqung!hi&` z-u$b0z6mH{>M~{Al^ID|at4mMs3-K5Ylh3`;j3vem8#K#vKMBIBq$-O{?ds1R_I@e z?^qZxeKOGo2t4?FzhyRW-l)Rh%z{lACsz|N+uZ(S zxELwunfXI&@KNQadGo}l*87}>wL4fDv z#7w(ZvqQITI>m_;wvx*H$-5Vza@tyyMsPf73LmwV_$x6;ioIwxhB1VI2&X!8b8Cy4 zcVTH~X9t|IcAe$FA8x>@;R!9yxUlpHLIaUf#h_OZZ0afqGjRjKH4c0b48p0I8O=Y> zxx$PKewP|-M|fO(PzYH1_d2UuGP{k za-Z3ZdqXjYtG8|^@JA!7NlATt+y}(DRbG>u5j_YaX*N#%2~C$PO;jpZrNP|4_uPMe zm*fwO!(4GWpMf3RgqfRcqm=;i|@2#u6#F}Z_4K;hQ{ z#`Pv>BI4KbMp-<_{EQl0YK8gn_oKgorxye%h6>XGW$4|@G>!+Isq`73<(q|@QCZ?W zi1CB3=B@7)Jhhp1edf$>q3>>BIn)2GbsD9kW5>R*rVdgc)^Q@fLRpsq`^Ts^>eFOo zvSFB)g5aafzFN#gG(gs&ba0>5A$8MTM|*}?kfPUYIvv|mCql)1-1-qir@B*@9_VBg zJTxysM*0TLONgwe^&?~uP`(ToGFYHP+l7{i)9bW&;Ajc728di|j5{5E`JtwVZCBmO zuZFn%hv&(XEa4wYpqW6E{L%5y!FI&s{tNf*qk;Rg*T&BEy(h9a)CteF0$f9nt{S1n)Mc|6x>jtuwvW4 zpE)8dxT%?`EK+6SxYsDgFM!cv_;8qaG(ub~2L#195b`p1j#ro!fPUAq{jGKVHw43l zheaT8a52rn7IXRnX9wFS5gFFQ&WlqT=?!ow`R*O?-#ob6+eIR^ZB!Buk<(QMN|X#A4M3 z&znA(db{V$E&^>r)k~(MS6dCg35Z1u&)=psGrQqCDsxPlGWhHNhQQ)(eCYzlGZH61y%?0!lvm-ZEF}x}E?E z>3uH3vrJcgrh)QI85rDNlwX)l4Avq=9$;%Z2L;Gd^HY52QIWSA)2s%OcklGyJ-6B& zaKM|S$UvBwC;>rB_R0Fln7d)Sq0swg_%I9$D4{w+?^jIe(wW~Ugop&m>S{<7(o-Wy znX#Tf7^TJ!##-=bL;*`9r|mmtS)qZy9ev7z0i<{7v~d!A2L*x*sUK|&p)BsPDk@fr z{3ee#c7FGZgDT)pw0(5!HQbjy3$80pWD^mn(2S&ttdU!SV1>j2rO_lANb_bq>=-kR zsu-(YsbF9hC~IglxNo=x)!}tCD9@K363Um**7F<}>~n(ZDC0)kid&5f^PMKM>Ffc0 z0V13;N#(S98aX_KWd)6oQgjy#QOFQ+Tw?f3cmMocJSmp-go|Q&sGd)-m-4?c@#C>x zP?!m>}>c zvLgkwvOp!{KmRYvBMdSvF|XcTjXu^3S0HQ+mmH`H219)U*=6T4V$18v098}NwWKrD zOeVb#tE%gOYah=r(kukofK=2slu%awRk@Fr!y#!(RYrdFwPiz9n``S4AJg73f4+sO z@g__y$CqRDy3M6{u6DiWUJieoF#*wi5_S%$Vl;VqdC;B%0->25Q%RtdG;1DKZBL%0 zKo#b`eD@*TVJ zTA!}!vayvjb4ETQJcg!9%4kW7pZ{=5(kQrkpP%XG5aRO1iCm~sg4VA5^a8O((&!Gu z_GrXveV~jH*$z1xlaS&MV9%jkL{afV`h@?1rANVHyDj|2uFA^waQ8H0b`p5?K$^x;I>_(*xZP>N>3QZl#WkY|&>Ps*^JI{E9uj!bs+6 z$Esbo1l9G1joMSL4hoGN!{|ZztThdtnV=eTTB50@WAT4ny>(QTYZvxQNh=-FA>9p1 zBj~0C=|wjzy1TnY8l(jz7Tt|>NtbkYmq>lL?>EjlW1KPgXYa9f!{WK`Ip=l#uKA$5 z#O0a66GghfQvuOy+cCl_hfpBl4vK%a?I@&-tDw>{M`sWJD`ihz&WhLZYesyimYyCV zQ8sxNO8|Xa4o@E8AGjP0ac1ed04lOqwAiSq*cV zXCv6devVwi+o;|=jKW&kFLRDdI-3?Uw|{g4%INCkBV0+PMj2YZJz|w{&=W?-J1EDePaRi3#dffH)ke zB~wG$Yaub6S2WpUKsAz3#$P^E9hC|rkh_p#U40lOp67QArVqvb3>R$9#fyW0O=vnX zMf=xU_IXcrKP&OZNfkbE9G_ll$&AE5(BQezz&w;;$KS&i@8{mMG93EfFnYN~%xful z>~s?8AAG0vc@YWCGf)E49-t!9C!j4@*IUY?-L6_JxYV>Wka8RpbPYK2Vl@5}B{v;_ zvH{w>uGyL>p3Lx?g|f4tT>1~oLd{tr0%Ab~@=4!OQ$*~k-O-Q`@-(p9lxX5nxzpr( z6O0=c*DvpagV=9t)X#9EdWR+jfSLoe(L5}qe7!1SyYJ#umFV_t?Ci7B9mQH0urJak z83J~CQ@ym^D#N1?EZme^w`1%H`~J( z?7Ub>5*S3S6-1d)%E-tE2B$RKB;XUAu)vT1_??|T^gez#>9AN+xpWTA`@y%Pk;^^$ znk?n5NoTKdj7+{uK`yk|7NVyIjD@tC#bmu_XUGrz zCuJJKZV-HN{ z+pmf@$W>yr(sz_#s3(|xn=n{rl$a_ri9l0_K$t9?U}{8wN6O^*?ARpuPUh0(Mq`p^ zaw&<_+I-y3UdgC%p7X4KS?F@?37bQF1WziLH)7MefE z2!eG7{9g8`BTkQveFYTTHwpg7b;%pm8!55IjQ0=$F3US4UwjF^uWK`EfZ&1A^_wo(4Qq1GWwQXHpf0MCG9as?he-Cy#E_Gdr|;9XEWZLm z!WV%BrY6iL!k$l^k}+`;7QsND)y+mT@joC*GU3+hYc6xKUqB62C8a$|6%?F$`x4gp z=BEK?C(zU>;%G@?euAt2ze=r5Muw-lKmEKHZ6jtidoyop@D7fzc328c&_e?0^D_rc z*6al|!5OV^E&Esju(`O{$Ao+z`S& z`N&6!I|db}hZ(u9jkwczeagY-6)j`@dj88hnNqQ+--K=Dlb|&PGP&ybP!3(1JbI>l zLF}Y(=&(@qMX<)GvjR-ZFh!m%xVf>Bu_S(r^17Xb%agV=w>^Hgg+tlP3kaldha3wY zvLFJ~!?1v_<hZ<`YF|S-jRVEsxvscvrO|dkdfloMAfXoVFHy2%##F4Yky>O zIBVz_}+TgLTx@3S}x{h+t@CTJy84RG7c}dFm)s6cznF8JgBPy-(D} zJGQZrcM`+?>4H6_^aSN6`2LJ|*iFEs#4S$aXU>Lg#-HIZ$~V_}?26&}C7R$eS2d+& z*%sUi%4qp+BG&vF<2`3ZnyfVOAHgFMbqP8Al&gdt^ihOB2;yJ2atpj4*t}*}Bo&k! zOa>e0?o;!s$tI+jp%{f7n{Tp)x51<0{8C+rf*urVxDtUmU@3G_HR+Up_WR-d>iMvX z=sacB4}Sf9;f7Elec^8*noGJA5xg(^FCIPFt=4ENHtLY-4w8iALP>R9RGuX|zu$@v zAgC2uT{$M2P_U~G=m}s-D+9Sv>BeUZKjGWr4BlP3JiWUx1u(3dS^oeN22LiXS`&i! z5$5svZpkij30kH3{ta%IM*Brl73yD;v80P_X~h_E=A$<5*@ z3_JD)?r=f*C?3~b!q`2XL&Mw+1ucxaA{XkdD|Ciqph78U>9VcVeXpDb%sCDYT(%Ljd9YFwqsTVcnxy?W=}E`M9Q!t}09 zB0^yXHS6L|xc%|iPQ&~3y&pD;nUtVE&;#J9g8#cmmCVH%`4mSLjW!aCY2e9^6kNm= z(=|z2WM1h9Med%WMKwmRcdxqo6wLXKOy-9lX6`ugPG69?{xC`dLCScf`h|pH z074x{#Cu6jE-TaaG(y9fICa^=*O*wN>w^22_evR(3OT^B61=Id{$MsXyoK9KBkF$0 z53JX(t8(=hZWa9I%3D@dn&5W}*RiUvUZwhy7@BshtKJy`XYAmB6BQLz+AK9C-H<$( zfWVkA_=beKgyH@gm14E`BW+znLyAkknHYAOR+T2}Mi`bde})Zo*SehkAlJY{Wd4KH zON){a5=Oq#yi)b?uVcICorqXexDjQ|^fMdYbw0%Y9X-*o)=3^sBMr~Le>r)vk^bIp zuE9TXY1S(c@1lHNhzIQrPQ_JBy|^3;yZk@5K-3R7hH3ILtOmgE{3i@ES*mMTfP)%b z>8Yn`g%;HtsLHISKG=N&w{EX#@v_v1h+C=_$?%!l!$JS>T$?qyWWT}rEn6)c@K?YM zn#Wz5+~hwpZi-SiBfu1&_ggF^A;Z&gJQCDyBm{VcaYyP6qqNh3nfKZawlgMWTg+5& zd1GIWQngRT={h=A9+gIhZwKLO3H^%|J#_bYm2;IkZ#$lSM(?XX|4yh9;|+N-z)o-y zVW~jka(A|-V{=~dG1Y_LDSWk-^9uPjR*a!V&Q(@~5ZwQU>x$o>SRhqdT`N+fA8{%> z;zvw|DiWCfE1a}4YtgEgC;YxJ6M;{bK(`Ud@b8H?sH=)nOQ>B|;-Qq^ovy*AW648- z42W0NDdZ~ogT9M7sl+pOU{42xdAn)jgsTr;jqP4)>glmdg^Ffl0o`E1+EwkqoEFBP zzArLv;q2xXH6um)&#P^|ON-N$!~V8c=lz5KV@U_CG?a)L%;D`%*A*JeCpFoR*4^0? zlw@7j76?j`dt%sqN1A?Cq1L^jm}=LZP7~ylqO2W%h@gR*Fph zI?zcrq0uheVT2$gCnt}utdtA+R*|J0NrS?(Vfsq|nxf~61v~8&s&8u}k9co1qsh{d zvOT6=s`kC+k6Xf^szW(d>FUU3<2o@>nh`n@!kK3q4Gaf3Q@64rZC>mq(;1XtWCT{~ zv|6eFI+CD8X(t9oVTUdDrmKh%O@oeydBGHb#sVM^cE$XK_AMEfChtnBQO zv3adr2amq=36^T0(yO?d8Nh&JN zUE6<{{E$hRfmHq`VNlH}03a2ECX&oaxPg{!y<0LPU&}D;C#1TMtXqL|RbO8psyYmu z06~X}?bB!rUdYZ_saebqW{uUo>q@%J%uF>(-?oEH8H+L5uCO?xHJQAX+Zo9Z{1}f3 zxX(KR9ZdceW4qm%ZYvR|zPBx4)@nRyKCHBwD^F+6hfG8cvoStR%W3ddi@Cm^CAnPi z491kGDbZq71W3V4wvAMF>OVjFhQ<+l*X>d1gN#u}|4c{m!sejxW*7Hp=%xW2Q^M0F z7UUf|@W|qLOPsw|%?Rw@=jRu`Vj_@|Uu=QjoQrbs96}+~@{5|?`+Vg9)zT^sU0q$i z<0-QmFlLl3G~^`T*4QbtrQ==SO-(i^p-5e~$*<2MIL;zK{uofcbw&kH0kD|pPCA~S zs%?I*a}p8~p0(e$eJZnfI;VWbfwMn^HK@foQp8Prp+Z`4pJW~KzW4y zR|6!Z>1b4y7m<011u`V$=KFgk8t9`o^U;;B-;zR=s~1>57f&ycEh~@e@LrpVsXRQ|^U*fs8=r%4DerAgQZ9u}1BnxX2p0(!h zHsMwy3mf=~y~WESEzj~GnM>uZHN8nr6jFW9#&9gV!UWA_lWX73l7L`T$o|fT@Umaj zJ2vr0DIAb@Z%xN9>Fqc|{k3@>@)(98tlM*ljXI1P;v!1w3Ui;2=Pgh5nWl4c(>g=2 zOz39c+pQG~EcZS#B>V@ctYwslM0Uz%Al=R8)MU-KdhpyFFKWzr1v=3UKU)qCTUh6y z?7i;knP$b#l5zKZ9^!X`EmRYbGNXX-;m|y&%|~>t%Z3BP9R+HFDd0jzLej(7TWH7DoPawDp6`$a%xF`*UM$rhZ4No zf?_GgRlPc)XSHltY_1%UyHHxHqO)& zxJgagjSYL3EkG@G6*+#~q0%8L`v}vQ>Xfw3e2q&Q=kCDbj9W0nR6M0qoBp%pKQuJmwpFJ#GMM#k$R7&uWq=a#Qe zv{;kVS+@_-k~t1u07EM}B{{RMm9qS^$*h!}!DeK6a##efRo&^&q}QY^gW~Lf_!`fZ za^HwxP}fC#i(fQl`R%QX?8EU%%W3GcZGRA!XgE*`IK0;}U|MAa756!DXc+7zmeSBP zEa-7&H*f3=)J8U&HW0mOvfrqx>^Fx?>a_P4Q*{o#!TAA*%tC#>5@V-rLkfJ3WUl|m zH+e!>gURFvKwAd#f}~)^@OIBRc#@P=yLhJ|EVO8`j!oarNLmu}Pu_t?8-pXon!glH zl$lS_+N|u_2pT|G{-(qS>xO=VY8(^UQUr%fTHliuQv|UVGj%$rFgffyZp_H$mj!}X z-cYls#DgsGKKhlF*f0uDR4`ngdd{^NfbnXh2MtU;OU_dYc^ddAlf}iwg^5|fyG@ZB zw}>f@u;4`x>z=UZV^m*T8xPlL;N#dov*j+q!9i@0*O_hR`4-q!!&tNJ4 zX_6fZbP$yjh>xvFCyiInKSWN*33>H?<#wn(J0l|qAZ*~5c(#1%>o)U5>3t^Am8cub zKL@ku_4FrB84l55XDCtHOVzV_8&K*|O`5(N&dzzOzmAkYy?U3 zyRf1U>Lt;T1Va|~Hh@Y17=4du1(WqAz^Z8>^iWtR8m>o+LEWl z94Q4wKCy7qSeq61bMN~wG|goQqm(Edq0(fK3;Xh0S-bYmnPTa9i)N== z&I!n=(0H{Cq$j%zx0l=*xw+kzMATDwR%W3X5PxqJy9HJJ-S1ycue zQ)a(PV3U)ZCNrnWM@qyNgdu5J!CZf^{G3vNCw=Nd3pVQ?)*}TR8CCS!nW~i;=KDI5MDREs^+z$=pikM7XYbu%1$s~~U)z-R)#fP!@! zwupofz*l5~8-WBmqkp)Qy&$Wt^|e$(ZLMmbjw%8hG^dgRGfB_Vj*f~U|F5?w2L&PD zru3XbGTZQTT(6N!62ZGnMc{#SRa$T~wMl zJ_c>v{y&lf{_-Or!4QB9Jq1gvB1pl!lq5%zc(Ir`;LGVrU8H?r3SYfoz2J412D+pj z=dXkVRE-9`G_*k9(lET^(fY0w0XX=gbgv2uubxQuG~M_q$?JM-i>=ll@Op1E+bg5` z>R3t`L{JDZ$# z)nQj&US7j1<_(MIg#vA8_czCQ+is5I(q9G8CTumi$@4MjlqQW;5!sUFzsiV5dcpzM zHN9Yb27iM)BtxG5#h!7NAVr*&;z^w+d*wd8)3Q#%-f=^6*VN&4xlt>->eZ`gDtwZz ztB=^k?02=8N7?T!#IV1mN?B-1{D0y@c6-Y3!xiJrCxu$G9(A3!rCP-kRQ-wv3l^JL z;!Zl-f^=@02bg5PBsj76Ip;H`B(HFr01(AK}oZ)a3|( zk^tyy4ZEjRG9(#1c8wC19!*vopfRRkD2?4RUa0Ieoq?*nAgLAafk-LixBfjSb-$j` zu+o2_A@u5cl|Z_y8%r!YjMA65aN((718KU-SC6N#Aj z$%rPTA~HWq1UNd zh}L992Ho*a;TLYkHNpRO*MNmkG!+5F!@f`GHdf~ahQo+OQ^ku7|5;7+O{cW_h-T~e zMke^=er(9X*MjY)y=2*boFvSr$h{7QV~4XpuABSkXaAJK5~+R$N zoTZMC%#Vjo`nq0wO=2bavyP@PC>@`LgCJRYG!D}z5wj0*xTb?S57<0zBe%t?!<)4W z)_=~z#B^?MA)mz{eieOzF*g-dQ4>L^F;|9EyrEBBdeJbG(7(4>fNIIJTlJMECq~8& z_A?R-+*E<{S7Hp_kEfC`mtDk)9y2mJV?>rIgp)T!=(J`;^0N}P?xn-m3E_#!WoO#i z2rFo*PRm?Mtt2Fb-1J;{w*3V8i?t9Y^6UAb5_%!FOnG`~^rA`g3!kz+>hR)iFF^RI z1?r`}*nQfT23QL&Nwyj2aX1oQ4Q$f6e9)=2ZS-;i&aG+w!;FT0Oq}1tW?uWVQ}+Eg z@y_h0tD+Y^1Tiw_MSg#a;QYnz62yRm4nhq5JY&K^6@HJ0jn}i<4r3y>sDJlYyiR*_ zrNY>M6Fq_t7At#9!?hc@2dKCD>Ur*ME7eQJZf*^>k>LcKQ2Kl=YQJ*e3=Enu8yjBv z%hWx32ve-*X~K?#Qij*t?@vmZ?11tPI0BpqU{u6Bi9Pi{Ta3PkH6BUb&|B_^YP~HL zSi!b{!+xT=(w@}jbX;}rsDr>tbu80BBBt$s z5;CfctYTE@>qt-&U5~B`0fC%%9Gx7+p~WtgzF?~T#6AOu(`8aKTs=2}TB6^0x0A7c z?YaIxzV1BMtrZc@eo8?g7icdacmY5o>w+;Te#KnWn(RK~^4*c^J8OPzUCZ3-a3Xzg zWv7C2_K0M=9C4}~E7hVI8z+%?CTT}&_MLP0gW0Kp%x~ncKFlD;ktsn57TH)?tv>=i zMZHzeNTereI$gDd*vKQ5gU8s%C(^qFJR^f-7 zU#4^f5sm$dydB=GNl(%k6R_@M43ewM^yAN%L9#rMwyMed?Lj9vm4PCFX`hyvNx-mV zz#0C;SyNLZ`BK5kr4L*Ztn8vH(qm%J!oZ~fQkI_Y-S*4dUei(ZG*lpc%A`!-Xq3u^ z@SREa-5N_c$jtZ~UNG`>Co34)qIkR8&Ak1HoQReSNpWn@H^4MQ6$5ncE%lwnNw^ z{}|42)%F-IV&01^-~ko(*~9!35jJHP{{dTwH@$oq8*KVBYX`wONjr4UB>wj5Rq*T;yvIpzsS=M|7FI(Kgdi0jT_;> zXtd{26oE7o3s=W@SICc@OrM>R*AK_5PcU}DCROp_a^03QuZ~-*QBU< zdO?Bvk5Z+2q^PeFAKU#bst-SG7ZK*?F;_8rB5KVn#lZ6q!28yw72PG&pK=DkI zFQi^Xjr2Rbv#l2WaA=1lwM1E(TdPT@PE~~jiA&n>SQoWCzES2s72$HiIn%kK+>I_&GX^|XB0Gb;!1ga?x>75Bk}?y*=!_9a%0R;Sj`xduCf6Qg!xu#J4yUeHMIc+;}Bk z9UqEz{1LY+MuUgo7pA}Et(d4;*zml27olz){Y6A*wsfB@-~(Hp@(qHKDema6)V$&% zjaM%>2fnKsCjn*Yo8oTCv7jAbuYuKD%@vrZwa_1GN!G9kW6DbE=LSr>CKK$!ym_lc z0{xy&EdwiK8Qp)s8q%gcPbg`YGMnJTgpV#s-{k>;OIdDl%g@h8#1cM(0~x8E-Q8i# z&hpj^*(IOb<-L=WzPdR*mJ6qg@0W-A&k*AHLA)=7+sX3u4i{VhSuZ!&ZJ69o%5kj! zIo}j?JxVRS`%U?@P8k{T`BnB93b?tpx3^37vIK@VHfZXt7d{i@Sa1m(E)!%Nc%`@P zQ-8j*vySf!`-+vXhxH1E(rZ>@Xm5`V%%V@CcW+`T#mZZJ{QSh~?N-^5X$q&^jWt@D zN^PV*AvXmpk3Ia?&QRiW67aZwv0AiK>8DQ#f*D+*?@G^Og`(wejf}?Q{wLXC@6ZPl zXOs7CZHXRbU>ZXO!=EOYMq*F9!JAt8%=wzt!pu1-4!SKm$R8i?xk{n0m6*Vv*dt{M zNIAPgMJ__&dM6sbHcuvL{Fu6jWn@zSwsHO3>H~3CME<`L?D;0V3+?eS2I&JQ4)g2d z(de6eJ8#09ar~PxECcT~#=tH_)R0$3f{j=Sxy86nJlH++@~A}R*$;;dsPl8Bt1*}~ znrZph-w4oO7|Qe`ha82E?52s*)fM_PBJK1PH*o$}G-X=<7lP+nrHTL3*yH>^91gLd z7;?*B>idE)_0r0NPvAeWB#70nT}mO!uH!F~r%zCTUE~rLQ%nhIdDZH%cO2!L@RCSx zesVY+6j%r4mGVxjxEbZRF*q! z;)G{jtM?SYGT&+3G<@>CNU(BZef7%N9s2Z8;e?0E|AmAkn~aGIw_8Nqon(Fg5f%CN zFeomFmRJ{_(%8q!3WJlY{U`BgiunA%hy*YzC&WCljir2uoF~cBDA)^D1MfN8>=00| zjSX6npnn}G9>^^G`JmE1temB;>DzlSzI_kjEHzBjepNVA)1Sih2R9>TJWI9$Kns~~ zPfuzWcHo}LH*1|4#j7Lyb=13MFQ|@YI+HC?AHu5421g5AGG^*sLHd;NgrwpZjmr9Y z+a1-(LZRio*Zw*b7(_jzoS2EP2@9uc{fkoz^g%64m!CCJtDPO|4VR_Ut@~~dB95$t zr6s!n^iTI_yEf6DrUKd*T2PLR`p1}X53T-Fd%^cfQ(zERS34OPk*zs-FtR%xb4^^jIi7BQXXT*!!vg%>f$YrpxB!6?iJ0Z5zZd@QIYEFX2%!oZ4mJ({N`4$)){EhwO~UTyc8LDFQzxBq)(Dg1XYzx2TXTwPBOW6xyS zcO&LQde1+J+Nt*B?*3fmwYBMPja^A{DAZ&niEtYz`H^H7vda5G*noO#O0B$4SA8(5m;4+v1hRAZoc* zHeQSjXhuqW2}Sa134Olx%uB`Uma@d)nFOX40{t~GSDg|?;oL+fR6J}XKsXdcW^%_O zWb%Pfr?wCaSVy3Xr3|Yf=g`E58x)&x=J%4Qp%-?gry=W<4w46;q{M>`C=ulGrT52gjfq=eIA5rnCq?Do2c7O6+c$l~t1%HXNX_jbF?* zv=jV$4B->yaTc0xa>FQoT2-_m!_Bw*yaNVLxy$i1U_*77C1N@~BV0^xwF`YLBJ}rD zEtqnV;T`qgPzbn?J32{vc%9G!H9D~){jR_)aKpf(HIL$>T->0L|Av-thwNLt!bCvd zev}(T(C0%fzHL_Jxv_eq$u+YlnSx2|B7eY-2*8Uo2EPl2yk-9t^BI+rI*&`UF;!un0@z3+k{_}jw#~(*N z{jubwX_Gd9%q<$9Vp0lkPL3%4eUR;hB;lVm7a^QgrI`ak)CtU2Wqy$`_`N01JS2K) zUM&mnPdbTa7370132R3fCeFgL33u_n-%m%&UlP@I9qAE9P*}V}LiR+NgQBf{Q?i3j z`NQNPcGjp_ykb%BH@(wcwXK#`J&snr(-M*^8I3I~kGQ4fsnc8Iu`ChyyX_R00J%4~ z#q&;*?GvMBP731YZDdS`FE{`t9q}Fk(1Cgt8uB}2l~>|&JQ|u1`A;s=&*8$^WA;78Ud#Cmy0vC1Tf9hFB%)%*S{RfwTyIyl4wsq5!xK= ze{3XI;h*^|NA{el$Z&D@z)a1dB4@(?b?|#33)^tdOadJrJycf#n2h|7&g zG}wmQI9j%#1>qHe=5!g`nzU~CX3X@a&E>!Tso$g<{eJx$GlAb4dGR5r%ilc9L&j;*t^G1H@O7Dtay`(atp=^b5rcKcriaio?h zzx1Kgv?K_JGl*xaQ_{xDmAy6Uw@mgN&ZZ`vD}J3KvyIG}ZebP@52lxSDkUsb(;6)R z?sj$Z(dt?z+R0q^wr(eDlMq6H*EHd52WURfBx*t+C30xwufnQ;x;Df%Zo!+^(&D9X z^eP|>AlVkW?d}&I>p>+U?i}i;DvO&j#tI7%Ra zrhPi%vk2cYk)?V=sD|?nb)BoyBmCvTk8VTTfDbT1gfpehJhyg}olL4=u$%>65wGn% zO#pBZv(4Rwz{=G91x6R6V0AVtnc1x5Soei@ZGP zy11V_HC=U+HxViSz?C=ckN_>Q_2FXp&qYc{G>6Z=ocmV%2m7r795NwCq));ib@FQq z1zCnuXc7gEn2b4MDDIa$NX!^Lo1l#&1xXl~;RF7Og%~Bbm<#-){IB@r?0y43Z169; z3SWr2@#Fjxmy^ zr!WalltpYHdXI|{(&emHfUAcP=gHti0q`;+*3ZEF%$62^f2IV>rJXu~niZx?eAB6= z5m4RQQivnfy8o(JG$$PIq+?Au^~!HI5Y63 z2POA6k+!BL<2!dS8Fv4q^zeF(3ebda!XDKd4iuu^jYm5eNC=ghte~`jnbb6kjhoRB zuTnP06t-Vu7DNP+?2chcc@L?CTG0#I;i#BkF{u5U~`YuwUv9wg~;rML5+x@Hy z<$Ns&Yva71vj3`9RNE21^d8~*pEQYXXi&cufQugDAK(BYMA299N@h3*lv0fNlB@D) zSMqWHK&s&JBf&oN5B}qC64$@R4Y!}Ao_*RUUy2()dLvWVy|*Y95>K$%lD3{Ui@6wy z(F_JyVIwkt#?oAuWvQZvAmBy>kEimM^yl1t(*vo?W_o$}2>1cWrv=##U^QT`dHqPhB7-UCHeYnA0EqWG!wf8FBlWV?05i0}; zmnz4D`25%Z|16R(oYLBy!uE}U(KuEP3St6nYBovVR(sZL^zTRvlIaij7YPgxpqfZ4 zfB9d=MY`D%<{vQDTvNB+jypKwv70#i zZDddl&)(%d7dDC1vjImR@|c|fA7_w(J$^ol6!AW(|Nj*%cVEATyF}*{bAdw%3**8k z>zb%C#3aWwJX*sHbr$t=hhjc%c3N9e*z`)H{$Amkk+7FY_%E5rNm%EQCdE>pKSu2| zOf74MIeX8zKp>*ptFG4w9@9goZZK$#z5@IBppK5({^HIX!CKWy{G%U{OA;vzWC8;f zH(i~Z3>Aqvs|>8f0Hq=J7D$^qukD)v%5+v0=OcgFbMGyBu9ud6<=JKw(zUt`rR63f zt(#W2jVz8eb8i^HI(WQY)ldF~C`;Z)TJV)L0$}8Rf5QAUU(DKeJi1D_0j~ULsR>VD z*?Fp&Le9?~sU{aq94+@*oVdpLk+01TT1$D~r(Ib-fu(`|d+!?lXH4P+&Z&Cwh z_7Y3sGau=YOFmBxdfpPn^}D2b>U9`ZF-F6awh^IvAEdoQ`Yz)8@Q0bpL<9v;$r*(* zv$#{x35AOnznfjGz>mKX$ui^^4H}XromV0vBI#wptu_S&FCOLiN&JiZ0?W)(=IhFT zl03GTeO2l=juWXrsN?WGk2>@eu3^cHH^ee>ExWm``$rwRjyna7eI?=iQ7WOyB)Jn9 zYJ4rr97 z*-!(CL%Ya4RPuNLM1d_CdT)jMM~(i|G*o+OGE*Z4h=`$I!JF*631$QI^ARn$n&1sg z??e7M8dw0l{WqxWK0jnzy#@E{>@;o(6b}R$I@5T}&%n%pVdpuOQR#NNqIR0wtTPH{ znTgMjo!CG(`Np*HIx}O?sEn^f4gb8bF)_$Awi^2no1F&+h0oPQG$6~UDEliBSm@vqOx_N0KH)%uZtiT`D|j4!w3?HdwWfcPaS@~2uIpa~qBqEm z>ahv;Te~=|m2~J+`$*hS4x%=Xj~pzywuJ-JIGKTI5Ti8D8gG^KCikuL3(p-#p)Pj5 z46WU3v)wc3?H569(13siJ_s%yz|_gpDg6y!u0~xJ`@ao88aR!@7X!5JHw)(HM>S&` z9M2aVRtRDsGeZbo&D^Jr#9mz|s-0z3&^h}%u_P^*PzWgO$}g#cU}oXYFOd;J2wtNg za<;TN9RC_1Z&_X^Lg#-OM9r;=kvfx!#6=F%r%}t7SyS$ zSNN-+ZFBf_r;O0IYJ)JpY_$tOVjE12-Ra|W+If*pE?(fP`dpaYgh#`-*)m?yy_4(& zQGb_y_cr=?@rb6mN$-JU!~snJ!8N}wl|6cqR$>NEy>QI`z-s^JPI~FV&qd%-@4Exl zLaXd%y>eFLOo_=34~MfV%du&L%H8@D?hZI~fIdC%F3AHk8kjgOc$s}o3?xfpngrT} zw;<5vjMoRw5lcMpmj|k~`n_`}B|#7rlv1*%lhdbi%v!k4e=}3*40>EYV#jJ6VC~ez zthI7U*DdA4N-6u#p3?qS3@;&-9D6!G+YjD{AalXJdUZ>y+P@oI^g;HXnE2;}=il}kFw z#j;7JVv*TvPg;r2rdf1a-!Opa!llnZrT@G~j|xk2Y2om|sTO|)WWz~}q_*SQQriA(G}(H9F$UU_k8f}{ zsFQ|o*ps@hcg3EYc2*a-?u(1E0%xGTpnsjlH%wO_2|e`FOuB0-@y|c)d?Sf6q)(Y% zrhn_mi7!d%zrH3aA6f`SV*e0;TvBBTCsNI`>}I7#P}y_^`QTpM{d5V3C}f3%PqH{03|+T;0PJkZ~(a6W{f;A zsTF5Xdr5TC-p^vQ@&%EDK8#NdNv&Bd)yD80S$q54F+I}hO7qDrBb(@STdX=4JNMA< zz1(fMQbi4$g=%T}*`%`2QL`FOVZlEiZBSA^n}O4* zBg$)^>FCEQ7I#4Stz4J8tpol9+YgY4_YS9Rw??+MuR8wDRP>Y-Ojga{q7=&d8`tW0 zaR2xpx<(BzDe1D(4;X>yTNJKBC?80nF&RTa^v?ebQ>Li&D(tf)>dRw}fb6FU+%*zP zh)}su^eCg+LSh;+p-NXS^+-rSas1bNJBz%Y2cQ7ShYpR+xmVUIa0=3h);QNo5of+d z7ngV*-x}hV7zqu?M+xg~dig3Q$?v9pvVLg9cO;)+h7bY&ySihCX=KsYDVw%UzDzGL zAzJg3IyR93sAh8CIn9Yf&iIbC#;ba4w^Xw#eb7YKk|Bd2lY-RROr`fllg_e~nY3Qx zD49Z;y+XNl2cBPUv?sOBEp#kBs_DJfGW0m1U&DXyUUqHp z>VCOTY9`8Zy1OTyVQ|ZTPgiTlNeoQ;lWNk-qlKDM3ek*FWMI-BFE(^%yRF8Qm$L)MNz$ps480(T zW&ew15=V3}pzT&Vsz<-UQ71?t68{!co-LHFJz;yu0WnUS~ms~{hV ztK-EuL>{NkB_#U3+oV^@DLy3sZ>%srkVL$La_?n%tqkfXWAD6&d9zUS95~{1)I8I5 z6y3!K&t zdshOB=SJ}JrxPRwh(y08>@s_7m+x6dsmL{4e>m8#4#LO6e%)u2x8HeJ_dT-4gV%Y!30qt;a!Y{)*JclBl)s%I67S2(?Nq z@U>u9AIK?Azl%$^)sADIJcQS=$Uk;|`!AHs91Mzt1MoW6L3QW?9$UI9A79*m&mfs0 zbR{=Z>t`nW*A(ul>uaXi=q}t^XV+`_R|_F#eXCPp`|0l)41@2l7Bbf?h;#R!4x)$e z5PO!;?bFD`{HwkuafJ5KbG;LZm55aF^x_iHer4Q8U&JM{(n0??boPZ(#i_svk7OV5 zFS5OX(JRz3BggG;uV81a`LvrXMb5-QD23{oQx_F{{#6r>2Jx0U!uD|xQPiIG>$j;c@vCaL5CdV)uMw2aXx+&KqdPtZZ!Si>pukz@nF{RJtf2<7L_KR$PPCFK` zDr$Nl0D=VE92e1`FOO%`)<1L95A2YO<^ziaRQHwMlqJ1X%GfDpQ8cbfWla6CQzPkc z1(AzQ3rrw#7M`o#*Di3V`7*jTp4~y(tBOQlM5*ym6vWxG7-F_xOpEd7VnnXd#SO*x zUZ5PixI#8ql85lfjITO=6D&UJ@9cyFLN{3CNM(u)cOk2T#oT~tG_prr0br3 z2~YuWGw>HJbQ&pPlR^k&$tZdQ0Rkj38yTw)h3>~a5qN(lQ`&<+`5dVHTVFHtb?){v zHc5jKIgN14Q*KadW~Oy!R8r1-LY~a;gBqi-8D7BgBtEMH2|w~ZO%?RpkE^4Z3wib5 zW^T82e}WnmJHg(H6^U;qFm)DiMcZ~%qhS4N3$@KgRF6_7!kn;^wre#+|8S#XIK+@L z98p4vkS4qO!K&=dk8{s9zR}kpq<8MFb0q|w-im>fE$_=y4_*j|b}|rt%DKI558Svw z(`%cV9%bc2Y7LdACn^!J-W|@g5@gnfv^fvQG8gmqQ{dHR()o{)k zwb56T_?{JZ)lMXVF`OWj{FxEN{Cn?m_tY>xf^~Vzm!rJ+(v35L%Prfyy0pfb)*BzF z9ocLfTEzxbn-=Tgbr)+TU<<(_84sog5zPhi^g-^zdZFa$Guf6iX)EPy%`#`Xndc%BN8iNX#{Rh|td+-TWTC1{G%(NQaRUsS|Q)Km3x z1=A9M2}Z~bpXT%Rxf~@Hl@OYlph+=W4Q)zMZR`4c0r~t1KoEl_pZ79Ik|e-;HS&yC z^m~nzd1Y)#?2Ani{`{V6SHHOj42jNVSleIdf1Q^z6}~RZb`Q|USQ21l03262xm$;$ ze;$(dLzej#(uJYI3o(Et8(TQL{28E)<9&Dn`DkZX*Lr_Bknq9<7_R*HE9&CpU%4S- zY-fXg_6VjWT_CV5z30g@a&Vp)rIJ0yz-;hMkpVa}XOZhSI{3q#5?D$Dr<>;E_AziA zY4XXBw!9>{jFEy3^2Yn{z;dOHEuOuUsSmameAbsc2*;2#Lul2rQ_zAxP@kt>1dN}D z^|nw_OYE@7&enZt7H5f=2?zzHEOkSG4tKKD1)Py~4t>Crn8HB;hWg2o* zh@w|gCC|4i@3P|EYgCnY)ez4K#22<*IQOw=SQcLniB-B)|o@gOT!Aoxs}Ky~!f#jY*~yt5fGyZ}FC41{Ibj-#I1MBu-cs6B==VrndR*pUWZp(75ulY zjKuyw`UJ4wji!GOAYHC4y+cyI2Gdw$p1~A|Uq8MfL00rE2=wd}KV6#DUN`0?aR3Ln zj8uEt;(z2PkXKzlw(>Xn;pQ$NvgEvp9$cxK1l>o_H4w%Md)gU^Z&_-`asGL@XN z^XMaG;sV!IoB|DgdYAkQ$`r8phwTVMqp?`E#IRCAcGb24Y=R6=6q@26b@YMtH4aE@ zf+&bO^7rXAaVs%TX%zg`YB!wa>C#NnYmaTOA5&UUE0Z8pP-W)qWnRHlw+Ndxe;w1O zcKMIG2152<>d0)4;QzzYSpa3(c3qq9lvHUR0VSkFN@-9^LXeW~?(US35Gg4^0g>+R zE&%}n>F(~5fAfC-4C6QsqTJlqdG1*2Si!Hcg%9hwPJrqlo?Cl4Tf6Ps2RnWX(d{uh z@FKy_{o!wbxjE4A7?0WyG$ih}iBEqFjNi}OtvC2M6-%psbqF>2xL1AEjI(CPwbv4% zmc3Edss6BQb6POfn{axBJ?9mMGC1*akH4!@nRrM+9=ywG}sa_#NVC zk_@Ks40#oiQH}{K-@8bB?iguA$`%?ykE-B$mvyvPiP3({-4|HV>E&M1ovBe^mwFS1 zVLi%%*b<{*I=z0O`ZQv)@1y1GXCjq%&gAaV=(Yvl|4oP9D{nZJ`9;9+6HcwgWoU(e z#|a}ZPD{2f9heqI!V#=~)(A?L%$j?5+RyN&i{z#jcoE=$<`5FXkLnuPM}9K*AISH@ zGDi*f=JF-g<60MN*HuX&$S61ogNN1dzWyU)Bape=IhNWjsITYIJFvhP4sB@l*{p|z z`(BmzR#hPT_TB!Lx$!K3`ugj-TdSW*LBPK0E!HOaiw{GusL@0X)~UBU)Pkg^Y7{V< z1tmky3|8k6ao)(r|CT||!BF-MxFJuZYVP)RB_l>qMwjFe6bzVe=4Cj=*Yh;TYi1J7 zh`AfWJDKRnGAJiK)}&v0$w(F%3ZP!qJg2zxPX@2)^=CD#xcJuCdYbKj6lpBnehmc5z6kY`_Dzc2gjJU~(x}m* z;@+_EvA0hi`L0XW>9~EwsJ(cPdnW-6htUa7GOm}GmuO#$y>ThIeX7vbaA?>{@~5Ic zb3N8uvP&24QhS9eCX~zhavzWUr2hgJvej)e2_odZupQiKj`5)oou<>`c6^*K^ocBW4Rlg45 z2RcO5XBHhNZ8*BCwKxmO;V!Nhdg@Km8 zUrjO5;2?EhK!!)cLiTf=XrH9HfJ^Ref6?Xp%q&x0{(2C}2WoyIXNiS_s{2yaB(pZ5O4> z{B(^2G*%$@u)LIe4|15(ZS{jI5EY4QD6w6QVEfOvh2R_L>go<;R>Ajd9|p@Kvx}t>7o%#1y8^Ns4 zX#>k2n278bh${M zl*&xwr@9)6)oJ)!sX^h)P}Yh?)8NRr!><-&P&V1i@|3A_XMMfeknB=233ma@vq8&b zoZc1rz#~7Ws(FRL9j`{XNAlK0=;}U*x2U|&^=O?fR!#DpM5vm z`8(myvJNr=(DN3$IF(vLt*z^+kG5=ItTF_@YjC!$rncBwZ`&*P$y6ygcE^I%xph(X5!j2}NHI?G~*eXe0*)>eM@gpzd{1<1T-;V0~hAn8M@D{WA z@XL?)fk{v566O5IakO|973@57Y1v_A{?i*npDi%GHwf+FKy42!vpRZHP13zoafs(G ze!2X?!5N(s8~EYq=m^A}K`suz*34OHpLgzpsp6>(B=pz0sItdBBe`!%q@~+rrc92Y|x_#3(c$E#NsNM9cqKgOF&LpR!h?Bn*fvxi*a9!uD;{*T95^UrenY@uMGi}3~b zd*6yEcf2rfNmgU55AUEGcK@pS$jCV*DM7vJZ+?Yvv+r9Zycy4d+V zy3mLJ{RUhb5qGO$fFBU=t$aOgCwen~Hyt_Xc>|us?5WBSKg$frTl^P9?Kf3Agt`IG;!IA#f4JGEd3Itk{g9^5$W8RTZeBqW`#&RO2csU_TLPi66dG!hc-_kff zMnPC%gtQ@o1PR(o%$e=zYLyoRBp% ziZ`sJW248krz5b zJa#toiX^!oux??n34PYN`a8Za&~zlAl2?wQ7D>UUw7S>o$3l*C=i$v0&Vok=Y$xq| zLKi)6+HVB}1cpZ(($+A7M2+^M#OdzJHD>>!&h9YG3B==*jcc!6n$xIw!FQdVm+VqM z*wx*w%&XBC%ybQP@QqLL!<9C4)BOQSqKANPQEr(e!0SI8^Ltz9&vVv^&)Nd>ds_iW z>!0-#JoWqy$|lCgqiO=^6Uot~o!yX|)r5@k(1xkEyVhIGa852bUha0aV<314t#(TJ z#vp(3m=#h-63i&^M$kL&V(g_IIj1o0-1s;WzMxB;9nyw@hR)9M;-lZJ>iu(f)IPTj zguW6{Ypfqt{^OSqJF<>3Gi+70quHJ4Zu?$;*~@(wl0BQ|E2H?^bw8BMj?TKh?i6i^ z(o_sYQa8RBRNa+Bu|X>n#E3Riqd@|=XoA<*n4Y%@gNu=Q9w5u>O}yu(1(3+ry>{a= z%;Ee$bjrq7req?kpza2gS(t;UMTm5Gw;@ZIC@p?Kr*of)JniKn5fiyA6FCbzu>-=5 z1wx{O-2}hK!j#ui?-{#3UuSyVu&U)H^is#v7lXHFISqgYlSd6`;_1X!0xN zv4<6CP`9pVPI2d(&sp#yPYo}7a#ulknJftQMT z(aY<_L|x81U;52gpv2LogVXhXTgyTC7*BF7vTH&|#N?Vz=b4V0=%7rO-I=C!fcmpv z!#DAks4}%<*q%sy_gx7m4o(a?A3HK?kZ29RLMdw8=Z-Mu(q+$#?$hnU){)?dZB;6% z4^e2*Z7uD=4#-0es@!2RyvI(g^5;C4_Y-!L@L`rZ?^2GRKBBQ06^{?u-<#*HyL+t* zYpW#|dnXTn`4-X@-*ow0cj?m*5a=^0DY)NQ94qKGY}|k0qAu@gE;GYZ;_>Lp!L9i&s-R=Oua^i}VNGfIdW@GA zMtpbUh~D&yJz!2uPqk&TloEv;&;}`WI>Ys_U)l#yPgPppL-?4QG|Ar#d@hJ+fgM;3 zb5v@kmbaAZDd<-+uJkVKxG6eYuk9u%tlI}E0=D9)X^jtQKC$UKERu**zF=zpkTQuX zv&O?)>)dLp$R&tIo{v}Va@uTJV*0=rG>qbHGTrU;!W>be86PrRK6oCp=*yT4Rk~ul zl0eYGA96#bsIv*0nnTplyy`U3TE@isAxE$Dao|TKJ}Y8@d%A{M5EwE|rQy<`Absrn zsbK%9(OCJHVcqLRvZm%|<66p9ANb*i(}I6c&)CX(F&8n`mmiJ&tT-P%TCVz{Q0{xCs3j=-zjLIcba?LH|NoyUB7^9<2zu? z{4gJskmEAsEY7^{Hll3yXggCy;tcpL&H#iPCXbKf8hu6ZA(})H8Pg3X+eC&xwQ#dm zrXjp<<)>N6BWfb%&rr&c#>XF=TPSKRJy{H!W$xqt&)mW%+a3f|w#h4JS#t^X>$^B8 zLwoiM$8XX)qSDk`>sT3v*@Bf&E;EajJ~Rie`Ces;u?f9-ou$A+3Y=lP!|ozNzMChq zc=$M7>Fv*CggQ7zc*M1)iVb%V1T}T1ej{F`={dT4Eefa?kdl97kV8w=VBkN!w>``| zXkL+-XTp{LXO?qG@atz)*(@bqhr?$qjmN|+Qur+%+l;(==3PB`=p}2xQ+j5lSDwm# zGV~=>NE6amhFA8iU)#c6YeMZS{EZ?`*0qkW6|EaDj1hek6Bq^_V4$e-P5guUrWt&1 z?7X}m?p&D`ms9{IOH4`0ce^@0bp~Pf5=^VXr6-;Q6o3`bYWnUM0n%7I3J}f1H^a!? zWLU4V9sD27|JQ|?pdqQ6){WpRfxyX?DSretqN0Xo58^wvnS!j4hh!P~fr}HjqeW}F zoND{44~vMg)#QH}iu1nwB(iwB<18?3UB&+1;7f>bK-R?V=Ev~`;Mn-1r@f4-Oy!9ydbqe3VCkV~1%WM0rl&!C)cnp;}cx5HOQy?bt7d3Ar&tWID z;ieBD=C!FCXKG-wbbq1uX7I9e)zTU&Yfq+;HU0n#ZTJwR!soG>3yt_B&ROp}y}+pF zc9_iTus-zxZ4SMz3R$3V0{aNw>9HpdoPcNz#jLm=q0c1+rN7y z23?S)Fg!kO#ui@A2(!*h<8Uq4XHTn>IwLo)|r1j8P{> zis(ucifB{hn)Px*M`ETjFeJffJb&rE=K3V;tr8>zGzL_FSR9vhz?cip`SovxC2B)s zlYRn4uNQL4-pnt*p$e+Hm7m~2ck;Lwvjall4-)Y)VO_44z2cJA*F2=7f1l??5{IK|`v}xl z?zQw7R4r~h2nAo&pbx>%PAp_D^4G(;$jCIS;z9?ag)hE+l6KujTx{x7tsx@2Y`wpW zK&C!Ep!;3k?SHbQL62Ewr%wzchd%!XZ-+o9IMgyovhirTb50oA z3a$!Td#)a_liKs1Z0*he6uMAU*N8}$`|~JPerYAgCpa=o>_ca!g1xWZl-w))Yeq{m zYy>pq`j=4O2W}w3*l4UVqrj z49nYA>JE_mfc>KlfGB;vpZgdNZL4#~7bZ>8JIV%MY95_JGJ=iA)D((tZq9QV`UUC~ zVN>S^BL!{%a1aI~W=lPAofQQk?kVtBP`GINAV`cp0_suPfkc8Zwrtj+@J~areJI^q za19`QtVj6dvA(WCN?0#=vGwh|qlaR)x-CG!8Yg}LpL1xTY_Mk%wwX$%cSJ-i`>9v| z(S2d+rThV?;fOHAPEoUil)-F{vu%g~?N5~=o!!07`M-N6Tha}Ja# zEpihjM(7a?Wdy=UT6yYB4Gz6qv7xMV2mRa#$bYRpsO=?_iw}#+&rSMJ(nj7s$(j<9 z-a6ViP(~8KQ!C(cz4mrI(GKM*62#xip#FCLt*KombWY^mp345k6kD(8zfa3!D~;Gi znPv z);0W`H#k>;E5!zGx(Za><@Maw!WQC!PeEU6VA&)FHo|@cWntOaw;sO?7oITNj1J}i zHHw8a0L}!Qy8a;orkm{zvV(IzdbG;PXCm0j%pl~10bN9Z<=V4>xvQtYknBL!NuG35+;L@yLqI)o{p5nQ|=NffO(dm!4Ay?I0 zwPn7&z7v%B9o2&Fxf#ml5g1x6c@M{KgWLPEI0U^{$(^T~e^c&QdK5M=gF>yw>@g&TZ`D`N`Al;nR_)i|t$jx~_9R{!?3;N3DwCGiy$(_)f2b zL>GReuvOwl8`MQ-Jo@}zTf1}adSEV}nfJP2?vhpSYdbnPF2ejwUgSAb;Gu)gIk>^& z4C~5%b+d>2nb;21m+25M17-3DnrQG}?^UOl{}{5BPj9a`gfg zk$f{|MFK?wFd}84<^BL03VL6_EMWr~0LG|+*~j#>%wnm?%G{p2xgRrlzQ?161D*g7 zkubr1gn=skpzACm{>H5(|9SUTSeHN_DdzD&IfX zjV;23_9ypkkMw^Oc-S)^Vc|NLM>@|)?ZMzYOIu&h&btzqC67~X{*Y^LH6XuhT)BC+AwQ-oE`Q%%_T6nXUu@Dh8N6z(pEE4U zxLSV%QP zpWmp=p)>`*Q+{eEhh1L2NC!YJ<|AXhCxQKv|F?aL1*Du70r>s%Q5s&an~9oCn4?8q zPyha&_9V|Yqcdow))N;YvxK+trcb9W7-`maNBi9KWrmNTdkWp#nu-tGXGovlkr7Tu zW7^edfr_^^Umh0$WNLS-4SB}d-!7=18S$2=8?T7!84tW1k9{y+*ibZQ4`@cqW{aCk zvVDZfK2kY>W64<9<=_1fcX3XG+2mW2%%*EJUG`SzrJ35e@A;&Qb83-ta>@l`T5*Zi zlg|=ae*Ky8STNseJ?Qem*pnG??O1J3dyW(T9+`EHDtpWIHu_nSi+0npZ+O>|+YGKG zEX5vbd)j%qOPhw4kpYZwRQXNl!{-DTA0$nH%=7NO6A8Fj0SL!PRStsliwifXVg;dl=dfR|&O9 zwx7c02p7NdUvFJcQlbEQUVfg43^-rlTvV`VwCq5`RE>_d`}$Ajg&R>lJBhe$^QanSAYHYaeofw`MMnCzPliVCuS~W#*+qZVBr*#kZiJgn&6CL@LL+A!nYU*gS@j4 zu{};;n{_S9f!iH+-0;a)vo%h~F24&5SQc_xR|0A^!wufSi?yb|l>om!X8|LrjV1L-!%l?&>I;gY% zl+aNpyVb2CjbaH_zmPR5v4xJ1=$#tGi(kz9%RR&t*(|%Y7f*P1co3u4N3D30OX};j z{(O${Rdhaoge>MDoL!XI`bi`Khqou};8}bXQF-)Z!hJ{p!&0XIR3<^o( z_utS7+W(b&_LYl37_==25xLyn43w_8zfmZ{;l?9xKUvtiBU`AXeaZUEDZuTr3=@F~ z4$n*E=Phaf^CdbavB=(qy8@iljt#@KMu_df3J>1cgH3zdfx&5~5u161S(NeEv&Epd z_r{xU(w?!3^EE;wEPQ@O3mpxo(8Y2rf;8?9Nd5||7qPUwPR3M(-b$KZ-*k}ajHZ47 z*SQfwGZ2^j!5sBXD(cUT(d=>d^JgctRZ~0g{L~V8SMWNl;?&mFy^~7=(LEZ%UCVJd z0_%xod|268L<|C>#j*+aw5}8PsNG#_%gIty_&gZ3iKbiUt--?R5EH~#(&ig8?GpIU z3{vXB)n1|o`fpCy zb7=QInEscG7v6!?G=~qr0wkkuCKCE+D3Hr5Dndho)cexI7!l3 z?Y;3?{lx9Dlnmcw>~i_N=q+^1D?eu2yI#nmSg}2HMiFFx@at@nmgs0PW+~BI579+u zJe1klnt9~aTMfa!+)TJ-AdUyVfjhfx5-Uv%Vt%k7kIQAyYs#zT5@jBdP%wzKwjx2; zPufjK)V$lSW^vOQ*Z$>{E@u*oi~(oTeqRmQL9Y^;i*_BVK$R8YykD@5Y94BjiMQ{5 zfDi5~%H+CPKL5fhyf$6V1og8c_ZZxmL3~^kv!T}tVv?O8W7#^{R8{M7_z%&z%pc+N z_VnRzx=7jE7dVnc&P_{I3;2#><@o0LoJkP~eQ}W^wsT%*Bo(7gkOS_lJ82D}TZzXuEg3RfJ0UZ!@~ESjaPP?PSF3Uy}=_e=Bp z$8j2}mA{nP)oC}+F0pyx7c29c92f1nuI_ZPmeP+?0ep%aC$TvT?1%w2wXbC%Q0gD2 zts*gChnx4#=%HLZntKs=@e1o@4#}M_NNs?jMczY@szn%KjnWnRsR$;Te*;3zHEG^j zH@j~zP8q18?y>>5mrMrh1Ign3T(<4#t1UuwF(E11uboc+cHgE?7#o4SpU3jyg-3Ih z`diH&1CD1;%|GG*0?v>#sdQH6vjRZ3!eU>Hywea}tC%%F=>}*Z_7S7qrpHq8M9PHy znUDXQ9NAcGqX!JX35q|x^*ho@T4{1W+}YmF=M^#ci;#Z7bj(dMX8QQ6v*NBsgT$tr z4=ew}6Bp}FTxCpMvlA-wRhOc7{hE2ZuV*8PIYrX1i*QnY%)0PWKzt?~Z$?+SVO3{28SRs5@+D#Vr>bt`$lOv>R z+g&;uJ*;g|=H4-J4rXF3l+$J4 z^+z1*0=^SDW>BwoG8JX#{P}+fFb=^gTe@QZD-?Jz8BlN^;KIRr!3va0RiXv&~JKLO%0Utd9SZOYEZzc zTe_TYx7~mvP^?MVd+VWX#~0rfHt3H0m%vSW(IK=$Q9pT;$v8hrAiK5)_bN{3T5ei|UY{sr9NGXjZL;n9i_ITIk zeYL9PkFVos&sa5LiCQFKO##&fHcHX>9YYYh(T)xY+KER@dK;|FrZCS&F`$3gnlxa% zP;J4JeDH95uRXbNhSoRAD(F6>!1H=oBR2NmE8Mhewd8CuE%|yB_7XB#z?nXgZZ6`- z?DZZ5GKK4>^QR30y|wg22;G@Vkq_ZXJt}JOr#v8wX*yb>d)8_GuoMMq^MLU!lKkeA zcRE37g%W}e=O~eE-w8Bc`dJ{8IyM-Q$4E6PIj8)}+d~n|dMya-g{>1+)Tb;##%1l$ zmHuh~wI$~nCB^N+T&tmr!P?%xXM*qRU;-@BCVO%LO6$Dd?qm`uUON(uf8}%^s#ADe zGETU6y#!DHvL1n%&n)A~U;E{wi%XpK@*h4*ydQm2HRd#}#%97~1eh=iQ8XqrB^unn z?)Jc)U|j`>o)49K6`d2y+yrTz?GylL57l5dqi$jMIl+eQ=(9>&QNSz@0QH}hpCVqc9EKV(nM7q+$tYCM zK;+CszG@=Y{X`0Da-6jhrBa6j4fU5;;ao{LrKluRF4vD~Zna$-{DMze_tJNm%{jmJ zK{x{}O+XSyfAIINe1z%+T1h~qAu+{$br+<9VZPLI0|JJ*0$#inaxnTKbJ?j75P)i-oYBdOP46b}9&4?PL71~QIei6A1f%(t<;2|$fQiW5rh zfhz?(e318{e@N3NI(W|?r}VKUQF9RToRq^eBnrTEjF|jdOixei!cCQ|-^jKQUy%Wx z2tUPTJ%qxw5chNq92#j1n3SorFb>jD$>|P8>fR@SWJ~xiL}3NkC4Oq;=2o-ZV?Wo_ zmZv%E*I2b9#+E>a&}_+bhg{kx1x_B&hvkD-x}jq4>+5q}-M8S)L(tAcME3HSFP_qK z-~}&tU}K=s)M$P&M;3&!5lNL@t0@vgRs|>8qvV0iM6J%>gN=y1Qw!T3RZL>5PU-MI zr#)>auHCz=TCcvjS+udw*_HG^LuMXHbe2u`#$;?d+*9cPt~+Uu%RlfqWrwHjk0_m(x_Gh`aAd% zX`LbegltScVV(Y3>HU=RU7aP`qld$P8c?Yly*!eduo;!0C+Oc9?X&`W1uTN@{0TeD zg5FO2;m#q5E+;$wa8M#dcF~^2WOA_%tWUi9ZOKz)KdKV&eACIba5-|atML;3LnAx# zpp%W*;0qs()ivcey&u*R`q2>(pD;Pcw^4PhRwCAon!hd9ak))0e&7yJ-gArqsQOKhmMOj1{` z&!8LHwPeJ64M#G7kX7&|MnBw5SU}hdAFvfDTaJ(Am`o$$_&SpLbzqO=(PRqt`jSXA zJoZ3v=v8{;T-Wg3MJ(sE^!|= zFKe?bX)%1F@>FU0NxF=x&an7S*n5F_yQlLBMJ)5fj5^JQ1vAyVKWFqa;(!c9D; z3-MZ3(5CG@2=4%n71TgZEi}ru#P|EMexs;0!i4I#OwN$q)D^0(!RBl0lpm+7G3pN` z6x;VCzbQ_WaVB>;rkJLfl{BXfA~p_8xUau7ys{1%*k!7d>UlyayIH~TbqyEMK(0B6 z+7YzspzmG;xXbXhK-?mj$4Rc1QeJpe=A-*x@4@@Fqw;RT2ZU1K+`sgTA1_OnW9ISx zA(yN6NMv4i0Gm2fdL!pfglNcafy!~1XbDa9cjkZ;nBF({f|))rD)jn3)M$6fKoF9b zU|?qU`h&;HpdQ#)$dzR#Mi=h&ql!rLQb_Vrkm7_-Ykv60ynPZYomFf$l3g0Auvb@x zlQ{qJ^h$I~kDGpLvs0jOmjJI0{11wcqC%7CUl|=%>($}!H4V@s;H%?JZp2%u0atVA z&mT1KxakP`pv(!R2rKagP8H5EH$#sg4mUH%A{4tDzn3)~wi3vquu znNj7)!jQ=CLR)gqLUB(4@mG~^^p%m>j3!FTp>u6>P%HIC=M)Ie8qYhPVpWZ~QxlvF zWVVhn{7xq{whkCqW!}vT~krB*sIRd8q+km$Eoff9~s(-I3^c(5!{0*(|VN>nd7He0rgQh$7hb0ee0}i$`+CDt+nyAT= z%U@jyVt3+#xLwg7eZ5rvrJi-entn|l1@t^x}dEc`o=)P~~W7i}sD{qUF zZZQrq&Wio=UN4HFZl-YKt0mMC7~IY~e^r9F%@OHO0%xxt_t%VyoiZ+b|M@cN`+cC6 zd9BnZxB>)rp;BFLNeOeGup`e;T9C@7gbjjGf(}%RXz9ANvyowZd}yN6df+pSPkd;* zTZ3Eo@}#Mcfs&I1z!y*nwAN~q251zhl1HE=9+{O_T=bE4tv%ruubjc*4q^6CzS)DT}5Iiq%f2wGMMAoKuLAqL-HzJ)< zyLmg80>ZB-lHF@j%OKr2urXwSE%*L{lYY=hYpXv3lPo6U9bP~8sWB6b70}_3S5o69 z`A>kv>(GP1n=43=vnxHoW)Kp~rEst^$KF@mz0~Ftfo1KIB)a`^<=i}V|LP@2M3GeZ zaNm(s7gI-m30rJ}+^&vLB1X1usffE*;7mCl$cmsl^Df9d8w5}zjOtyY+r4sgQv`6EGV6jD(j;W5SkA<{(E_wY7#v_ z#&M>Bayvd1V1#WfUunPbjEohIW$!5Ebq)|1Bo2XgO%g9!%nGTCC%?aayD$D@~z1->qJ8ccd2ZOTWIP@ZJX% zC`WRM!4|0M zySGKqtY8DH#=`{up(k+~E(l@=4h2(67*jZ^AKYd@`TgoYr5MWB|J~Ckh#kzqsWdbW z-&Pf*8lPDM&x7Pu2nW89u}PO^nF_OpBCVi@wV&4rNjJ-2+rjFa&xpxKL~$9GPQQ9U zxzM)b3}c5ylNe_$15MKY4*+mD=pZk>xYwP8&xq2dUo{ov{pre>kMrF>*fT+AK~(z@ zs9~OxB80vjs|3P9lI~hVcRasgb_L;*#HSXXuMW&@5+FE)0K+yN{t8T3rKh+W^*8xN!V(9YnyllL zNq=exvo@vSu&lD9iE=NK`^Zv^tL`HgM$JZWDLK%)7s5)LLdg5tUy!DB z9?N&#((^GY)IRz~gLZhG7Lj=#%X zdh>>3t92E2Y6!sDy^<0SIY^IuOWJ#j^&vs_HFuJs1g=ECpmTOAuavzY7d($A8Ih+v zLc!ik4`hY@S$MjfN@&$}guEB1Y+Z4LP)4i_<`G5|MilkY%kBY7b?KYKk}}u%T!(e5 zD!S^1hm@3*qCR48p2h2d6}-9W;^jkB^SbM$_dyrCCTvwwLorttszbUjz)Nir-mG8U z{GK? znMv~W>IRlb{zi0Pqx&lE`5VBo82w3gkN{ ztc!JQG9W$8{>Id~;*y|FqdliW)21)d3t_5xn*AmgxLhLP(~rvk_PRERy|;JiDU^S( zF0F;h(ym{U{XtHBrku1g(8#IY=fMlMSr_-OL5^i#f4-m^{;%K*RZcuPU$M7w$X#wWKoF(+U*t^J~Gv zWFhRjG5>~lyQI17Y%D7d`~3&(za&R^o!BB?Bu_z35u30?$RMk9<0Nk^%O@!5K>Yx+ zP+jH3%SC_gd!dj6kExqUx>@Qj&GzxvioMYh*b($gFvMu_#Y%>_djcSJ2;1pEG87Qm zI;8l|as9rKP(`7`7_D4Q2iw$))S+z&{0}P6o@lff+kCgG5M^^%4WN5xY*ztkLFJ3B zh-80@l|!V+w4u!fxr^$0Y0%9E*P1N@s@BZLW6i8J$e!O3EqTGH2;!B_-|#8E0bpC8 z%l%Li{UAcgtQ1rAjlg2kr!^V)Z!;DBGUS9|1(K~|`R4Ad-*WDn?PWWM<<`u{TfQ5? z-;+p!@(-O|K7WzE#|uR>i>DFF+P(1g>vJ92rP)AX8X5{`aQ{c3A^&>mPObD*2<`U$ zE!Aovr4eN^rsW-BcXuLEZf1t}coXybQuba>nWSLZKBx7}Zg8Kmgh>dsm3Py69;ov7 z{gSI_(%9xVQUL%_9OQL&1F$-rj>K#3pjt)jbqc>ZuD7bmg&?ixc&YKcKA8NOe9g&}Ya_wTqcIc|*Bszw13XgOA-H3J$*0d5(H_g2 zY&V}eWA$iFy$<>8W|_V8Lhz;Qmh(gbDaXG)q<3IN0JZq<70Bo{oU{>`yZWFZOog3i zvcAuD#;>1bYhsdPsyW3=CxrKprth;0susAe5@&0Au$ zSP4%TRdRTnkSmC!#arYls&GrZ-|JWIP`dUwg%RVB`*SZ1P6=)%Qe+$_^B0*G&^XnDilJD5!gW`Rbc$8c^@XNP_{X;o2B~yFo6#P!SKP9|^gM5g zqM2(gx=B~Qn+om_s5Ve$kFJEbaSr`n=u;>WXUTqj zf-G|RdwX&$ydc@5xR|0PluM?1?;YxYrDloV&KPZb>j7Omq^;`il>~v&JM$A#!T+7~ z8mL{*>SUU-XYSCa2er*1!{fOAo9}CM$gm~hO)wLSsto4(=RRGxXEI$U^*T5mbPASK zTS{k2j#HIZ&n~L(K-C=A-ahJa(s2LYadgi;8#zO?_yA1bC{4gZ-z4+V$&O!!QUt7n zBZnSZZlextubO%rv9?-1_oO{JLGvTIO_$D^2VXe&BWef!JRFc6zk8*@)tBO!d!(y^ zSHYC;udbmb%3#v$TtosOOCtgFS)VC+a>YQ}^q`jFTJHGWI+kSPIsWWmCM*V1nl{}M zwdhy>5ri`ms2mm-CUz=XEJAu>Farf1xYiaY3ePfJHznFL6&=y}B{W{`?f^Wp7^0gr zEFTf8WpTvUQgc$G*^p@^J7c9{i=;u_wK92#6sfO+guwP42ZTvDIL0*a@-G%=6 zP;vUNOM&jMB>AOhG)$S*@%ox#`h*v1nDr}*echANnIs)azJeIC4%QxBZ601s&e`MaziQ^di7|p>-G5Ur4AtmN+6OtEJOXPnr?P#;W#E- z{YfoYgQ;8QZ!A=S;zW1y7XN)jbW*&e(whN&KbX*{j&{Z?ap?mD6GAc1<0^OVB$|#7 zg3kHQ1^%|1&zf@U&i}Q_bireGD1XWLKk<8LPx_()|APJDGF^z#M97=2gE1+c*4v}g z7wgArsLY`Dmv}}$WBO5E=sJi!-#GS_OY}29>cf(W&Zzw&!l>6V>``p%-qY}im4AX7 zN4Y@fGy8tG^04HA;WbW^)6?Hc6#rJ%2A9^>QYMJ-zIk=f1vaDrrRVq48w!~>LMVeL zd%k;Lsy>)!LLJV5ule@^$z>8sbE9QzkpHEr$SNz34-f;+^@=aeIN2)3cQJh}Dl zulZJNRg0ADeN_})#uwC+0;Jk;iKo9(TuE{%iXXXZ9<7dQSj)O06+VJEG6vIye;}Q( zu3iWZj=sqvCr$;8YIfnjtw}Ov>#Zan#pI@E_slmP3%-h-`V5C9-H5abTn1=Jc8cp;|i32@XeV;9k=I_jTA-o-WhhcfWeG^=ZC|H&sed=Q9( zS3v>O5MT6CI*M@6Fcz*KEToQ~H1CyT{Yhd$yzd7*5CCx%HBs7WqRUfZV*W`mGrjC3 zNGTR5hr1XK(xF543P=FzI4CvXnj0Maqt9sS1?>?y45f9u5YDIZjw{t;-k3;8M`UVd z{~q+bYNB^I&r!QRO{e4Z!GS;#FpuA*l@(F@ZJ`rXZ>lD;k|I_DSgKF@YY!VR3BiTE zyeK1F;_LYYt*y73Wy|cRTM1LlBiE1WC_Gj*#mzyBl7AWBVb@&5k|J;<4}6Iedu!Dv zRR1+jUiN<(>V%nN;V>LVf`1D#@W}dO+;Yp`zhIGn5zCL*;;u4BK=byAMd6A-kFWvj zKUNCzypCqS``hV?1Yamx{|9#+4O2CZC?f9rM54DD@T)*J3TDcsPlV%tlVYJJeiTm5 zdRq&=fxGWGH-*H97$|Wd1bl)EfeYkIYQG>66;-*l^`89SV^dm#=Fg$Ii5*jglPFPr zY_;rVSi!Q`9a-;ZUa-6K#|T{#%Tow3)XSf%%RaO7$S$3v|6s7pMlaOhhO|MUmh}gVxj(`a7tD?Pp7OjSYqpD{X2VRMGA96*LVR?;5z$XLNB4&* z8q=2F4-$O|vMV}5SBOG3Eah|Ey})+0aerFrwH`HpToG>3hE=?o6i6rAvHGje$wF&1 zHRIvOi;JTDfshoh*DBk}ca8<7*u2NVlTgAzx1FB}m2 zFr#BLaO4viXiXKK@&I{K|23)=UYY9*ptK7La3?KQ9Y1BeU|5|%cLxZeAFdfbZ~t%S z_K#KTVx%E1mg7E3w2Hk+q-3vmcsr~F!`+6Va%jmO@_mkEuk%G zJifT5s_emG5Fy$9>d|`|&kHZ%Fwf25o}}c1x3^PJGYYdt4PyrduOEyoL*bDzIbKFmmW0?r$C6f8T-RQ9!(V;Z38SK=2vr zUB9ng6@jJvR7=8v?%PDA($H=y=(O*0g*=5<2U!%Q-j9l$#Mj&J%2{K(i?L&$)iojae&4 zN7!`@mkEK1Sbs6GTR5gbH9;_X?Eqr07=GstVwN;iu0TM@gnnWL06-m)^$)E^i z5iAj5`aeV{FH=lc&;n4NlRgSgi^M}zT9(LZ(e;H^-T8`m62Ulk8Su?IiJ27ENz7?=C*5q!{!d2pIr7mCe9tRzPcZZCn|R z6|7PcgiJSri^*}qe=8#75e&pahik=q)gtT?`NVWGP)@WX#aP$KGWP6l)M9H&h&V5h zM_PF?7M5@q@pj;RZs)m+XdWnVD)l_DkY3dLQe*7=1cpw2(Mf4uSIT|8pIJ4T{if`r zc=gxG^>VDuF>cmhM^lt$pY}D4Aq4G4+MA`NMfqw6ik97F>n6N-6_Z4aglaDR=g9=4 zg{U4Iqs-(~hb}@yP{g_p3>(EyBChK>-y2qFNL+p}YFn_a{#>he|KZB#D3*zpIY6G6 z;x@m@FfE#1=H-TgkE!#IQE5Py7k zx4XAH^?^!(-3CT3QKR(hKKH)**2~k%i(uPXq|NGN)-wl4sRF1MSZnrge;jI`T5KyS zl63jjjysl(`%4kK8MiLy3!J2P)=c9i5Zu-W&N!LQ*a76e)3-kov-WzFxr}Y7hq!FU zw}|Gse5;KjcgJoVq*sWJ!cG)}JCf~H=K{tsof8T?4x``mKa%=Con*O-dbJuNr6BXd zQs11$2KWZ@;nW%j@8wBRzcS6h3%A-h>O8rzp#cHF{~{4u$A^x5<1;gFMF9FN4tfGT z)Hz`@H#guoryU^-Ugl!K`YxwS(R7|ie1Dha03g``trujIT&6%MP|YRh71=(XNchTx z`b9yi-JVf9KMB7;G!F#<8a?zZ>?xKfQ!y>qL?R}R>GZ39 zMe>v>BkT3>{&R|*6!mJ1dUns$T8(sUz1zluf7yt@H=~zJ&d)J#y#sapZL=bBhu%;1 zY>85{P56jn%&gJbu>i{|HA4Ey1lq5u#_KSRZ#nNwi`88%}Pd>`q=Ia65`^UQ!^K*5~4eT#rs9#-6L}I@Uh` zO&bvR01Mm2V@2o>(S1sjwQIznngTyFD9Sxb0cU84fMg;g=^)VV-Hwg^x*fy&0Ox`H@ z#m28U4GxV0Bc$#qBgfu{OCDaoPin(g`U-Fjxy*_7y%44!ocS{Rwe`w9Yspo5-948- zz~I!zhnCJG7IM+COhWVF1xS-846zAUps}UMsH~D_t(aeOin3Mu0UVwYR}zJ z4{Hu9|EDfktaaVG#9Wl>+N0CW`K^`O@gXz10V3Br(BMm>*1tW+u)(w~HO$Xv9RG$@ z)l@(HmSO+>5rTI810@B-hXT7_Ru^danJO61SEIjb%=lY$vM}ZV9Yi;D;d*sAlzK86 zJWBrC5ovk(00RN$kEf_FKvqf$_YgiL-H zYIdy72lsHC7WlRw2w_&|-U)TLPPA})->Vp9-gCXm5q?$dem2`1bRW#d~iTLWeY&7CFdwses(62#l!fFzqmA1}8|P(aWhq&!{@+ZX#$1XCjRiqU-=T{#IN{#Hf^<{(`++!OM4`|!)- zjgK2CmN2j1sL#u+>unD#I3m9c{@o{(TLg`l3K3-Dr+lk^9S82F#LUk1J*+O7XpIzy z$~HAfCu}|T4B_{e0u;NHSot^I%47_#l(7hkd&FVJv|4f@QpJ!ovPe56VCY(`)6~Cq z>fT&IaXCecH8zCB4{9+|0^^e9z;7v`7nZP4nzipTTwxpMKAtvY*VfniCLN(Si;J3W zmKi>%&DDKl&P$qU=s#*z?;=%)IS8jZe)@%5iuEyP2}sD9mtD<5Gitme0o^-r%1DNx zbb&$=vb4V={?a`2OkX7;V{__N784tNWuQ4RIy$;Rv~mjv<>#xX3P?o%PI9pP#XKIF zu;l>^{!j!4rxo4ZQ_MT*X@eI_ytPkSK^C-FN5>pvu)AiQJh;B5W9T2P&Va&p)gP*P zNozbg-q?ymWpZMi_2bmcjH-Q|%EYbiiWk&qI?sDM1$$Tl`&~wZQ0iruN!3n#ppzc{ z_|}Q!yq(SV)WxQIJmUmbuI0O15nf$FV<)iKXuL9~J|e}ApT9%LkuTbgZ9X%|RP=onf$k++%HNU*PFPsy2?y^_NBUo02u%5zG5 z!OtWff~F5v=Rn^CmKJ&3&W+}|P5<8lHCq5S!FUj-1M=ROej<7}*?MTIR)n-^9pko@iesXf zV>g5PIM@n}MlCZ4qY(z4&V(DCbfS$V(Ncfn%XXmgF_!0xMN( z=Bqr7Qf>BGS}xt|%4}Gcwk!i=k~{5yG18A)UoY^|V^osxJIl~ASag9s z<Guti0TMF|SPXErb!>|7 z^r_n-T3De&8vp2wq1YTG%&y67@`TB+M1NHX1gVUFjUA+st8dDI;aq^)PY@QsD4E-3 z5V#Vel3(VUJH*|r`^r{u4LkgKk<4Xf#Q&$@dAz`5w+V0Cc86u4W1xaN8g2QfuPSyY zPQs0&!f*kCRH@e68MJWoL9@2kt3G~{PwlIX)$Nvz{8mf4WOF28Z)J( z6OZ*!+S9-6qh(NT?(sREzh~XC9z5F=xs`BKv}E~}J}dPAk5HTgbe&6FKXZv-OL$Ra zJlb<3;^@AQymr9Dh(4hUth2oCERsAAhIca;iGEi!OPA0_9Oh}H%U`|r8(UeeBz?Mp zngaNA=aF;X@84MbJ{!DQD!FTcwgx7TS4Gb9NzEyiwWt76k#yg z8>rP!AD+G$JF>A~9(>gm_qaxB*%m-L>#3fB6B!VH^|n6glo10$m)UM>2fe*{(B0_b zLd4Ll5qDozXmh1~1U^M17B_N-&n~)t7CW-vHlEhI)YI>_>RC_PanmYW^p}oV9XM&{ zB|gQ>5;byT0$mypi{kA^D~Vc9^VYqe#?>knb`9+(W9kS7#=P?i*SLHg03n(?LfPRB{p*uBY>HbW#W0;RC+t%S|Nw+`ND6#=b}A zDyeUDd1*4@YPIjl&Q05uo2HtA~W_<@#gRNip@UWdm89=zFW0LMnh znMY6kHt|CkWFpJ`U9FS@dhYvcp`Csz%jCtVV%+~HU7CV)d z_%fIaF7Oxz-Xy&3Idq(MT>q&HpruMX%I~=qx<-^011Z7icX=zF6vEU7GAIU1#TWOc~|G}8( zMF+>ENVtIW@eIK^KyXLpZ=Cphp+IXxjB#0?NU6)ek=^F>3HBw@BiCV0eC)h#N(q(A z7Ula(r4ROF9rzB6*##LbGDHNyYmcYX9l>RhS!jA3_QdRvjOh*$QBmv7D^J$LN12}I z(%|53xt#b6gqgRmV|K7i5vl8{-{k$#_2GO#ICE3KQZ6%D)co}qdU)ooN^Zq4rpl#8 zgTB=9h#U8*eGH~7*-!6+Lqgs}N@UP~90=@})?uD|OG`^~lwMK-kcRAd1ABW+Aa@SL zSZpYSW)<$aUJB^PA<*dJvp%%w{5bTF_;l468*p;dGUIUg=M6@+n+0n`diZcaCI?Nt z_~hd$Busf=-P?am%ldqX9y8=a{Dt2N#90%ImRX)r4xe$zI$SbV>&7+jOiWG1Po|P% zAn+W9j_!1CZesT$cXTBe(8g<54B_2lPBr4S>L)cW!;H(sq)sqaN6s_lcsiz z_c4yeXY_A$@h@1YQo8wkjmm?6@H4E`bL<)3jruUUD_96sw1RG0$EsaBX8Bpa)DPC| zgHh^RU@^tSLeE80+ACv{U;sPcYxg6I+aWlgvm|IT!?NhV7H%0V*?;RBQNjj+U&D zt+eK9fA{2F^d;{x)0XFu=jV{L<`-;}#~*t{WpA1j|A`WBc2 z?FSy-geUz&?*EvK-EW?{t;`O7a1%%-NF8cSJDB=&Cte#8K|3UK@-SpvmsuxIm+1Ox zlUPq}b1Q#s-$D@nJ0Xh}NC^jl+;A)2X4YzL6cLR=^>Qif=XkAuR7=LU@o$cxm~Y1& zN3&EomI!hbZVu>QN}?LT)@EE>+(;zwUIK2F>F^?QG2nBYr63E)q|ngN)V@x9huyxE zUa&$}1k2=`uo5rC17fIO{ZMAg)RpW6OSBjGPg=0RpW9iVr&)DYv13eQHzv9QfW<~N zwW{8113TvW^Z^irokuWi+M9w}ucsOXZ*QN7Ra9t3$3`v^l*bgiQGWR;)+;a{LuDUr z3u>}8JKh~zoq}FTL=53p%h+jxPVQJ7Dc~FZXVTBiN#cAN&dCHRsdhy=`NP6H!~jSH z+2s+emu)BYc89AAr#CN1v}D4emrZFbHfNuT(w;Uq^BpXKY88Ana9bX#4`FF5lPu%N zJ!YgKPx?Q=!P0!swi1}_KUrt)PCSf#d^X2v4#Z$=eHRt#M+pOc&qYIcpBbu**_ZW5 zAr?>JxHil~Wc|nv$LxTpvk!?CDs}*gKfly4^GQ3`P<23LjzlI!78PyDr4WL%NoRU zFaRLL#-RE^v1n_L2oY&(l|yN>{GchXq7rUmb5%+HCqpR&ctDN+3M#~g ziv8D&6WGet{9ural5+9%BnD$G5co!!r8Uc_M=_O@XuM0?Dvdcf>>B@?<=eP%a@N~< zz~Zyy^u2doZjdoUjtU?(6H4GF1ncv(aaViPIC&AsMat$fnL`%GVZqJR;$fWbaZc_{ zZwrfkht4$Ot5_zkFvU)K?yG=1fsLw)eM9^(U7wRiKy7^|Z)$cTz;KhpH<@;A+3QGN zynH5gFxPJ^VxQHjKcHzB1@75-*Ir7x^_=u zQ1S28jHb=n(}_>JgQeoQ4jK$~-qhse1_8#ajqV!AdswdNt9QTJPd#b$TX8IKI*vh| zHAnQKxs9iPbRWmwg^=h$o-%uqc`%fI^Co4JEab6?mP z?8zQNeyjb%ajJQjBGb$Iok2cB>Z0K|v&ZxxHQEpF9|q4YWiQ!Ebm)c9_v7U)46*Ej z0$A_>Z)|L2Dn~be&>Z;;NHwsrq0RIL1ej9Cy^CNclhI^hm?dMCQypU9UtwsuB(N%BoIsX!$%{LHL501|k4Ibn1;2HzzS5aUW2^GjppYCnwu# z`O_d%?kU{)4#jwh5b87B-`{5+xCaII4O>e?%wzc1jTU7>eC2!OsvdP%lE@(#=E0-r z$yQQQisDvbnrRXkrcz=6pMj2iWRsazdEQl}kb7~N{zni3Hq& z99-NH%Z{XlL~S(7lXj)i7LH9!_^UC(0f(E|*f&KXF%PNINj4B;jwC~scL=yXkEN$d zXj`=}0na4pl$>lRb6vUv@lqkqhzQ6)Lp|p~{Boz8)m`Bw`3CK^0E;4YE`&sPnaHjA zPcx)*{78eef2lkF_p>A{G!(H2)09~x++k!MW!dw1R`2~vwDL`X>BDJOcB#pLdh6&Y z!Nvr@16+K7EDxuc^5#0yAM)L&5)*yKZf#2KOy(c`o?NVHqn|`mF`!0;Uj!=J?#-h& z^vlye`9p9!P^%n!x39R_Zq{K&0wo3tD(Y*ni?eti?Vc7Q#1eY23>D{~)PNVq#6~}= z#(qIWiBpM{1pD$4#Uz(?Yv`lTz|`Q!B+CVguTP2$>)v&xk?cRt;?11qg}*EAE1ODq zj7sXSY5bDGY@PLiYj&p1DHX}JY3(L%4tlf~j{Lx!76N=jw& zz`QK)torQR{1W~JW2zf5(>9b{k{B%ETsOmk3fSYPZfKs^K|`KOp2T}_JoWXlA@nX_ zREwq@YEmPU8+l+;aefyw$2LBo1p7!J__UAAL~gFdlQd-66ZY|lM2+K_u$TEIx?wZd zVl=Gqn`%c8hJR*e<|MsCIUFWor1`WYyR>LO*Y>27exkXHOM*gcrdT9betKk=#zeBU zbJ3S^vs%%A`EmwK~3@ON#A; z*jBi{>?D0E`wXA(9xiid%2X-%by#`@!r6Fd0ie=X`hiWtP{}QZQCyAbuJHqvzSh(+ z{0=b~--7jB`IJM%D8T=h6n?jW*T{gNHe zz@|jXbW>3d!g?(`+P9~E7u)(epYc!lZ7Arfw7h61)rp6GHdLhX?a)mc{Xhl#X!wg4 zj1oSlv>3*3IA$Vgbf1Nw9L5f05zu;h6!XM+?gsM|qFRxBKGRC9-0bXXH*Tl=t*wdEW7<*b85UO9Jco_=JS^ zq;>YH^ciye@AxJ;Okg#PUUOEMn3!$>xZy8+8z9V6ej$)CgHWwl23iU@VpK^^i0l&j zrUgwFPEM8D*s_}CB&<3ufdS>Pg(WT!c>q=nz!Ek#5^qAFy=AN!%Db6wxz9WdLva?I z4NmVnKqp(nY99q!aWpK7C)G_#xx&#$XJ}C|1Q=hkR$CYW9?jq*)VmTPtAMF@F=8r~re5o@y3QEkhpAM2bc6&4a)b8Kpff=%4;TN@qFsvCI zgzOO`1v55{DN3$@xu1zoDmgeC<*MxD4etUcR@hxA*NUpIamb!U=$Fic_yOy8TQoJk zpwlHr?{%yHZE@0Aq;xXTi*C)ZCd?7>S8F+BEuI~GBBB5cDBz!->Y%{3#8rF#J4fMX z#j_D}lvR_VWjuxH2Uwl(VrlBKk;2zGvZDF8DYcY(K2;xt8UzFcs5LphqbmRvm9z40 zn0w_Ae{Pr>4j%sOv>V+6E-po(^~(33OmYpNgY;O`5)dsDKX8MJSgoE}c3R9Ohp%w< zMDo<2Z^cb1v@akGyieXm*u$%u;nF_IGAj4p-zSxccqI3;H*bJE>1>a0a@?B5Z&`R{*lJFS0NJ{Tb9GP!@Z`|)~?0z~i zO+^(TI5LX$J(99mo2kIbMXoEhclaNNXKdIrxTq*( z!Vyz`U)O~12$RjS*?;)X-w1tAI2fPjJ*gpD$mHz(R#6Leb&thq&uH%-(YN7%rn87L zsFkt{KvUWmzPK3ZKR92t{J!dX;mm3|$PODSV#8X@ly%0*3xz&C+!&s%_eAx9_SFHx zPb=0e^|jU0ANWB7YF@)h+k>%}H@K5s{;qAfO+z~T#baUcH1q?0d9v&paG0MJ|{`&{so2_@(F??i*{?wnT zBewv(>8Rc3-!S^lIVSr9SE$lYz$Bh|epbqb)vu`@M;rBqvp&m+B`_O9iEsJzj z8k*j{rRLktbGdRmY4B*tdGpjCOSOA+l=1t$m6=(Ja~ep8flQ{BimiJx2{U(^{AMi@ zH?$?NBy55?!LL_{5>ZmpaJwFU_INSMZ+>R}H`sF(VimjqevvN7Ni)tZKuQsRh>Q4_Zpg- zXOTfm-{G#p24wz8{VXwWEQ1S>a|$OKYiK5HCi(p>xo{66sTCfMrJ}}g>&G2wjItFg zEdh?pVE<77B@u>Dy$wD%+_kFQW8?n4)9sh$Qq$0t@&$UqbW9V(z{NgRUfxh(UeTQ9 zfD7CGp`(bm@=L4fLW^^EvZ5sZra$&s35-iD>1yN!IKqv;FL_gG;Szs z@OVyKGQI$kgAoLy8x(T&Lk>MF^}nxTy3YiE5-Yp?)z(QC_zH5AW2Zj-opNtgl}YN0 z=T3ikYs*eyEdp92qUuB&N5wK4kwo4FW%{l7e~`&DD6&u>;$T%jgz%f*X5>GBOT97z z(M2qG3K@P<@>%CwlRfCVu5Qi}B7I!>`#@I=Zk zeP&;d)5j0qI(hS*vgXnLyC-4Q-Ow6?h2I<0eKdqvt_yqEm5GUU0`5hePnf@^&N1ww zZS2!$mBV8CRU6t=5AfeR1z5k8;OiLVh{>h9eL^qu6Z>RFcH_M@$H=2z%7$$%vgX{9Fl9gmp~oE6 z(^?YCyX@Za@j6cdyXTGDFf}##-CUng@N1}b$NAQfMKyK2B8Vo?Gd1mhlhR0L%8Ste z4~tla`(7s^+H;fYc7D`*=CrC@{WsjKjz@V2W#XZn8(hPGSFwr`&^f!mbics7f%sAzW(D4{ye9;>0B{dgmdw9N8oJPYp(?dS*UqAR$)EA6whoihl?THy9SP*v-&w6sLY`LzWb zH(->05pUSE@NQX~t%uLa&k1SG7GDNK;C>r} zBWQgac{|7InevaSjmSyR?D}IHDN6etF~@Ys?J*hEUe(unF;W`77B`rLMu8j&xPX3qj)<`dW%V|y&VJ-4_gg7Q%W{dIKM)g{|5a<&l%f2v zZp8c(U(X%8Lh<4uY60URpDzM&=}bc`S~E;OeasR!A>bAg+jA`5gakqCowR> zY&~yNQgu&+qK=xQAR!X#?pRp4{9~bdoGkFj$7iCVh^(Otu=7gacPcZ7`{s%bnB*Ma zyKEMsQC3Ri;Hx7{!?Qqtu*E9I zK93s_VON^61|wvp5!X$ijMp$s{%ae*4Rl*kh-oDya`jsx23{O_XMxWaQ-dR!dqw%vTTWj5(ImpV~nuEmZ0RkNkvdhtjGp!-DC!y>%^q zaA^DPNijRtz&O7s(foGEu0kMVOK23>v)~~ATU&9$^c7K~a=q-QPIT<6avc|gzXc)J zHBQ4fg=eZ|z>3nT*WL``*4iY6h`AnwC)}p9FtexBEIGD6R&5SyH9-yPh(ibnk}t;P z&{Pld47ZfXI{qF%>0kWy;4u=W1a=P|H5glta`?2ne%K@?Wrt zSGWU%ydpW_6!76B!QK z$vrb=A?}9Jr&fgs1-u3+N95I-LG2*|zZCZdsU0nszTNXsc@>qN+H*2Fp=7pU%+L=p z!^TCm$w{c?iwubBa_PW?s*M&mJcBjOZ4ddE{njS|U>V&2z$FGaygggSz>ZidNfw*s zmaq-G7yh^bo?O;DxB71l4{HFNXt)^RKO540#_WqGtJKTON83AH>wX0^K&QA?_Q`1f z6WaG_Mb9miF-KC~>ffag_4d%5h=ZwhFT<{tA9;v_K|KsEz_lR%x>M9$G3Cy+HOG-K zvK}Nu%N$Bea>0>eUVP(bMn~IcRy-89(cf`OeT}NI(LWxG$Y>eveo1FPelYW|-%j=u zx{>=&4|R*~iqrFdoKRZ%CJ|GxDy7~(48ICxg~%(}-JW8|Q9Cr01m)y8g_>9=@AE4C+;lN=-~G4@G4<{X(YjK>3Y|Nii&Vb4YQFsk&RaxeO}zdW?N#Q5Af{ir-z zYQ{U5t-NW`jobn=v5I=G{g=wA>P6>;S2eqw4F-hkD}BiAbHSZCdNNm)XOPv}+S;)B zW(z{}yssAS z8NB|ij}O;N%g)2W0o%K>gj{DfF2!lSZ`n6C76VT%WmlS>Z!+n{3wAj%LwS%qxm7fT z=DEdM8yTF8v8oU3+=65{XK1jI)@o;Ux?)o}Njn0w1sLE4fDo zL`lS9cfiY`V(z-6v_cGQ=4;xtZn=5s=|Mn4LywRHPSNw*OhDnGAdTPWMm%wL(7b{X zEC$rev(JgFqcqKIB(?)v=cj2{rw2=D3O{esKYjVtOi*UIOh=$BhTua480j)=UPIgb zR;cE0;5HgXQRFlX_ZGw}4USqE!0LcqPYGRxTJ5T~kBxluRD$rBR<`{-O6j=pU0z~R zJy?jC)cNxHtBQI#P{%Te3{6cbci(jt7Z;m-&QL0j-;u8t>@gVM!=&e=sr5#do%~<) z5G{27Q~WA%G73-2*6(-LUdNz}&)0!{kb)LM=H0M=QU~7L!xnhj#6!+Wswj@P+`gPen8wM*Dap33uvT zV9|`Oes0dI!u|#DG{6L{0s)`kyayu)n4D{6pfZ8H1R8d_X5E3_`^4gb^-LmI3nlxjy_<|8B5i`1T zP<=BYQ<2^ni%i2CTrjy;a(r;i5zn|9BVilC`nZ3Eb-TwP2?41!IUDpcHob>GDlHiH zzw9E@IQaOcz`O9Dzs|D@n21|U7Z;?n6|EC*w%Y>c(jr&GV3A`GJxMdxbU<14XAM3P z_JT-yf6x(D@jXvCK4O$?0q6TALA8mAzi>0Uwv;obM~*)Z65AAcD|&w$Ybim`I)-i>Rwg_V<$5 z00_~VE2)UX z@MV9+FvPEu(=WuE8Mj9|ODU%oO!4@Ja_>oRT-7jdp7ropt6X1 z*^=u_cR1wtB#v&$_;Zd+axmJApEFiF@(`CIfQBOXis9igAC)|o7l%Q3*<9=Mmzpps zQLyLm6D{dn=kP2gBSXXw7@7Omq*U`LN@)qHXZbwe{eQrAA-|t`EL#{AnY}7W;A1-x zz(Sf|Vr>yHo-C_Upi|ye$@l$5eA@J&A{|^fAO4eI*mtLq4t?HvQ|16?Dd8u50Rn+^ zO)XN9j&&fVVHR_2G2r*^V(BanXMI4gsd6U6y0B z@5SZe+n7p$o8c&SLqlf=e`Ad!S4Pk%jHwyN;yViUX)1^EtkM#_5Aa zHIrgJMX8^8YoUUFg)2g_%o}f6(Z7-;EMHLR;%_v7Lvn+WG(+M@GjSlqg=QCyuRLL+ zG&wa9+o$Ughhs?otsRQaubg@tq~SprJf4Rzbtfd5su6O&XzHGabsoW=fY|IbW zM;?8ZT*lS+&XsZ_aHb%jP%ccWFnm*%DbSV_$&C^Ck5;Mu?Vga4ks-%M5}oAeW0X67 zjhZ`CR`WX0TXp06{z_Edzia&S$9u#%V@MIgJkEro3fM#sJyX-UbH*5xPFe9y&qKC&uw zZO#WDT_67NH024wJkI#{lz%KPKXauLJEebTOUwasT_Er2 zbD_9%Qs#j$x;+}4;5TX{?oQJJ+-t%#3L zdt9IM%fN{YAe?S^mGiaTnd&pr)6?r}(jB5e@`Q@u%EL+f%3WK^^T_eW&#NT4qEh$W z_^%9LCK&!Hm^s=jl>4Rkque2kNOrPVzlq9`G8Wv>VA1(aet(@tS#pxEnHtolDaU?1 zTk``;qhC02G$ADXL~)YhK1)5w6Xng+Fym2gRj)Mo#FfB-0v+8}gI5#*!MuN9<)6q7 zt7SfJ!yY-Q4x3c3ZWI5p7>~{8-O$7~-{A1_X7^qNGn6k_+Uvy!z3OyY!~dSi8Z+}; zKM{k(G7-};{0lxOsR~AcP)Vv3nHftS0zfh|q-imms2k3@L68BJ2``xp;Fp1&Vod`2 zIbZ*QbA_R%?h5~g^vKDd;Bx*9pX)0t{!(4x1}|i1*^B29fz&fJ2xir+tVSQ_#c3|+ zKKU*>qnPh-7K9@MUB2h^Y3D!o?TvxkpKCH97&{@@x>@v+Q3hn*DD9!}?4Slfiy=s{ z2E>|p!(y-#*BKf0OEEaQlgAKRlZaB1njobH(u{) ztsR+1xyn>WhcA0}|4AjB&LDiWy|YA{_uEIsMQtVU%Y$nt-hQ*WX*9iJQy5^sGLz9! zVYOR%_FQ4*C6!St$rd!c(7ICR*O$orc^GVbpGY{HLa{CMYJjW03XC|1or zaZ-{h`+*z-q5vDc%@xDvtixi?&DOH_BFfJGeX#elEOqpei%7hY-(b4~qXSZ$5*BJg z3VSaLhd|iT!$k55VQi)rbVk|6oekd5P%;Bqjpox`h$+g5$7v56|Gp_ZobTZ zTr<77Ne!ky;4iczQ1F&a@5W->bgB_<3oUsP@{f6OyGB)GC3?dP+U1frH`lPQ;Jnj| z>gCnd+B0U6Z{)$l*zD}iFOny8jfKVfQm$#+ml^)C*?Q6icnCeb`}-NgzQn8DgM)77 zwDI|B=*%bUjF~=5dtdmgYGN-lkhv;Gu643S)$~H}2izV?wtn zs;#A3^Djh=5e{44S#*2|MvWR%xgMh*Rw=TQyBZ+yoq_a^xe)zvNiwkc0bnS?r!9|H z3cR@j2IXAPOix)(bH6Dnl89SXunt&RaQ_igW&i=@kH90JSito(;%Q`S)*2X#-A-3} z2LX_~6KNPnsiE8lk85Qm`oUUKMZ9$%rW*~#axU!o*&FCiD2aY~nF!yzEJrrGSi_z3 zkGC)XGhT{v;&gF(n0XjmX~)v!vWEVJ_VmPGwRW5_vjbsyeA2f>RAzW^vSR6D4nMPG z$9?Z&S*0H7l+f2^2;s8S4$Xh85ptxmn|s@9wcGB4e0*}^BIL1BD74t>MeA(cj_#%D z3<1$r_YKe4t*sg9`$8MmnM8%A4Vm*bH~f-|m=vmX-gZhlOqb{LZE z!;3pG|BR6y1?!^bGR&|a3H@#)&RlZ97qfl5<}4kbUY==z9L2RYv*3TgTUa`BVD<~o zzux}T|Bm+2T*7*~Bms!Wb}0UWu3scZ2ISXYS^}dw5d=F@Jr@%rL}&00;I*9wg`Ifp z=7gLM+jwIc8XA%w97=SCdyp5;#GEFlUT2eg)E#9{^{lM^(19GXtn+vIqyDO*JSzk zvI;HD!hrJb$nDRQukbSGlNoAL#o!VVqr}e_?_0>l@vjf}WeW{$Rm%T5AZBiI2u@!sKGqWAmP)*rf!$dwR(4AI2;FfW zg?zRm^vv%09QGn`@6_VSGheQ$5CajkzQqAjns0*$Cd zZGsH%PuofvfH4lkTLX1rvGO3RCCDC?Lu4<&26Phm{9TB10Ac$|Gyux3>Ib*%Z)fV; zf?l`U{s`VI27r>pPhR+Vulkv2U}f!}MPP@K<%8mmQYuCwgu$DMA=-7Xg72}*H6v&Z|M501k`r!6gL05Ys2JOXlq0V zveVV$h1R{&W-gnoZF=sFGPLJ-J{4YvGnAnqRlYd!aR~RFT9140jK?V}EqmKx zQ@3Z)K8*WIF`$(LSaPSf%Tf?LnI{In%W?Wy5&#B^d`4tQgI~4jw-4q+Ib zAU@bKN6&V&+)OvLx36Yi1&`w^&&y!7A5@c9dA&Lae<{nv1nF_W(WjeiWZvy*KI)-XY?Vf89b^Z(ON*b3IdPWfOV4)+ zs?46aiUSp=IG}^dQ9ua90KDsNlMvHydf4V^dev_Z1Cy)^ae^U6Cg!|cTlS4+AKN2X zTORKkAK_C-R38o#-$HJOkB4TzMg^{w2X{UJKHe=8Hm-*fjCl(R@XBF&wZsV|Ir7nOfXIPXnwxiAK z!S?o4AKaS0{BmN)*Hi_d!utr^Dub@`1QuxqCW9&tKrk;03bfA|p3nFg?9(Q#aOf)+ z4xZF?jX<#+vq@#3iOaD@q`8--l`r>|P6YUFXbfK~ z9FtMhVNYL`rz74#eRl?kDcoTF*DH2=Rq3O>rafuuc~z==b<4}rOOKxtk_o@#|yfY?FI~z){u_iQ<>(I3+xSv~npO5&+r*a2QmlU?nF;)amCeNJ3yBA`vDQ zx8~9vKw=OgFnbY0Am(>2d&@rwl#2};BX5D?1YnIHM>9bE_xra+t`t6Qzo2Z98Vr;^ zuR2`NpxCtCy#;x>^Ceji;Pg23h1jFGD7Wzf%Qt6dcBZMp3Uq;B%XfKM2i&AZAcJO? z>y&mg16P+lPF_tRPk|nUJL}q*BMwSyP5FM8gbs-RaQQ~b`mAXA}mZZkbjrr;F7@@In> z-89Jl4bML~$2g86cyYM>hBzF-hDkn2u&>hYmdEoU*Rvix3x8kt4mtVqOsP_mP&0DHZf{<`6h%-rG9c9B8wq?2{`*F<0%5>o_7TL~&1z3+x}4VIdm zG7l7@c`c|VBqi-`mRzzXLl}e`EV#17N*YBhdK;5b4hP)dVwG#zk_yIZKKpQy_2M}VS)`FPE3wh`aLi97m`51O zgpLMrm(gI61WU{{U(m|mW}JX%1BRFxl7Nm?=S3^S*egxa8lmRp>gkz)(h0f)!E8*_{yRf zV?Jv&!j7U!?a1pHTy#_3$>T%W-YstI8i=3!;sB#2Htxv?cU(#LRcQi7&gsf=5dce9 zKTuv=p_pU>NDnPA%_=@>W=ef}U7N7+zDT>>5PseWj^CNClYScqES3NZI?@;q-Kdd6 zhXmL*4%u!=q4PH&#Q=16kDp~@F94OQ4-Wh3%dg2+VLRaX1x>KSjDf*hyPHBC2s;#% zLWnuF1XeT&`0tXTGyESN9DWW0b1xjQOy|Luu*hPxH*$v!8(VNo~d5(HT!$odfM+ zyU0o+_I-V2U*b_fgNGrWFORc;tMIS0>+RjC2nS3>_KE&{pT{ZkWqkV8L1x%++z}W0 zyOO(7slt!5PDO`q%o`_l?Ll?l(RJ^}+~jaZ9e2p_V#E+4Xq9+aIl^Sxe5)ctt7`lZ zw!LKACHi!KU07(=a9q zF-!)vz+FXYZrf~$1F1K3Od-Po12)nv2pN}*h>jlJZ}NIw0I;!n52%#qzL#4v2j}R= z{jcq*fL&-FyK5X^@E^#f%BUS0SXjs|dY!rICQ4JCe2?xp@3axL+SFaezD)M*Gv){kpf)1<4rTt+^UHkWm*NMmNZ{dgE4!w2xbvC_6H#Y`5 zUb+@hXv40fa0S3|2cpnSRoj)YFci<3%=eSB=i%Tq0?ea=%Jf-)U5Ht#95R*|0#Z;{ z&B*WHp*R=onXFFZo@9Ez1%mZ`S)-nyC96(0se6B;Y_wVL#;^WJjzWOn?!zhD)AFqg z`T`Wne+tz%Rho^X+wHKwUJnQ8e$`J#@wquAy&RTb4Zyqc=bHTJfUIS-@*hc885UL7 zwTGd*hHjAVl9U)J>F!1v>F(~32k8b$>F%LXIz<8LZX_kY!~0#AKm0Q~v(G+zuXV3G za(QvB;}`&66~N;v4^<@#x!nYKngAV$fSCYQeb=u4OVfta%Z=0P8T_sDB)#W~9^2am zI2TJk0$qF9E)eFvC9+;q$pWKvT?5{xpnvH>sJ-%-tFB}0x^2#83prPcZjG@;)WGEa zr-%P~2(mK}*_w}kj;v+@|LgtE z8xCJc5<&E?(SdH3D2BXs;R99D@#ijt^ z1#`liz=atl?4Dk+koBglwA5;6mx=KLp!?*!j%ENuo=V3{ppqlsaQ+47{om+gS0{xOP`B@u}sNi6%+WZsa6s_KuiyM^(>w{5fdJ0_x-v&Vbhv5?lO{>$LmU7}N`N zEjc$QW$3?@8Sft+T!5jU+3yBRLFaXeOJ-o6H7WUhI8?oswr_ZF@J-;&qk#=R2CMI+ z8@b(|P~%Ktms`vf^afrUiqBiXwBtY#Nj5RRpDYTAI|HsX^m3+H&2V~jy48U|A0KrD zqB6&KZjL2A2P(|cO12}!#Tw7SwM#-g$M!NthSdb)h1zJYd)1gkq}9Pt^>^=A{U0wz zruG{=-v-1gGmeHR&?c9gQUaz6OeF+_*MR0E(oAz-&Q9-8ApD-hZHeIZ+KEevo#n$c zx$7qarjfZ@$pu>g!x^fefFAhJ8bk&xmRrtg8e&6^P^O|VXgC)sWqH>X=mK&Y><<>G z1JGXWc7k4RgOEXw|MFkj%Q7wbrTyFU6S8TFz7(l4t;3#LUp)0;#ekp@n1;l>>IIkH zVkHa~Cy6cjFJ;ff>xG*UC*qdjfK|G$g!6=GoR6}Y(ylqeZL=uD6lf3{epi*nsyA>p zeqvR1is#3Gub4-`A{U7mpwr74wP(UZ?3RS5xWJh-S&2}cPWo)m@t=hockbZKC$Iht zVyTg+p3oLnNBdaYAbjF^x`izJC7^U}raK8=djv zBMw>w`FWZmgCvSe_(*J#pwf?U9A)?)5$Ht14^w-WubrujKCF*_(NF`f&FYoX3j<;g zoJT0U)`3xytyl#h>TAz>qe%b&KtR~pM~vDx@VXFUS)FBCM$9)OtiKnl{0q}33Ctj_ z(Id(#|E&`OGF1i_yEidUBeKrkc&ZRg6nf{KP*J=YE^Q72!<2WP!5L6EM{rIUS|h4{ zR{U7Inc=7&kY#1QMog};u}2vIi>3?>9nvkfK9qD2U-_@DtieBl$b!$ z2pM3xCC89LVEH?E=hG``r|bFt2oy}_)P)NKV3fcYRQmkX^kdq(5G*Y%HO*oGESP{^ zZLbT31~`I%BPnsYwCUA!$ zMKW+@jG8HirB$R;)+hlrW^cvG)#78ygg*+HF`XId4gRa2c08N{^J8?g@O;G4n(a7%40&XbsAEQp<6tG};__hZPe&y+ZKoMyKSB`S2Tfz{#%!-94W=8sbjhvf9sf|=2BC0w5M3|E;nDnM=Nj<7TIM4K-OLWte)eob62&DUfFtc-Dzn#a25%yMY>vj9`yBpnxEjm*u(6T|44-%Cp+o1PV6vgo{(rHm18d67Jp21J->f&TMQ;Lm_c zTC?eE5$hXRUpDW10b&1ShA8SyqNzL2p_7AyFyH%IC{@=Q+OQ3}8i?&0&? zGygIl*;HvDi5(EgTU#?mMn+EVd!4Mos6gicu)xO_Kv z1_T9r>p#wfMt*t_+5@;`-k;7SyPWypX$60BD6apvLt&%DCQg?SkbQBQoR?T>PGeQe1t|=LFJf(u_gX@mJKnrS+|(0 z(6XS|Q8U05AIV4ZpT|bdRtPesAR~b$jQIlgy!g_;JCW`3cz0nNF$Y9-0j?>p#4c4P zK1KrF*I&xE>y8I^{)1Un8j%Je$4%uT;+PCDj!?!-SWkXe_L*NWZA7ce9(`lBnKg?v z?R8xoPROs(_Au0$pID_x8johztNo_DI+V(&`=m2#a2h^G=|z0b(pGx%!}f zmGikkiGUU=s&)rdcM+pO;(_UX;zaB+XLrGfEbF>obY%Mqe5yhooYb2a?+L6T|2^5`dY@p?DHK?c8V{HjkR z7Z^bjnE$a`s}Fh!EUy%1Ol1RLQ9%CyD2)MlhM<6nGHJ?&3mELol`0B5JRFCFgv3@> z$|UK?u){g3s9-yGp1cK|$N)}nEpUXsl5v{}_sCVm{(YsZdzTATNy;Xr04@wnR1A|h zYJ>iw;n7e%k1=vc8rY*h*CrWLx%+iEDCyN#Z#(EDX*{31af9*t^IS-A@aRpuo z24^7+qB6LjkvO4a9Gw_@`9VE%>(eK+%zX)4ctUR@sUFvn2_D)30N3TWWqRMQO#`x8lI$g8q6H$y~3#03C(EjIcilw;Z+Q$|?2E#Ba`m_z~0dXvXZ zBIRr##5oEOPXRv&NVO3GIdcF9)#iMK#spa#a8Ku6sL<$k7a-0AW5H^KrcN4GBZ4_Y zWp8^zd;Xz5ng~?c8&|z<5)tN7UX|i6z?4gJ@fr>JhwC{2C2$c}Wkq)U9c2YPGzuyY zg~pKGCcg!G0rQYD@h4kr`s+B8N3av@>Bctm7vSqrhPzYvK5F-vyrZK7(5(XDc*|Wr zz;euyJZK^Y-4$L+qE-+S;hBkRkH>9wS#4@SY#*uac)GLgTs;z zmw)0f)|bOTs|Zv949=O^sP_WwRruDR>`Tta|0u{E3kP>ql$ z<*EL+Nr1Aj6QivQ-<%_dV8^iq2&vFI?%=niT%Ez2B-jC z&&qciS_H6LKUkE&nm<0kcKg<$^!gtIzrl#76_%}1Lx_{X>S^)zfhOF0G-@Ys^+UWu zv+J*pxX?1oFUJ1S?8%;qAd_Ocha*^Rr}Xo5Xz zf)$*c&P1MDyMd>8@fy_qS~dcw_-XrI-tOEA@M%B|5+Y~;)Zx-w>IuvlsLmB5eB){K z2PY@j#{#*^uwr6NsNBL9Fm4|PqT5yM*MJt}Rf7d6Ot$%&AW-V;33EWMG?GZ+){-k8 zBnFg@Ao&X96-+Fw&AW@OJAgVMQ1-P0sGncg7l8wIQFwH3>*0`x&bXrA+e-ly07F2q z-@imS_BcZJtecFZp;uG{Kpb(PqMN%w-}5RxMaClU4S`1%&DU#lrU}PMWOW9z5Vn%U zS0PJ)G~@N(UKQ!xao=*6P0 zC`&w=O$6}}J52S+Fp~0xS$OSbCTp2-&6~2mCr;w}5bOd7pa}^2`QYRwtqO!J+WG$L zG?Az}qqUhCBq8z6`+ezV*nLB|C&mohi?9v-7J%&uF2;6?GLO zJOeB41aYqDW>wp>RBMmPAZfW!Y;X;0K-LQ!=E4AGKl0`L8%ka`d8m)>wVt`@a$CKn zOE>)<&QQ=`;LyENxEoyf-u(wv4KNS%*SgfH2FMUhMMI8b@dSGyjj2rk9-xv@ih5`_ zs*5Vx#YoTSV(o|Ai-Vm}zgmlJOiKgvxHAl9X(ZcD&_w!OTpXPXvzeqC+`MDDN_#uy zLFRL+v)^WCv2fC^Hn_dqiDTlYM=)(Jp~VI#%(*QQ5HdW){Vpaw=*7yp5d>xW`E*M~ zBN%j%lXqnL7X?yT`0j1(ZXIhX1#j4`{^+_GXIG{|ECdLQMu})BsqmIS)nQU z^ESkvoq}r){C?^YFV68{zUe{udLLH&Fr1_!!qL<0hG1W_e~uvsmgxD6geZCO3#3aE zCb0)SGS((gl}29hkN`zo&>(d9kr&XPjU<$diKK*#okOxu%74n&1zD zVu5O4{JgWxW-kVo9)mA8^rJNd@*;#c{Pot(D8t8J^3V%i(rw9zaB@TzrJb=j+B}q` z4KD>?wFNoajimK@ukG%0=>%?3f?XjJ(wGe+rWNDriLe!+cqMi>dY zXWCtR>>Cago;-Z1$q92#Or#Y5udKB9(x=XWv??QtEAHH0vb++B+exfHPN$Gd49&z( zz&{4dW=0SagdC8G+4 zp{>4VtMcUx=0J41XcxdqL^-`hURDn7C9gBhZ&XBg!RkXG-pV^-UpbD2H(d`#baWbM zuj3ac&oKy!=RSfVw!)!$N&I(vn=)bq=B5W}bR@0_QF>>7Me2>~5+|EXo6k6I?<+tE zaC^pSfMVGR>LcdZ*tA~-5C^!(E=+WA=VbPZdajm~{Ln=i zTr}h<+Z#oEPrITPCjCZRU!fEQsL{OKAaqmWu|E}R8i|GbBm)9PFYm*2=Q=6FlEkCW z5s#9^dC-E&f=Offy`keBvP$@&?azvh?i9?@506ZVCsV=qPpYA2Og+J=f7KyOmDn?? z;1o9Gl1BKgS}~*RZ%xsNA7fLPr!vS4r$cM9Ii+@|Ro!IlU+Y96n+p`K!;n;-B1vx| z%N_UV^e;@+4GIp52fR`!<(eV3#3e&*N59^ff}$GlS(Tc!f`{FMIJBiS5sh|CM;_Yk z)|I2}juXm%8MkTI{R~1QN>R(2R;WrKBL5(<*F8xejMCR zqwvhr^25yumGfcqss1pGNFq2B9J@rk+^={27Q262^}X9vTSn#wrViMlU#xiWolm;y z=0rN{DmuGi=!H&x#lL+_@h1hFPrJ?KwS>j&lAy>dXX9t5Dh6&U%L(AsU3R!GRffZGb{kwYa?-x;zgnIi~sQ zj+3_X1F8BecaEbnJrIWLd+G)b&c^6*Hl3t`rj7j!l7lz9+hd3B?!$%q%J-WVm9Ham z7Sk&H*5k%rpmLD=GNyzdmh>bdT-%8lD;|xQ9f*wn_DR_m+I^>gZjKA=bTIo&;$W77 zbwEwnmTaACpLBw_SWcl}W+-LC)V+wTi9eW~$QZHcOJwH{f4uG!R^Jd2S{U@rC zZ3Fn}PFLzmBx5$PCS2jXd0jM``gQ#$e~0NOG*=B7BOHn=X`FrI7`lE0p9ig`s;a>1 z@>AqC5a+Jsu0$13$#or(q#u?{76}jZkGZquK|ZIyD<773=IG6+)4;ibjm-(ZtzZ9; zKYx!8f@^-xPMwv?S+1(J7h&8PJb}bKF&>`4CiDHM)`LxNOelsUd7ZLi{U(RTz#+w7 zc3m3j`?FnBMmCQJepB7nNkV@uephDi%hkWElX2E19!7ALMoRg;HWiUtY5@-ACANaY z&m>pm_&g3t=7a!#DL@v)=P~PK&ey-FF%hbA#d5_;6Gy@gkE`3&+BHg_&faVCcxis} zH&wZY?IIHX=9572E<~xE{G`I%r&wN}X4`s6zXT`$nM!om=Usz2`(L^+tU=F7v)j1n ztLkh|mSNy$d_+z0)*&`+hXXrMiIAuGndDxym%8C+EOva9$)7Q2 zCl1(6Z|v#$v6v@07NG-1SVvSaQO}VNB~mLaIancsBIhX=<(IOLCjMsTIHvGa`V8lkq@-1bXY>JX} z;HFi^`J$irZSETCaOMy~NT?f@(qf&bF#c&@bfFjV&w-gbR9z+Tft13c6-y>)uj1I(6Frkxv)6x)Xg><8bFqU;@e| zbA%hSbUvJU2|J(Vk7mW)`PGZEjipAVcsP8RY+DU84jri{@<9lEnuq48Yx zRajSu=3OFi)hHtTHf}&D>01=-Tot&) zP3kE5=1Xr(h|&JxJ1Y4Ek5V@i?TS(dpzDZ7C;fnp8mu+Xs6$|dwk$hHKXe|evQgcF zyQ3w=gUmkE>}paq*zYVLLZkCy7>qYm$zg818`Aj;*&cS|)xeWn9l+Lg4ERkO?A6A* zR0wJ>!qk*R=yoV5wWF4y+HHfKmi@*_o@H+och%il**0q2KK-GV)qay2Y46YfsHD)K&q=-MaH37k1w@2F^3mc&$|S`Lm-F9%pn zYK7lO-Ic;h52ih+`~$@S-%@|EKb5oV;0P#EyIwN}6Xvr;ttjd{M{Zi*k(KnEtb>?H z4P6k9NdW3B@@@Zkhg5s1jvuXH>u5pqA$~D;=HPeUojvbP6n&8 zhI305nc8ZE|65BOasq^KO!a3q-1A2 zue@S~663!{q@#r+S=Dv*c6f`%9ZD!W)lWRm7CUsFzna6Oa5y{ZRP}#!W_(e68)i!V zvG%aUGhC1d-~Rn9PM@oA*at06qRo4871vx%Ggm=T%c;R@15`&|Rr=i6c?Xp5>Mk32 zEa)iayli;AZSE}2AxaAG2a*Laxh4yk(U{asc_cKLP&T+o!b&Rv@q-DQ#G<=G)Q0&G z3Oz>>5XEVi{30o8<(}v`P!dzvvWL#A1oEv_Z*~rPs%|M zh((z^YGyP;;u)zZGPgtU?FtyqC-Zs6Z88ajmtaQwVOBQ|2}Mr>gG#Y_A~pw!^*K9A zH{FUk#X`=DcFw&xGL|pp63yNBieIa&^HvWy5E7LiC<^u>-uqVwM@!n~8L#SJ&}oQO zqcktrJClzA`&4r5-yFK1hM%#N`%VYix|J(@sKKUx+7$ExS+X2#!4o%cFhy6ti&vif zD?ZWwxP%dCN|?V$c+2ElAdUP0DAxbeuCGpGJREbXb^MZXo#Vd= z4BK>$=}r5LvM{|zJrz0#%ld~V`r8!ZBEBiMg%*CkPh`=@Rh#t&Ixok+JcNUtoE6nB z#uojJQ?W2Ks}i`UxN=vluEBk8K2Cz=%l{Ik0u%M1x-?_incr5Hwd%LJJy)#MNBMc2 z)%jQ2DajdlogLmp6sd(H#Rl(&)$FUrfMJyqG++nxEm-qdy7d+8f2`?-Qf&-n?3v;!@2Ib;m_ir}8adKFAGH_qrsmypDcmU7DS=4`* z{9kIIZwqwF@;}NP(voN2E zL*YFA24Y_!tg){=MQJX{Bpb8DH3*nFMp88at>pMLrxvL}8ju9-ANBX^weJKY`eM0s z>xKOIi%|_pDaPNu{QW}O`5nhh$(f1wJ>Z6^_}jjvEk&fD00HvV`6q9BYKhzmzW5#? zYi|jPmgcR-Ou3^i*Qj)@p`gUzQd%cM=?!;1DRp@2Q>K=&MG-W3%;(cun(Op7F79&w z&VNJ+0`$9IL*5XZ?JV|tJY_iVbic7-3sIpF#CWCO1)G8|@o?`nDPp0LpQQA`G$ro& zP$qxPFM$$m@+Iw^AD8HHc8h3L_A4Clz(`wdXPNKsTGJCHTEGCtJFQs)t^*20i1O3@ zTC$LDU5_m>NS*-lADvD2c^0qyP0M@2wLN*Xpyf(LAwFf{$>6F^ z@;mU(B)?AO=C=4fyril$9&UQ&rXo!VUd_078@%Cq3605daC6IqVA?f~sJnX>-DR`0Gw(=H^F$$K90=}HeEeyNE^$1cUbBb< zS50JMKXbB0N97ncn|CVDsBGyWL4nxci?mefxTkr!${{ky>=%Shb^>DRPF>M?NkO*55A>co9*$WA z(1Rb{wf$?|IQr$nVf4QV`iKh-CaXvO3fa^%wW);{O_EEoJO?je+YtgLqg|HV9~m(b zikISbDYcm-7Bsmgt9A)BB{eo?<8S2^zq#Nxlfr8SV{E|D^;^bj7g{qTLmc_&{MMa0 z*Ku}w*mfjJs-PneVlLTLzKQRgwl@|ZQ+uW53M34vSQb0yNmx+q9Hi}FDu-Q;*!MpV zzRMTR_My?JI@WO-rb-RAq!N{wtiJu4a+V4rYi(wYCm|eCX3}IVbL@7?!lJfIqLNP^KAeF;k!JcvEuVU!Hns)_51Xsj zqNmk_xH&Z9{@{u~oRUsQQtk(&Wrgd>R8H@gcLb=LY!b7W(ax&njvq3KE(?4M@F1NA z3U9f{P=~p0{$fE!A|>4^D0F}@sB_e>NylMA{2}8K;u4T>LXHrao0$1GPDD(EJ~usy zg@W>|EnR~h94m6R`~kQ89$-&()RbTUC7bp=cql-CP8%#0GAV!B0OJ#P}6f0RV4%HcZ&CE%QSFq>n`AUz7f zf}zEqs@NRH+*UbhuPr=pn!JGQm0%ojR#Cbx_R-f-8*BmebtB2Qo+b9{gzEpy-__S3 zQ+&q595Rxz5AB`H|NiGe0_O`t>-tWtWyXrs3=w- zad)i2+V?22{ddG)oXLL|rcC1*nKB?-c$Q>$)vnOr&$@G`ha@XQolH#O)qha(#L1=< z_n4lq|KOE5VhFqh18gt5Si$2s2naj>hg%p;hdpt!#nOljlk&O z51ipB`#md5nBkL^VcK~)nyw-BV1l6(zo|NwxfF@6q!!XpF4(n^*7XI!vUdncOqv%v z|B!Q;$ORYq>#^wf;}8XYnMlpGyf2-*zQhDR{q!b;>It7*bjaFG8g*)^)4UfUo7_O8Gx(X%}9>CNTNXRzi&FggYAD)VoksC#oXW$$W!4+HdWG05C^giRFwm zsaOZa`d7HcRmuRGq$Y+JP~tL1;BIfEAckk%?Mt8yw+$wXygmbN+(mzs6sPXk&5vj? zaW$bZi=KtAoWvoN35AjEpW`S7azfJ0?J#Pe*Rp%j5v|vt&P_&vblT5-CJQf^JQ_?4 zvSy0$wBoL4Y}t{d3e{kQ5CtVvWC*D);y~x=J+a!D`vfDURJXS}SrX$iF`;$M(r+ds zSMh~tuoA>T|AkJKV*AVELUi>hW6gVrWfj(iF^(BF`A4fR;fhVNQ}u7&CSDBJ4P6;g z9`!-Uo0ej2ZX1T6WVuhD|5!w$6I2=seZ!uPygT5_jkOFdi| zbD%JCOOEO{a?t~K`wOPKkr(>BuWdXM>&I|EZi%WG*)~uZ6DhF3pQ(i58b8A$hfrd? zM-Q(m^)E!ZvH|;cO=SM!m0d*=z?9OifgdYzxng_?&oc-@W~BNj@DXV>l5++tXo^R6 zP3^is5cyD3VS=!0|3cgFJ}GH)Kj~ER@AclgeSVY=nNw@kVHw#MC~kQnN}Vb9cIw_Z z!dPiCnNY-deVAz`Gh{e&+I40jp-84IKF=9FSRth5p-&?WcUxAue@(2m51_l1aDRR; zLC!OSN0eG~G>fk9;;n)gx5!|{9iO5uO=+9U*>a>HNnui%LQ#gaTp&o$aap3fFK3b=5SO3r-}2qBf_1)*OQcUO2! zI7A;)`LV=Sj6)l3CFQ)rvyMJ?eMkvHCLIS8d^4vEyIZa zy2jxup9w=%i3%#IB4#AnV3*<+k2{Rq?Lh+Jwnf*om~+%KzHzRnLb5an1qWDvu%!_f z0-}d&py4=od}rInImGWz2VWZ=#6FC0LN;md-=yEd({V7wFS-2LbI+SSLXi4(|M?lX zT$Qawai{k0Pmc5|!Czc*hSm0S%FH9OhvOWH^&K+|Y>9Vb$BEy{>c)$^8fOc45e*Lt zHX$vMw}r8=*u24F$CEw1lYGPBCq4`RMC|wPLzA)VpQeJLClQx0IF{=xm;d_LW{GDD z(5u}Qa>C@??~|vp&XKLf*zlo!6Xu^jF9CpAc1RqPEV*T7%wMc7rXwu2QC)~it5pGB z&O97j$>K`BR~WVWjZ+)xOCfDF{hTNPGnb?(7d+{8;g@m_*5HaVT?Z)%Jqr=WKT4uU zJm~&{?)B)wIE(zLr1>cfTgLWv{vl=)YNUBg@E< zEScxfYhg_ySL1RaCG8;LP#`w6%lh6{SHhNxNwNW#0kXhAvN%5yTkbazgpe~2a6o?v zXSzykIlt9j4v~S*JOMY8K1Vy&R_(hmn>Aq!@oRJhqG}0mAYWVD(vl6^1&(r$ysophys(P(-#kDY5N@2C$3{>gN-yc~JkU6zG z2xSRt`={~6rS~F}CJjMs2$6Zu^uo3Os3lOw$019#kD$oBMq~&fu@@ZOf5Z!M=wM4=g%-uFbeL-F|Q$!}s zFeo!qVZmQIa*k;Yq&M%7Z4RvE^!PL1yGHZ08b1*Kc}fglF9`32tnB_cfqeK065&Ji z&?1-8pw^HPDn>EV!kzZm6QKD@o}f=%4Goi$AK8ocYX_ll9#|iS*IH1<{xG}i^qqFy zSdcsQ#bPHiLFUaKzB`(tad}QHvpm>r(hs%_FIA%`%8)gqMYS*|?=PeAT`ie@+Bh7i z4}P3R{g`+n`>-HjalR-Hx9~K*l}1<1Ed~bd`@U2Y2OiQW-oTLPaRBm6YrmX|>0@e{ znj%*5Qx-N9Q}K+ciV027n%C8y!sjqOqxIsZ^322VfhNA^j(CZ~smm!jGf&EOk$1oA z=6%T`k1a@I&!g4!4gmLDE}G}UFo!=q5wpYF%#RswH%b)uT4LFccBV^nd-BBn^y!Nf zA3zgg!u-0P#oejvH9}EGJxYx<6TtxzX+3o?&Tu1cVzI$30ylYgBKc(!Zk!J7SxGqH z^PZmaZVR@iH9=;_6Wp*Si3PXTORt5kON^zuR``^%Cb-j?$s5PFK4Me<6BGDE_qN?+ z^5n^&R->@*BS!z{QpcjJo<@@gURT(un6#qi6?>&O0BA4&n*4*iBqW~B>ga*rHEXSC zRb)d5U~=n*y|VDCg&@oBgtl|xL$tnJF==O^BPa?aQ_s$uiNd4(8(CwgTFMg{@1%rL zKuPpB7zD0W{R48T>Ek6$T_Jf}u%)v#WMh$kzfv9W%&RrL+@*^_HjIlMdaDLeu`4hR z?;tGv%yRwThpJAzgOFB9Cdn~G9cV_x9FHSixGv~Fg`cru-&k;BsOxM$#C}sNZcTtzJcS(Hx;~MufEmXE98NglJb)wKizYQo1uefA}4 z8xuQ4JP$g*W4Pf#wN%N;u4eD-IV8>8QT`=s6lB$!;b^7=&>;X6{K1a#%A&q9!~#`< z2=e#bQx1O!LPWmt-u;4)uI@kyIgJR$Azr;ech;72w~T4Q^1LL<-hN@I3HTZIr;W==h{1a&%2nFBbZRh^eVzcCx2VXURo8aAHjm)K(z8; z{ZuB+19);2U-sBz*0&1}jQp#uvJi2W+>)ir$E?v8dgX40c zOe$l76@*?LBk)$Ev(nDC>MK1QhTiHzrwiQzh=?k+G_9QRb1|8zY{wf&qE)da-QAeh zAb~fa1`wKc0~IcF(|NE4Pq@E1J_iqGFsvx{`Z;dH zf?hPHEJWwY0?8<4_r+#6k90z&5G-S1Y=LqYC&nP0VL=E~;WpA@`E04o`HzUF2N8ks zO(IG#n&2lwv{JZylQ5e_HMS*TY%R%%@8v6>>c;)2vL#uL(uV|Nd5>3F1*0;Rbh;>w zeBk0MAb-O~l#dEidK2(|U+YV9SeQ<^4G7*16Eo2RlQc;4m3PA{toMXwv=}r#!xImC z7LC=|vgv&Ebvgn;+17Bh?LK{OTSv>#z(=`aiy~Dr-H*vn?WHc+Z@USz>AZSU7TB}H zh=*!r`1=x?-yK8&h8}%Q%O1vF=rSh$U5}fBFXC6*oYM`bEF;8qqM?7@aWSSCbEVkG zj!7??onIic>T*LtZD*W&w^o!cHH`sbS-7r9EIvi-fe_d0n&x03AtZi>fA|C%BusGK zLdCfoZ2?B)@L@g~*H)7>WOX3S%#0DbD?guYla6sR#oLmrE zRt&68{3AO{DEhbJ&J^bx9NHgq!pAEAl%z9zs4!3_a~S599Pu>p>iMKr1}h|1QYWte zbm@y?_in!CBnO9s6@iik#VnPPHC#AVx?jw*!UWe6$vy2h4%5(q$QY2CgFmR%;()_b z)OSA9jne0#mThC$QRbS^sk;V#6!3$s>WwFM(jiYJxwtoZHvc+!E zMY9>r{i^&hw_$%G6X-sDz=R26%OCosATsUqC+aA0b*&vI1t2fgc6U0!NIOh7mxj8XNT)dpuR8H*mR7GtG7yYxbfy(Q*_`W!V8L>Za}8{opf+#De>&Rzn#CK);oD#qAQCW$cP!?5iu8P|eD zi)AtU^-axlyxQ70$Qs^aI*Kk|#M6JMthvxaD1EF}<)~4~54?TBK;}~g>MrWk&Mtj9 zJ#@H-mrT=wx=WIl?=2r654uqrJc2zweWGDwe!}v1Mfpt;gq-0+3~Ew{qh?)0Hd0d{ z*ikoS3yIzGqlG1T&r1I7=d$YOBbH#|(+Vl7)NYiPx61j63wveo$nH z)9n(*GEtRw?!((gPNMO9qz*;564S%LQZ#d>4wEXQLf09b?(Fa+`0*=Fg}TX`9vqkE z2iXLcJo2~#4q;czD`SDqCH`G!H-h2u)M1P#QwWZX$x29~y;%5h1s$>9wQZBJyAopC ze@b}ONI7X(Qrc1rf4zimreUTB)-8Pg?6e9xX8ZNX8?eBXYau0UiH0K!THTl8i+cBY{bpRA{!RQo#u%FXBvJ=NR*-SuSl~$Ts$F538d6u*9T)X` z)r1;dRJDx#ag9(ITX#&{w=!&73|RbgP166Z431Mlt-UgGbdDggx#crf+aO}NR7@(a zWf?mPF?XT!M4Y6Q?Ih$hq=wYhe*OWj290*}kk>|}N1uSvxi>7>jPn#yK3(;xt%|RK z(a#txHc7LbKoFA?d|VU1x|`g8VNLT^W9#cVh^fxdJ?4?*jU~MvY1w6=hf=#yh^DJk z{aI8$#I!^HW241%PHGK^=4MYS#;3^9giuEau%A#26rd?!iKwylEQW4+OcL-O7qAKf zoG1fUcks9Y>5wRBWHnF1PB2RP8(y?0yA(HnYz4d%ZNs=Zu`3CDi0ZYK&sJH3poceF zrHbU)p_b{z{ds5X;)XDx^K6fIW$s+v0=l^Lnlf?Xs`_@x)7bXW3 zR0AsFzzIj<()t3}Z!#C&}40Z(T1kqZ(q-;ukg%Xr;BQujM?4B-y%DXbo8Bhte z@+bmkSEOVTnTr`1QmkIEDniYp(Y`|M&C-*`<`sQ|aao%2Kx~LZNU0qVqmZ={ z?eNnkRbONC)JqCCVWiYj?@cyW!=+kNEev;sDOkHckcw)2bAJ`}brw&nJ=pUOQ8e%c z7jlUaqb%$9m3C* zX;&IP949|bo3l^je@a7&!%62)j(Yq);b_kqoj5?&zoJ9fUrG}2c(kyWV&k8jxo($+Nh zUMIbi&!TTXEk%1b{(YoCFf?R~&iTC3JH$N2ip-(Tb`%UYhSUEVI0&!l(4nn8jW*@S zq0#9&-T%jyW&`&{c!J;$*y0q5zQf=J=FsTCn;1k1>(^S0{X-{paig1~bVj?W|Dy;& zlWmF+3vh&NiLLY3$qA&d`I7um0A*t`%D^TDD^krNo;&k9PEf=#W8|Lc)ponyYS1ssq@8D z`yq-Or$>XJ2_!4g+t9mOszi6QH`f*~e2eaQ!Hl(`)&4ZxbkmpN5p(>bLhvm{ceBM3 zDr@#zu0WnRs+TE&!t#=D_%TOqyB2ZNvm{bQV@}z7{De8#KTEU})(cHPZp^WnB=wC@ zg#)d9W-)RB!ux&SwbG6Uk>)4a{na}Ik5-bvU9%=*fA%jD-#f5!rsP}e&z4O_VmY7M zj|@w#6+z$h6Io&{IQEc|=OQx4BrXu;drOXaSL!@W)u$i-rl5=;Nt+sfSR6p}VG;}K zrYd>9HXS$rI;r|b_V0NVA0+8iX1u0`H0T0UWKSr8`7hU?oy!&PInifA?^BJ2v_Y$R z=h0ertK+BA*j47jIba7)C8RLoH}(%M;eQ>1mIYr4sR<18N5O#MaricyvVq zrJSsB3l}y7M2cgK?J=>Hg22*Tg=m}*7~K8}+%e9F&R z+}>lC0EO|~{&&D?ZD8E*QS{~1yupGWPE({Ljfgy4^-e36c25;0 zgri%_(5OH%I*uG)+fEVSx(=C{mpgoA(nH8jr5TI^$HYy>w!U@bKC9{_%jmro6^J)^ z8H00T1%n@-1vtZYvwweN$gr(vtnrKfttE=4l`Is9qu+!$pz=)qoQN1*-9xPZMmy>U zh+)ki6^Pj_l-~4!`ECD`O>Q%NH*fmYZq%|Pu?FPmijoqRohC`q22wm_A(Q!mU$WAh z;D>qmH931Lli_81kAk;L{RdCRxA`T=x^zeirxn+uFV+tWy^Ix*1w+OUnsI&0shYpm z%hQuma14J<I6AfG4pl3BNtISEZ6aX{|G_(z;M8^h7H-EjR|MRD_aK=}coaU#F}>JZ zXdY8UbqlX^pfeHR?ce9Mg3I!<19SMJKdFndXk+Zivv+M;zsH^4$x-{$>wD^9GLp3+ zY3{}U0Rln&zOo7=UedO7_A%vrn8EKUUW6#y3kx`G zs-i&CH0YWJUDu$gDpXaoG%%_Hs!;g+wFewRfLtMmBZF_*?1o~CeCf1~v7xAriLpF} zj-;Imm|MQohf{~ApeO`^h}O{LOBKa3>*EY2E5I;|V1hwYd{C%@!N-4sw)NK|wdZ97 zdzM0rwt7m4E3y|w6I8d-P02kkG*qJO@0f=|auoToLHOcr4G$vup%YL8Ap{pJskpEN zs7Un?IKqn?6hM+1OeYrrwZ!Zd=_AvC7LFm+Ut+H6BtTzyxbZ~ue$;kM12004jSF9X=}g&T0+gZ)_7*Y=J%M#7kpFM3}4xRP|~^x2=G82N-hAep9rZsu7UuZnBaO5JWp`s zmwB|U4WMOlpp?2HL{<>H1h`h}rzF}Hp3>P_c+yS8zEDyFBVP;0tEWnalE?7!+mAvJ z0bTLqqUG14CDab8&TJwZJC#K)ZJ=Xe7`os3>}0ZlL$8lx#l@`%M)cZrPmM`$GMj`? z^&>rU98?Gx#|I#CIVgdU)#s zFY|*r*TIVg1}e;%NXWOQbF7hb8FbOn{a{7hwr# znPz|#Xo=O4{vyQNnV1m8qmV_=ZU)sCWlG6<#06l8A|#a;%!J-ZJsP^;$3YM#!c)#^ekT6zXKhui?C$gd04gZ($dB*aNg)bdT?M0 zYp(G2=7}bJSht}Yrw&bG;LQoFxVROnMk`k9POlu-mvO=2*MrbhA3};BdP@h!PMrYh zOdvOS1bHJ5P0^uLnV4ZPAW(We(76z)UC%+k=<0^fMQ`l{@%b_O(i3RA^nG==WrZAQ zC|dVI5kf4XE+HVAZY@j<1GI*qm8u$oJu!31BrLingskQ$yHpK(3h^wix1saIlk3p>}98OCUn!F~836j^q6$Y42?#5;= zB;&!s6{|5J$!l=BOxts>s#Bn#fKdaKX*RYX)^SicO$CLk^ts|Y?8UmUtAa|!Rotpp zman1IvH8SKj?ujWk%hpbn=F=wgIm>1#L^w8pfH7L10&)1;&H*PYfAts>>fIqab%zU z7Qii^8J0Q*t)&;N`vNcl_!R|;)lv~EAuwR2iQXP5;-yo0yfs?Hs&+p@ic6p?P3MRk zcn}Y6fg={CcKV9g7B;0Hi|RCYP>l z&)&TxitZ)Aq1{P92rN0@#eCSTfZ!aEYy^NpA%lQF0%I}>f7e2cJo7M^QADI;0TP$3 zgsS;rup)}ZEEuy=O1ka`&lI7Ayd~U(Qur6nOaq~XV@RBT1%{veIXbSprRH`cPd|)> zANlOG`;*Ly>`|p?^;2lU1xqpfsqkJGNRtt#3Uxo`vrn*tru{hqx3{h$9YQU^{So6{e>u<5FSr zR(i%ttc5L-gd5lZ9(UXF$|EThLIrw9+#6cu`TssiDLl>%>ZFOCxv2t!kXl%;2?~YS_??Isn4*gVTwA4sh50Y zT;r*La2h+BzAV%{1r@fzm-K-lu5=L*@K}F2Y>V)Cvw8nplu}CoI5;>pk(;un_d?1l zkLH9!5d?%O;M6)=1q2q?WNAxGFcgUaa1%c2v#ukt*fw@*mjhayD|GxdDD&1K01ANG z<<=J9l5Q6ZBRW(H1T_MU%Bw^`s%bv)p>54?2^G4aW1o!>wFR;4jGJJUb?;_v} zH?(4(NrW2EvMf0-0i(dM_l04!%@3k|LD=%9VOGgF6cwyk03e{KIs`L8bw5}kkI3@# zVWg9o-1j=VZ@kR{7pe~$d^Xr(D5TRUhys*s4!RbAs;HL61As5lIpgXX#pg%Ib+=&n z>0hGliW?o%Gxv4M9DN%^{aAxUh-FAf8`P7uU;9CfJpU-#uefn;N5~quMhivJam~#b ze)1u-TzVbUV0e!3NvSDmsf)Sukb@8c#pj3O4}v7xQ5+ja>-rl(C_(nryt9bQnop0~@_2{*a zLo#aEUY$`R%qW#Z3(j2Zgxlzidl(fixXb0%-N=u-M6RXJa91Z{&!0=>R2J>{xmceM#^R07Gt4ZR zur*K?%uRv8V`0w|)BPa%0+d-!Y=e*g6rI<85Jc5b zoES%OY!KAvhZbvv7LGMIe@{~$T{T^D2&z9gyOdF_W8iGs-*@b#9SHU=N1%QFS)Dq} zTn0n{N-%`t*c6nIABtadQb(dt1XPNBFAZYRA`Vu}gDML2L?`q_`@7r6C6BXT)RWHx zen0Z5K@6ty=O84+G!7X9?Ob5TYT3vD1)xGe1+mM4 z1vnU}&Gc|^Fj6wOW8mPg{Se~l^VS8|LkPV8|A7`tIB5z_Yz+_r6hgoW0T+O-QkQ|8 z4Kyh1^p7RJrM7i1AthH`VqXwqS0Op?p=3k{Y20W3y?)|3Xo`-DmcM^mQ?!`^m&vg_ zR9!(ZGIQ#F_;>~*M>FWVtPP4v!HNcqVgZFCZ(HTXLV)^%;DsExk%zCPtLpI-h9}_b zs0|<(Gf>Q>L4AHGRE0v-8370YnArOohM)R5hIjnb5mNaXa|m4A>7xPkuJ5f5TuKa!3%Iy6CeqhKzRum&{I=%_g!eOU z7DZU7$NqPzs>oqor12bcGcC5yi7=rE)d3$241_6;JwK-mgi{bh0R%1eB9i_j{gH)bL`Y5BMe25JT??lif(WRb+U9P&lpZ4j2C?=}>`EcUCZ!C*p#q?SK}-(9;04e~H*`H{ zb%usz<~KcJUSHOf0OLH{hmGN{f_?rE5;~2X>8N(dsxfefA}_V}m&a!z#3Z04bVC z?tTfa7hVlkn1YeXz}MOVmQ6#8R!&srWERw?gZk74CT$a-s@;CWX2=>S`v!o)CmzIs z?|dE9)e?Z4MXdhn-=XEgYi2Y-Hx8NvUi`hAVNN9-P}zOsC$Z#rzFN5@=MdZk7y~O7 zP#hmYF*OQvVjRWn6sTaJp(vtD*TUb`<25O)RiRbLVfdMc(fPhjAe3UF|5XrBL~RG# z8G{qk1ZM_})EKgZM^PLd0?VZ>!$V3C?pY2s7z1Y-LW?Z6$4pOx)-qD&R>%1+DDrXOB^m69F505@GiTu3&iWcuc|@aJVdE#*Ec z6`+O#OcX7FEVHV99N=Pu5>5mdOlz_-6cA2rLprw`Z;4Iu^e~d_i+l32Q%Wo^F#KA< z=?<#|fUYZ5E1ksciPlhECD``ob>^g-tVW2$0vk+m*cK2#s3wGN07Vt!hq5rI2og*D z2(&4nO!4$ABC7!8ledxCkMC z#5K7Xj!4$dyI8g$wE6`1@}nnk$&IICPvLLPdo z#ZxUKxIlhr0)g(vQemu6fa3Gb>iBm5e_zDZzSk>WPh5O0R(<6gji0ASI6ci^w&w-B z`Sr~pE^Q9cG@Som??YywA4WCO>tBMIwuV+M-i}ND?&qLYM8+(iftk&KWi!Z+oJ4Va1S~rV>I+!uoX+{s zPqq*{PzUR)E4NRH#sd0>Uiz#v}$5PQj?fz)(U!1qBn9 zw~Gn|lnNNOdmVv*E+`lkAcBAbFaYQ_*P{Sn_WeNZ_5-%m7t}7bE~#kUbwdJmaZUV}xQeO0aFL4aDSPO8%BW@#>4g5 z8kInFhSe>W(Ox5ci~wPn5Txu^WgLNdy$JOzn>je-e8%TaD8FYkSzg7leP9sl*RR7MaQ1*&Y7he{ zptrX^tEGAo3d$MBj0|*y@$soAj zux$20fs76oC|Jya&4>`LfaX(R#S-<}zq=0>@G*szPMR9$h@q!lO?t@e#`W9Y{zJ(Vfl^Mm(w;l#F^0<7> zhoGu@>ERGI@T#(}NW8YWoRBP=Epo3{XH5w~?&JW%y(=LYgP=YXb9v|?KlDT#EK>kg z{UAOSMsgTj_~7e^&TJA^RS0GRv*-Z5;MOl7`TBF9YUzBrQNa8UeR}2~sKI)3y`>#$ zFalo8*;FM*boJ$)CX_P|L*=bmNe80T09j;q69Qb z_Vc6!X59Au?#|G>lrADd1tUceu35c{8Fzq3sS`A@84U)9s!##$H-MsMfd^hn9T8gx z!wLk#1k^Bv&<)VI0iM)A@_xjZ3QP?ZKtK@gQ6RF!66AKLfk+WzEC>`;i}j%&%bseQH5UGXfC_kmD=gobeoc!n@lCM99j;l7};=3Qjf&cxN z$Q;>^)=M{F@n^nrTKk^KeIW!#=I8;mUV1%_{p5c+*I6(ViSyRi?~~eiWr8Er_r(C-C7Er!p>AlB-a!gQZmcBOPuzb8lz8?*<<7{Zf-aZl`5z9gUq5 zVkYx6LUh~zb5nR4F@g&)VuBb7IAK;w$)u$wf;PzFx(OjTiYGP8*i9(V5|)XaP%V82 z&niH{!fV0=#$V?U42ZAeRvM_F05*3(A_X8?fJpj5d>kYd0D=}EKv9LzOptKV(zPUm zAQ{~P7yy`If+zxtq5&!c(Kt|4L3CzmV+aB3N<$MsJ89{gu^5zC?yW5 zL1AffOu``jfEnS?K|zTCgXN^F2p~^5bXn$11T;b|;tB#jYKdf-5HM|4$VZ9QkBAbR zc_5CZKOvS52a05i;8YtCsevISFhe0(8<+kCD2a2a;(cpZ^oR$cUf|k)|e^oMr6T%WOYdXeWc@l)Gh_AhLdXJa}?1%;D z7bH-(@af{I zA0%V~1;t?qL_xKL96kmx0>p|SI)|9jklC*wGiaHz`CAplmMNfy#fCuPAdx%-6%gS9 z=y2R34I+8a$*`+0QK?4}QMd(CxN7~kW?B=yAeMWtW(#no37#S#U;>H&GXzdProfyc z2+s#Pt}X(Wb@TwESKfF^Mq=taUqZwQqdVV*ij&hm@99P~^Sd7-pPyyb4X3Udn0fqu zhAzDt6`%d7)VEJgrG@)+R%n-}Og;2p((``@RJan5 zbffxR+Zoi8#o~Kfo81zZP#chV8SpX8?!w`MW=DzT zSKlseAuH9MMW(>|93>PosRRd=HQ)?I5mBwbyq4G#4}6tX*WVV#H@?&307Br5>CX!QIWc#F*bP+Ft! zyYD`3yY05u@6z4YUi{VrthsIXX|)%BBS2yw!}RKDT+W5*(Y*|Ah>90Iy+oy|u-BCX z{mskmf46~4=lAVefcAY|cQn*ny66MT(it_i$4|ZEqxSPtNWXC14;uzlP(8Cs5 z5yHvNeVl7stvx;kq7b9TP>NrS@N;1ya19+sNP{_Ym;hiBAP#JeHv&wlixD2TD3M7h zS0?t*j3Bo7R0YjRwLnx&I3e3M0`d6C1)NsMW~dKvkwF+4a%WTkM`(*r^0J#q;DyI4 z!v4wNgpgSj$`gy=77~Du47oOdM+%T$Axs+(c#JBLWwwkZ?3Z)`8#$ztNMP^+OH`A@ zBOWUpnKC3!gQOf8fx)5#nAsN~ZvbEpe~)78Z6*8B<_^k}vj`(1>s+vE3qfWrS}BAt zL-bro0F+W-%gP1HQCPd&TDCuziZV;4%&92_F1{2L1*@{`7w(F#p5gf1;XdFZr7Wu^ z9L^b}P#r6Ea6fgg#+`LImv^u7okJp!aTTywXU{qdW!YjgKT9&Ux~n0N1W%b2p zd=2$Y+c^4_PqXIsk8$+gyIK8?kFNM$2oVJJ*4eV*8%{p(H7cvuv;KW&2MAOYGr#Mx z^8zkHO1#ntsY@2dlN~+C$;ZCU*i|>O_PsxT%KK*1Cm7rL)|Y*9_Rb-d4jQov(?LYGlinj#F&Q&)sp__qqS9NSTg{?=MlL=Ze~OfA4!cih2-D zuh6!C{M271&?mz6EED+lyN^8Hcv^?c#bgm$hdhH7S+YKX8uCtbE!qx93?6}4&cI;&B&R;54RxE&yLqfApsYaBMU3hUlN=aOLXyjjiAyBWrQn1nrJ!ajAupyZ zShOmH)(HU&Zw3_w#%0Y_VKETF?yNe+hyp8Q2*pzp14ObL#V<=uitpsq$iB~zcOEYV zqRiHRn@7~jKR!AwkDY}3$>GFk)z}`p|Sc}3G7*`-nj!LQ>-oTgw z;VoWBT%LiBI?cvX%K)0rbDMhL%dCCRDHhD7E+k_SNk2;xR}^tYu`rV&rJ}xNlJwXd zLJgtfgmmgC$>_u~U5Ak2wTKl)J5vvSjq&SlJ1Z?nds}n+$C!EiJFI!<9h~^~7nr#D z11sK6N`=Fd9(sv|=bm8V){mSs;Hz)mcGg;z<;OgT+81AVn)&CSWa2IFIV%=r_KEvh zed|YFCTb~9Y*Im1Alsm2VU}p?Fa6RTKXARtN}8U%r-(`w)*DsXyU12Sy2E|#r+7=&DZ=LC~EzWkwKp`QwhZX73$FzUf4yg0C z`+J)^j(n9)DBQqyLw$z{)?-Hy;hHk3SCpV9mr(RLic}EX_(l{M6)%v3CXA6hh}a_Q z7H2>WSVZFS({XS`SpgM`h<%9uj|>8dZ)&_1U;^90Kn{Z$ZXrUIjvZRz@fj!(^&(US zXisBTOyjvQ;*v3p-vH654P&G%LRb|>M$$v22yBo8>4V-ynYcTpDS?YCt=UdEB3EY0 z_!2Ns{vMBw4B9D_5acRHsxbD`$TG0bQD8uLVi9c75{qb@KzM^1*%*TSgzvbh+BRw- zz&J-O(zKi-mI|#T1&&ClQlMLocS>fYE!yn>9N8P;FS<7Ao>9@#8i4+m#xAhgb>vZY zZhiY%75tgTBDr)JXGr2IzG;vVNbAr8!~JEJoL?pi!1QC^X86);P)Y5Sqm|yqZ07qBQ87ahCzZYFR2&^fz~02ZEqlKO?0AeH7= zuV!b-Yg%~mDO7!k`dPYWma$Zeb2Ja`VR*;Y=X~GA7oVYZ{2*gj-;9haXXVE7-ZORo zmza3#%j?K(S4p@Y&|(_%%Z|(6+rU> z!>B9l?M>VD-iI>iw&umQiE@n?&O(+;s{%>J$wxf4)m`|8w@C(8#h^h%2A>oVxzHh$D^#A8#fT;K z9tZbS;L#mkg|P=^siG8MqXK1v%f?Gb5e194Dzzkq%!$xMNKBcO+fK=qWg2dV>4=77 zp^&|!7)j4~CX8ANEV;ELN|8HDRY#pN#lkt_NOjnkjytG)P}%dR=%$Nu-+o*o7! z;Foq8W4F_2E}z5LoV8A{wb;(?)n*Wr}QX;h-yWrtbeTlW+gf z%VHFceD%|;z5U}jQ!xGLxBG;)-Wa^I$T$fXGv1-(`RRj>eEH8=`<{=VnWbujzAVK# ziCUK}%qWTwxJ9e1>hSiL6w*p!;>S{ra!}Iyc;K z!#UsY(4j+ocQ8A$^Ho_?U#sT@IJ)}*e*dm} zxap3c<9$1~yeiN6TD{(*4}6NsO+Uv7u=}1*vEzNGX0}#7YjkM&{xMSjZTi{Io=H(x zBh&s_ThLpMm|WpG`J`cVhbF9&ZOu!`(6m$YdmTqA1h@@cAgOQ9@r8s&6aYzL@mApH zHQwqn>&peVO${(UgvRA1b73U1;!#5dW?Dlbaj5|9uu}>Z2W^S07{owB9BNs^Z*y3J$7^vnK-X0U~G0H@sJWjcCpF)<36cVFyOjMwqMxziwMo!IE z@B(t3qfzM6p;L(9EOJ;XGQwccBEn(GaY!#hz+8vuC`08CC?pjXm>VetUP?0OQ8KuE zjCDjh>g$W?6XEuOmL66{^o)tuf>i>@$zD{)0dHvO$ZtJ)os@uDu>X z3&0IG+`xxEbZ#K`x#yna;)^dnFVF%odvpzulHTz?VDGE;T3@T@ec-Np*!hX~ap#?{ zuHxjidcAEe5x|c3z3(hFE=w=-dVxsWX4@6Q^xS}+#NCoDVM&@Uz9%Qf(>UTd@jXLz zJtV`b!|1e`mA)W4!096BGF-@B@lpm$b0rThqn0c?gu;FV_9u*ur1aRup#LDE%=!o0 z1l!ce0YfpPuq{Wj)}YqeaMfOR4!K<7PQ-}FAqOpL$Y7^6a?k~l?RZgY9Lo2ikcc=q zu!NDg*(e0ZWg0P>B4Uq76(k0MXLy^UvDf3AMGr$|twuBxSP%#ufQr=yi3F>VMg}%T zgxUj}7%G(rl*8x@Wi>7`D5tQcXxBm90D(0p`w0<0e4HRLdyKWCBqSUpEJyCr9SiXR_YOzdPH*}2PD>liE=8fEU;?}wb1N{xZ7mooF@gN*h#bqbRb=`g7`&Y(s2G}OLi zI@7ZbZ{NxMb5Ag|{i;qRf+#bTO6y}_+;rUkSp80fGc#j(N`1?=^9L=?f|PjcI?SNU z^U$LtU!S1me75JFdk%n$FTVJ^ALFJ^-o$VJ_NVydCx40AqdQ(T*5kE$UUomgZ{7L8 zk{|xyfy`_6KK~LOu=2ofKfq0&yyF~3MZF2OrtALcXji=Ju`ag*=-MM4+s$;bJz5vn z6XkDwXZ(}PW(Za@D&)8HjG%%u$YZq$_bbAe-%A$+w@n?mgvAghC%ou%9d#|(AZixZ zRAHPXeaKOX%DmrD)WgDq;UrqSqDA$R9M=G;1l}mT0oRnMA%o8(ZazW|nJ|7@NMNx% z=}M1Ym*VDP)T#`-zm6D55seCBCG=?dP9pogg!$hrj!VkS`7B8$oqO4$gl zJicP^gH1#XvKgVW7*{FKd4iB0uPvsM;UkOABeaX~%Hbo6jS7-12?Apo97Ym>l8Ts+ z(CefvH>wpV2RtIZl&Evh%Pf{yv5?trPx-Lw&cte%^Y$z5IO7*6 zpP$90izJg95WxKO6axc;U@fv*>j5IcwtiOQo2jFG?;qcR%QK>pRow7<_k_%uvs(Rv z_`DsH@4cre!uK$#o&Bg~aWVgbs@;jlqU%l90MY0Gb;h8sF9Ey>)VV? zOW>VEMCFxQNp7O%=2&k;mr(Q4i7m z4CaW6LsVLL87O{tu!c_zvSPwxMh>jNok);%hp*;{G=i}fE>}U<5^O!8`TFD_LVNr` ziWzJo5EO|)S&hszakGj`3eX;5CE2WJe!m2nFnoc>Pqt7fwAGzO!AghlAq^M6im+fw zAuz%b35mrK%czsr(g7^(@eL3Qjq{$|n_!#vF1UjL|P5JWkS?30n1vZCC1~lgFd_E8 zZ##!|ea|2NKY=NUV$A#uhwr(I^&dFPjvrALQ(A|Y0f@!1f*6X-k)?*(K-6JnPPGk; zBv|WdHa*SV-(_U`PDE70rA=%mhz5o*wm>Nr7{2pi7y#iM!=c>Ie}4wDUI9W2i8~bl#SAol8zmWn6>zo@j6wXNsPnL5Y+J-Wr^9s>YaQ8jj zbjSO6HSEym(xLN;Vx`x}{@rJXo_(BjWaq1roO>?ES1;Mc$TcoetWPP|hf*U6moULk&2x{T0w2-;%i4;93${bJ)4ERB_Pb zPDc3LAO|gGTH{+1RST?-UY&! zzmJHkot~k#dni&7)_Ee`W^*JW3Zd z0ID+m=i`%iylRQAuT_pq@9TZ7wsiI==?Je1a5y@iY`GA%tA=U6M{kDlGf`!|iVZK&RvNxMuj^QfbAZIYdUnfoKg-d^B@3$4pl zhfjjk)FTj9V^bNd%uR(rmOV*jrU!s6T~f*-Y93uLM;`ExDNWjBErp_DVX23t5Ht%;&?oYr<1 z^?;V;pXsngI^m@wPp=4E(qo56Ce|XP#5CrY{oYxJie*PUdUgtl?smaX|6>|^pJndp zhgtoOJD9ln{b#uz_OM(+gq|u7wwa-7U58UrRU}nK+BD1^Y)~JGsSfmC*?Z?W_Km+{ z%{xLKiOW*5g%nX8Bx}u*BqO1TJO%Qd81REe_lG_3t1(eu&ECdY*pi0WQ7h zMqI0jx2}(M0g%RFbdaI7KbzJTq3esFTa!xSj0r5BiqHcCocPY;3~s$-$r1NUfRP}H zsw7dBJk60((pa2EE002=bp^G;$Y}QIhgtph51$1i)&zBwD5-bc_)hi40@J=VqV}A6Z&CF4UBhmbRSOJphK||IcV{DAS8mtI&}AV z8KVA0#o{xtO@T`#z9@tATp2{C9OM#LD10H13D`^`8XlhsFcLc}5ek$M;eJhpnd^?u zYy*5tBB~O!uSapMr1}e5l$hTM+$*$E^PLr%&-_xTb zmoSQ@;8#kVwFs@x+WpeI6I*`je`aX=&U5-QixRY1XG15E3e1$MC75Q8R1%qVuRkg^ zO{Jzu8-}C%78n{ys13)M#W|**e5eCj%)$(+GJvSLpk>OFknZe#_<&gx5`@n*PI0c! zdfvD1N|CHu!@i@>ux?^&aGO=@*tCh1T}O>CLaC(yjLp$1E=NBa;|vOg5DuG#U_cM$ zh)9u)tvajvg3dX~T9njO;yQ6WP!c%>S&;)Ct)f!+ZcfiCuXvtxWn4lME~13PHW%;+ zbglj-@^~dj7_Z`1*%3nDZo2am-1G)`pI0$(VyLlQHu&=UpGSO}j} z17-ScL*nNZE>oqEpmZ1caAhW?LDd{C@?b!ZTYM^sR~IGVk=R9v8Vj#e)I7q1R}O`w zSO_OyRSgzugbViUmINyhBRPI1K@H|Xdotcc%vZzM%1iug6u?NTz)6HFfs_xg&5xwW zA}Vub0?-iJ<01#zL*#Ik0#PVbGYRRq(lc_g;lv~T$6;)Hk0zvy=r_WGkSN+owgM$& z7!e6sx^n_E5*R1iH9&YA)>|?cGC7P5$2item$6g95hH~_iy+7aL8N*|PY}hLR+dw% zCS3+a_Bx0tb6+H?qvZ(qHHD?wN|92M#0g5tZv4OKci(KB+>UhyB{inGfXh;niM7i> zM(sgf3-pBhDK~6XCr6*OZWMYJZkt<AE6ZBUpI6f-BhtyO$Rtn5qgixMh8dTlk78UV2hf4+KXn6%F1VWgyJsMQqGjMeVnM9A;0H)?5 z+^j~9=E#vEG)fQW0f^)hGKozCW8#|$*{a+MNM>1sUM z9X-+^twJ{yDvv=qTx^g|GQK{-wG8un!+31;BEir$j}@i_Dhe+h%B%8q3A}JxiZ9>PLF4&`U=^?H@&PL=?xJ#`3%{IPZ~C5=9!>qfJ@A>LO0gA7Ln$L_=f5qZ7+N z;)pI=SoSIT4r?QqPN2@}DnC1M^xSh%Rv3C|8KL6{Yb}fEJW@!iLpAcL1)|{^BI;ih zv%@biIT4YpeG5|u=Am(%vF#T!y>OJV!F63WN=MLYQmNHKHjIcttTjXfLp|fXm^52Jcnt!yu2RShR}`ovt=BS&@KJ^7 z?|-KcxCo_id4{SiZv#&c@29qAGsXOL&@!C@B(|P?l93B9$9sqM!PzK;KqAY4$E9aE zfy-LRq>j|V#pu%(su}=gG&Bm{Q#2Q_jRjP-PBb|3<_h%Y_U3kez-9T#arsopb85Ka zm)-A_%*@h%%PzZ9-z2D9nBjzlR*2B|xx$&Spi(Kof-4-tDllOYbxTGfW;#N~z2mJ= z;wY;QQdOq?hMzk+wL3x7>jZMxAmY&KCnArV1vO-`iz)!7stt~&BDj&H0-I`32DQ2f zcInaJeDYp|@r?<2FhYA+NRY#M5E?H=hzMwf!bB1esSW~U339GpvQIK}6={!;g62mG zfovrZ1@Pgt38SncLduYqJGosmep%=%id=$~S*R!wA=|~5g@zJ|6_%*floXf_c<2HM z(P3HutalhJLO?xAI%ArSma^?Yk`k>X);lt5Lsyd!=tz?m1#zTHh9m%+%obSh(Xy-s z=(RnwLS{?Pf+K`LN?B@g1lBnUW61J?p*SpJgVkZa^S~E*`&)nJl;FdQ9susb=cHpr zZfj}I0k|x_w42rMJola(*JdJCcrv9F18NBGJ&UbbvbaSu-6DzV#AD%e)7bw4$@nDE z;0VRSEJH~XGqILK2aYl}JhA*Wl!q|ji?Xy-h^{2*96$@eW6$5qEmwSGHK&Zjm5 zLP)Z;jd`LZA(e(&JQ%b*@u{z`WTi@V&1OuifmBh@<|s{e^dPkj{b7UNIZSIYoF^9N zPP^~*3oq>eRo!C?x6V@7EL?C2i4r=DdDA9H9mb@U3fa_Al2vP#UGzouA)@*aF3)Hl z+=FwL`uYoB5f;YgX}1XU&F#(YZ!&Q4XTln1ysBE^q`$%yY}-ED^xpt1fiJE zt1@pT4Y*1;iCc{D+8~ri)(mzo!es(IYB4k2FTEVF%YuJ#;g$MQQt6%VFh?S?T~??F z0^a;ki0E&AzlIzD4ngt0G^mOrT5T~467K{qlc<_SCLU1@P70q2Yy>n^us2s7&WKPO zFjByL9CBqGp+Z2Gok`A@HsheXVK{?abyy;Vhok`M@g|I5gwaSB9>c{2(g>v0$o9iX zi*ypNLZ^}yE?lj<7_Ur+mM>I6;ww1ih=_u;LD--vKz8iUZI%Tfcfon2r6Q3E>q7!+ z2SZhJ^MOX8)cAD(n^ElClBGD$QiCn1~+a+#0jmV2Z-uJ%q374o{gK<;k_qq2B%A9 zAY|vrxY}{Ugy$C>=0uz$T03y!1vX4>?_)uh6(f3!92llpm<0qXsRU*MNUR}UTqLR1 zu+4c=EvT=gV^NCAsx_oX4p7^8VQ5(%8l$oQxn;nmJ>RpfCNeqo0zdWO*BHC{Z7cpx zNmY)q=xC3!#aX=8u+XBqY67z`i>lU6e{AD~+J+19-jPimrFD28^-WueMpm73ny$-I z4t?=|fPjr3{rNXnwKumn9^-N<_N5o4h;meM21)NJz>V*tk~`;M$ zq0I2j1Y(z?7R$!LWWuZ zJFBs?3i$U_YTOSNfA#A1w{*60z3ss|^H95e_CwxLjy8Ez^G0H*Fk z7Dp}+6%o>Tz36}fp&dTeWu3Fbi6YF`3k`(^Z9|?5;3^i90@X?abuD||Tj`KK!pVZj z#~`v!gR?;4geBJ*6<-M;#|uzxCs{Z-cL7Ft11&b}meQTH*v#c5O7|5Sb{Ux>B<+^k zkZ$i`H;YASO&n>Ab2txLD_p5Dm~XVGBylOel_6A2_H+^TfR+v;(PNM9tsg)L(qo4Z zNkX!A1A_}=XC8-^A6i=&M2`?xNQpCLE=TVN{1l+2b@TwE*WG&l;~^msLLt4vj zZO9TpCQjF>u)FED+Z!$hb;1 z*0j3 zbr91C&d0{|5sFHJbe4G0P^pic7KjKTsZ6Y+GO-SmHkp3>JLsfJee-s7eekr;ZyF06 zx#v%D*0TPCKY7O6zq!4+y&-_hnGsFz75Q?uMu?ugI(+Bfz4>9_gEPicUe$^a=ikFh zcOF)@Gg<_`CGl24qK#Ys)&!W=uN19?yL~Nb*9$U=g%CSpY1d zmcStf3S2`YrGttMLft$Z9$zmIHvHSiLHsM6M71jA`$Z=^#l<ep~nq{y$a*B_)2o2+ab0IItw>y=T!e-_8qO&0Spa)rDn|}10XCE|ohVPs} zl0;$TWo*IR;z+sGMNy@sj7yP4P!?9OSi zNF}K*0|J$a^|bcC(5Wa;^&!;Y5VqCmXiVCSi_{UOF-ttQdc}QDPaJ0W;;YV%ZMGJi z!={dCs77P|0R}d8>j4&z9bgViUSvqA7_1JH#HVIrbfw1l)wh86%)js?>EV6UHeJNP z1^sq!o24B2(p?k_bFBa1Pp_!ed2@SndlR^vf`Ji~CLi0kX7t@ql;fi^WWPhd_h#G) zM5ox%D+jsg^xF7NMo18?c+tz+2z)9rxk6Sw(TKyQ9@mfoK$K%7@4*`pG$L&f1vu$( znFIoRBddTDxSGe#^w7FhM{y)VCJwitP@@)6FTg2$+g+)CVUX)fJ-<0*Lj?x@HXVNBNnTtb9o-#(z`Rt#;+XHGD3#f?9h zFRqFh9taCoGhN{1%t4Cz8P;5|lVV|xV(ujN;`J!+xoqZYYJ=m{!AO0aI9kpq zNF@rf%;G$HU}U1p zCPoKW^Yq>axNJ+mX|g)Gj^oXF7WY2Kzy;gOpRLC<8^N3wR|9Br9vQ{h#RZ~GEB6o0 z?Rt#WZ~x$#L5ug8#vHf`dbmbDcd`Sz+FP7dsV75-fiU7)XwERTaEvrtWUxBS=-?Wn zmF(t1FtqJThPGWvHao@f@7{xyijm82;MjeiC!0CJ`Vamz$=KwZE7+Uc8*-CNnDu3h z$r+K%ia+wp9-}>%7kwATC5(`zcBROIyM?@ae2wgWW2QwofjUdwjRH>4I zs#3qL5M{2@Z%t6s7$+ z^a}}O=#=Rj^@KkQXVC3&k`O`TBFpDP2GO(B_);v}ElVu_F1t46z}U2JBZ;GkNGYZKFYPBkrBv@sO+|X>bXtq+aya?fT)-4&S3~*xZ$Z0>= zZN|kK6B1#2Li0rL6nFPxRMyEjkDNVF08GuyO74g7rS6)?Pl`%awOy| z))aW>QAq{UYy@ld3ZtYpU_H~;cxe~-Dr%rYF?W(^a1`(R0c||8ifnqS^Y6jhDC@^B zVC%Xo7#&>AeB&ff?D-ClJ%1n53r8^~U-mr7$SNjox}DaceLVMjcaqMYWbN%Af6YP5 zxi&+;xxKml;24)>R%d@|)}==WaH`w*o`?0KXQV{`n8`~ACM>whL_C!J8GDL{d6)V} zY~af7eVpid{w|x-76kh|*p%#SXeO3P;B54m!7eC5pQJ}CK{RHGR$KDp8oQuM!KJ{p zBr0*l>oZKfKvlsmNSu+#*rNtr5Z*3GWPLVxDATh+#b*SOc3=WG!M{L6?Hn^KrNs zTd@Dwv+TU+?WdzDI(ivz4ZdXT`rdk_K$bd`dSJ=M2G{WD^Y^mzqTARwxs9(r`e(fR znji1G-_Rx3a_F!Bq?6yGs&%qs2N=9y2SP_EJVkR68CS4bV`VUM-~}dbde@l&+9Thf zy5=%WGb3L(Om$*IV04P*pDCL*SgG$i(h1|kYZ)J2i}yjhwD)-!VZ2Ymm7vAf}JjcHISLjNOp-Zm$8*QsDih?6Yj?irO2S-*a6^4d} z7#kaVa}|HX0vExudLpq@d@H)YT!vZ7#k0LAbume>GWTj*d=FzHg~0f7fTUb!4zONb zMs72P^murpB7hrj=@$iyavm?rsDCRUF6-l6nI78^h{RzB3O>I$M{P{zfpg zZIsm2igd;${$+o8v*}|*!{Z30X&!hHKQY1a`6Fy8!`{Y+*D*f44uGk-!x(267#u>J zTp${$0}h!NRO=()9meKJ5tz8sxujOwzWwCqxNYah&SKu&>2wG)<|UxdEVhWphgo>` zF_Km5pgcU+YRT@U8?!L&-@ktuSn1u;G$l<_jvo)lc+;j$)M~XiSM)a|t(giA_U(wLdu!tph z6)T^#LR5NrQvnEva1t*p(kq;Yi{qQw#w{UTS2|?mu&xZl>eb71Qe4Y|#dh9|C=1Vg zS$E$Oh)9tLiS`1!D9hXy86x=w2o27FuwWO12-Pi0MBQQXGOVr$>KNaWxCMclFleFi zMHnT?s>Qc7t{F-fz4Ew*LJeD-l`v><(-CUWp@%&>mBDsg$%2zgTcq%TVG*Je>2K#1 z$DhoJM`2AZDTTJ>0w^3_8LdE+(%!$-C|GP#`pVvQYYjyGtBFLXgC9 z2wQ8mh@%LlRd*p0OCtVz?b00qb^ssA67aHR%_U6FA7lNhffYWd3Y)gVee)F66W4BX zOSM`Fibzlz&NXA1R%JtiC=lO$=v2DZE%rs6c2MLqwnR)D6tbNbl>Kjk@>}*J` zm0}q%vsrq^v0gqig=sF39r0Aw3sikI@!;6$2x?SZVgA`C7`@_#Grm3E7><19&q=2a zbI}KWs`I)Fn{#w}AG`KH$b55_&8v5?Wz8jM6)|+l)eK#7HO1UXPCoKY#;<$(>v};t za^wheb93hfbO5$(+lG2GnfMI^TzUnyz9&|0B}J|eY>6wKEPXK=%fL)Iu8={~(Ye@c zKW^KUVr0;|h~8Lw4_1cTM+RX-mr&=bxV(b(-j$F=bRIMKdOfP*5Hjdr-fKqCbw^Sy z0Z8EyE-)-I@z^$N<9#S7RHZPu5XhRt8x?Y2On5E6A&_-TaZ=NIp@JT=R5u!YQ-y-W zszrEkErFWMVMYgsj|HR)i+ar>w1uopi*2c%k(vOj@KFIuptbBYX19TY(-xh_pu)eU zFK<%<8z;LisvyJ-NyM56hb5s>_7W9kOui%%F@-OPL?|*8K%x>dpW({IxRa~WqkXa7 z6R8l$WxYcwjgX?plrEMqG(9+jrDCftc+pxjG&sOQqd~1w4MN?%R%m*~R2_hvWjWq^ zq9|JS!5^-V^TOfpvwqdq71vkO2q(|x%mPF8sE2U@q{QWU0B|duBxj#|nBlA65?C#h zcl&;v1EqqUT9<9*=el`MHhY3(bP}^Lhj*3}s>RxYEz9iDE8e};KpVrVP1|tJk}k|6 z5=|0SIv_KAkIu{p9X#;@Cl?NLV)iiejcG2u;3n$H*;{gj(%2$Hm3kA~OwmJC^6BFw zW0MSSyMmb~9z;bI^w0>k${@~r8tFXOZhI#W?z)E?FL__*@kXzC8~g71y-rGRb@fJU z+C)`qow1&btKoP^*{K>p2xgynfYGaNI?dben0w|ST)L5wD+fTxWurhLS6(nHlk0G% zK2&3sEvHZGTVb z77|_qw#D161>tq5UsiHF2OQ{hf()MNop zLQ{uJ$$ALT^96{ygE;T}Uc?^e6$}?plrT(sgpow!jt%crWq4gz4C*6`@Up{TIAu$1 zOBr4!TxiA?6036}TOm?$Nlf_8NG32VQK@N(P*Mf`i!X?YQ9@Gqf>hrTn||9#a^M zF+u1XMW@Ugnprr0Y9^rwiLTRo_cIo?sIJ>mG8Ps@gv(lZ=g}(!jkQi5VW@IrSSU+J zR#+s1g*LPtpL!uX<>F}##rzz}=p^aX5#+!S)6F?HuG)5HW+Y2VPadZ_xvmW511S~N z!69rGgsYYUA%Zyfblp79?0b+Cvxm8E`@7gMaZ$Ojd!9Y`2q$NcaP_u#QmYKC2)dTC zFH-4XD^{{>{d66m0Wf;yjhuYs8;o3W11hPqed9IU_xPu|ZRf{WGrGCY)-H8m6SJvf zR3_I^yKo0KOFNHevlMAsqFr^R%*z zTBXwYy$A9<#~4esQX!6_B{uBk+hA=B=R)%Da@sxsmsVo|n}>zYS&u1P2M9>#VF_?q zd}$X0S6z=15}UVBNwsrTt&&P`t@I@Gp6zDSCf*pLkukDkhbRVX7}I3U*rqcwG|hv1 z(1XL&)~$S7l|*u{RbG*GV9Qo>}Nsk|9!$tm)BLW|BQ4B^nFi>MtI=Zy#FQME8n)1x*pFcpuR*SOj6dgN#x$`mIH zMBSAIj~+2(0^`&OZP2pay6j8avk_2jXNM2~k0NMbMEG9_aFIb;)fuT-ZO|@gTfDO5 zx=AoS>+rviLxzhGL4ZqKYFuRBXi5>-l{QeQ=!C)-C{<>ol!{y_B$cR&@s8YDtn)zx zD}ueb?LG>Y?C>*LwoS{jZ3ZRMp-no^3$mghO*52I)a$jd zujRO?C<@XvUGc-edG&U(qP6mR?|Ld3N*1ZLXnJ85&J@e;x436F)m7_pMc%R8dgqW) zgw0GjA~L8bK0B5LFpb4Bi>5|Cb(GnPCyA3kQ13W-PJ zjKk+41z5yYe3k_^DoIv+%<=2r!SQeWWdK@IvuWaDj?L`jZI^wRmySNux!u48J7^v` z5S~wKnn(BdjbvQbBpT`m3bRi?+^q-bw!wzux%XKxtEg-orE&1ZQ-YQNT+}H6>A(fs zX&pVl;V=FVUidG+#rXB_zjvRT}*{^jy?gf= z-;1fKDR%GP9hl!YGH?;Sz@*0w)LtMvJvDwgVCe%n?YMW*zxId~Gz|cY2RwWKL}8{? zk2uqJ`)E38u%fRsNA_5cDHN*WQ3Dp|f?vj|;q|McKqY}yY0PJgt_}=}Eiz=%-#(lkJBZkP0TB|LwK}5+mp1Xn zcicxVOV8Q@UCd9TDiyGnY+;reoijPKe#HQ}4m*=InR)6#R2(yS(G_QJw-z9DD26yT zv!DAO{|k=K9^ma)+`*-rZ#d@;osARQxc$1HWM=UM-+1D)OwAn*-(e+!)<;CRR)(3I zN7kwoi*x-+w@bFkTR+V4Z{GvJnz1b$Jn{*Ym!# zuvtnnKH0}e^^NRAw+*|PpP}*65h|18WG7x=^vavg0RD8xjka{`ICcM*c=1pE4HIvB zAKQN6fA8Oi^W3tc#s1^Z@|~ytlJ7qKS2Xj+>uv!$A0h6!j*VUqEX%pR56?gU{2Lm) z$Q8*Iv7B@13zA#XYuB6MFZ%v2`tRGmtAuz62DV#NwL2o{rXBcx@um_8-xZ}wAwp?l zVmX-ROt&1WW&;?>!--d@GD*h!F7VOevAl4dHQQ&P#~rRAJIo3Qd`saP5+Okk2wdia z&^8rBYb80Q^DyUn)`vkGeE;-2Oyw%uyH59+yECn$uj*bF2O|u+? zAUB4QkztZJCQY+oo6a&?trp&U1_tWH@u}H?II5l!xU{c)e32qcSJCY8w6jl(FFe)P ztphOq*mtRK+=@wC=-NQJF1nuN!;*DVXBSwVO&=#78l#w-A#*v4E;iBl2ADAHp`X&v5k#>bkx`F$L@_ig~Lz4)Dc^NG)J&9-;&ohSdYbDOan-_6`J zkA`F1qZ@HWfmxjIJ8p}6pJn9oC5|5{!8=ZT=PSfR8)+SXlCf)UIWz8)YMJ=&=-2ON z&wu$XR^9M!F8bMjvJC8=>$cdM<;gwY<*Se0#S?qJ&FayOyzTN2^VZ8g#6;;Fd%bM0 z2BGI6eRT^KV$-qI)kgdapX97v&W;{Th~%nUMr@Oz0nR9csQ`bJBGsg~;vh zLR}e?tbThC9O85**;SN_S(^xuQs9KeHzamZAcrhO4q3o-)A6Nrj(RHjSTu&vpc046 zL!OE##k(PM!-sKB3aSzU@51jLLixb3WC}fG1Ar1i4C`7R8G)`40FP0)2Ba_5a4ki& zDkmN>!R?fXk&&pBwFMdmu1axp3YiG}tUySINMn2w#zta31j%*W%|_uWp*)e147pIj z3y&%ye5Js}1*%mGHfZT_vBfKkE-DBua4JU;;k^rPA!$(PQWWh`qHMR7-7v7FfK>po zOla6e>T$i3cB_f7zQA}#Bvj|du5=S=tK=(RylQp}!2$Qsdb04v4f9MQn=8RtX!$)m($lcYxv(5h%+ zov>=))C*IwFhlduUIw>bjy%V?zW0u&UivPJjTtW4awG4&_7i=K#LEfD>tkS6U&O}M z7jgK+UcUbLXSj6B4NO!f(PIM~eX&7nSIW$j|Cx;+{#&PIUe?_DVUBp$?5%bw%# z*FHx)coimlfytXccvi1ZXpJv&ymK78_p>w)?qU6heug#gxFfK414Ar4_XI=RuR81Z z%z4N0nS(rg@KGWev2Nl*F5P?sS6ukkaCoexd1x;uAN&fg~Et3?!P@I>eaGznxj1nyEN%x!O+#7c+%kw)TLrrDb__% z5Z)Fcs$EvYI7n)NZ@Z1~fCD3tL*V8D`qE<_Hy79oS#`KYi5hlLDcwUhB;@)<5prFW zz&lBCtaQ(`5~9eV#w{L)PX$DwbWzkCA`U6GenB87i{L;KKq_IxK&=SGm+S=8K2;pT2q!S)13$%;zksJH z!x8C(!W$A1cSccKMtD4#DX2uDkkQ(LB#z7Ye?g>Uyl^zLlvKAnNCEnW8 z0s(Ig`OFF8@zrFv{Go!=(S|FPOYxBV+9V zzhxsC#l+igXX>GQS#`rZsU?G~9pA$J&-^vFUiqU4V0haVWG4=jj7`!ydXVaxjd){l zt?puJn~fE-TTXoUODM4oYj&~vwmZ)L^?Nw>_0QAT_Z*x5)-SQ<-9NVMbMA_)lkR)U z1wC8j@W~f>@z4{D53ObEx+}T$$^d?Bo>H7V&Vlc(cmbn-~J)iz5gf9i(z}M zwxTFrwdb0dnK@_Ra;iL;X0yre-MiVbW5+8pB6>Z&k3W2)BEKZ&zmw0=71H*03w5r{ z{qlvVPpI1)EGD{vV_oA>&_6h7$}h6$pBnT$M!d=qt#at9@6hhm2tHOD=dHDY&egg^ zKq?VVAO~z zeTs-Ya=;@Kk6dk#3D62QPw6ErC`8qPwgC`XQR-U4m`lhK>{$tkMY>=C_u7JTp@32a zfT!~$v`m+P(v>45s|u8h$|?khB1Hc?VTnYg6T9Ez)qyf;x1&Lk0_zQlO3+GUoGDqC zV7-=7p_L}HMaXr5uD~gDDHG|KT2iBMmb@)uZ9hhjAa@yPDfh!UPns8`Sxy`!RI9bl z!e@*n%`%FjV0dTblK+xgC2N`?>C-+sLO+bVd=2`wkKf4s~9mX*D_{q?I^XRA9{rtDN?vi(N(^Vf` z8MM62&3oSonUf+2rj0Eyw!nMG>Y+8f_okm>{$R$R{q>)*;0|!ZC$6A&+k1HFiI^Av z;P+^qIJh!+5t6a1Z)Wz%2id%OI}bkdMXuZaZVns|i^1qMw{Y^2Z=eT;Y3>h{y0Zq` zBdDHx_Hl+Uzpj52v*&5j0}--%D1esU^P6+0%(prI&A(>PAN}8qUV97Me(BeVM_1Oc z3~sxEbn4jh`_CTavFGmPtB>Brf#c7yX>teez5ZvoZu`5@M~`#xum3C0{_a0#|EK?u zVsVyDAN_f@|H^N0;m`gm^(_~_Y|yg%t~<~9J`db^=Xw3E4Gex*w=_-9$b`HS_U%_n zl>AD+m($bJ96x^ihZ+>grLvY4^>?B-AdH@@75YjGh3N7(D`{Yal-=fl&dDr*i1q^9 zJHBWeON4{kCdb%Y3iPlqqgzC@8VprH`M7SVR>s*v*{ z78GJt0g;1TB9h>QLfek(iP(S%t|n;|P8ZnW6q!chHF$!}IV#hJMJQMF(xH9SdGAy? z&T+zYTs(c~Qi{Ig*FIL(8MKPZe3uX+=SyL3DBues-dM*p^CntHoezL7#j#q4Ai7Fi zA&z2NSsE6yrC0NP`x15{&2rK#BQBW~t#!xj(P%U&OhJ+)BuRqSia3rsx)umsN7ZVj zlZD{DXZ&rKv+&~bMR0UrlEYIg02k}9#t>-@2=df0zAmsU&4YW;wE<+w(oB8#OGI0? zGX3ygsh2U3B?5oRAke@X}+%Tt2fxq~#ePg-K$t#K(*s_E9 z=bqq}EAL>}-iJ6ky$|Os)wP?L-~A{msgO<`4ZEFZ9lJL`di-FY;Mg|inSS^sqE(Bm zy6HVDoGoPtyzF@|j(_7XdGSC0OGdAHD_j5WuMrK5oc29YNtN{Q9-Q~QaQF$n_2lQc z|Cuk~yyNPN-^shL`2?#MJSV>NX?Fk4uW{h+|BTIAZ1~_$v;9|ogA0E0e`4^$OOZ+C z2fjEwaOa&oaQE-?+rNKz`IDpk_MLZf&+f;0;3%D+J#ZA#qYrTBop*B2<43#q@4N4L zjEQ#r5f9D7iEsTT-|Ct0{lYDGp7M9E#MT}U-FeGD1mKcS+y&V~{OV`-Fu&(6c4aT0 z?KqXwkwf3&l1u&&fFJphe;xk3<<1qK|CJgy^=_ZoDfsg7<4jLa^Wrx@g%EeXYG7pN z&VLsET=Pq3F)9*0rlDT$Cy?TL~Wid<$0C%d=q z%WzTUVju$ZV8O?}T-@o*uth0WZG#YN;BJR8oxk^b0`WS~L zrqT`j>k&{d?Hh79thb@BsQn?4n!+1|*T}X-xja5vYMgVWrYL-v3!n6pSbL4qeHa|xsNu>j7^P<35gVqt%N)@SP--WPJ3Ze*OOkZw8tyZHb3`LPq zT{FVWUq8>l1#1ve_w8F+tmMXUIO|BN0ce~!&|uxxpiSunn3X|p&m8$a*X{iKG@g6} zQ38Pz-*|#G@4LSHXx1Q3;ciNgA0!$cCp&t8nFPj1H&97d4xF0X{TRvU1S6MTcMe*D zS!RyB#OTBZHePV`xt~!)I6iXe_-N_a?=&NoP7}HJ6gDHBU!XcNf^96YZ{ZLJPrkqn zSH7D|ufK!mpE$;!ef{&?@SYu9xbq`CdCxv({^fsS%ZILH=<@#j7(F;l)EH&)#b>y9 z<2B4Srg-StFLTo+?`LTH)fDs7$hP&|S)$T@T+GcddevL{fZ2i1f01}3X7cSHLa0-W za>|RZBVYXs7WY2K#yftV$y-0X>>_QYEjKAozVuy=&Fo^!Ud5($mvYg%E6JvgaO9p( zv+LMF1~zSD`0^WA_rAY%)*|j#YP++CC29ZtraOL#n@Vu<_+7jCT9rT{j%qO zrMH*9@n!D(XTQqhef#ohLba`K!9eEh@ZsrOU;a9Y6uBr~!{%2q!N)2hm!KnJIIC z3y?{O@|QIat&r}Ek-^m@1ajQq8xmrHFtUs{@i1tDyD8WBn!$TZF)MM#lMFa?m5}(C z7(@}m>x2tpX|Ei@XngFzNt9Kk21b<$E3zz9bf_}b)`%jEh)N5y>%5u0+SuN%AxkBy zmLWIYOrA)_6fP&0akpyRoR{Q2?S9jkyeprIZ+hu=YgWg@i^k7 zf>Hq(dG9dBVhV$fG_^A5?Nm|&r4(tJqLk_jQIk@3Y=a|LT}XOjk?Q17AGKJo46Q&g zc)ar@)v)NDJkny*C8MOr4p7^$wX=xLKKUT>qKj!fc0Utu3-R;m(HZJnCi@mKyEsQY zygajG_Nj*$yy$Wk55BC&lQ;h~&;8|7)V}g>x#;IU(Km{zuGvUq{|l(;Sr+UJ!}V1xrgN;h{bS5N z`5@`B13dGu{xR9fqg2;y#1%R5*aV|jc7elefN)bE8bVYErrRLnm@veho1yI+c#g&B@uX86h9<>7^l zG#%&U$&*y8=jRfeot-6HVW-z80H*W1xhFow>OcK!vh7KD{-65yJiL&RW&MDu(Rle* zc(M6n(tUqLo~F#EDeEc~pm;?d`|K{Tnq<%ZH`adp$+KWw+PVVYO}eF5yVCP-DFjw{ zR%H9jaZkG>T8NcOaLcebUlu`^CqF?b_%qUg^_}N(fu@~;664$B5 z13dP^eHfE*>-%papBm&V_uR{6Z`;Ud^mlpWcRtJJt0UHb_{TdRi2A0BSa{(nc1&#N ziIYz;|M>kp^#{L+Z7r7hKw*Dd2VUglgZGB<;f?R)qQCpUG4uGt*i5nEqwnjoGfTD; z-~BQ(PkfgPf9jJ=-tvL&Q4|vL3{j2%TX}uLK$WC?6! zLTHs%;c-P$YHbP``igv+0_+La=u8FOi;-YJ8riXYpZH#kneU$PH{Ir->dV}g68ve8 z%E}_e*kR)WWi^@vRM52uDG*A8lwBRNT8u1+L{bWB!&u0OoLD3!10;IDj;HWJ2rH%N zT9bPkxZ9(opkYyDMM||&?a>W+vLZ(-NgTyJ_Y)ocl(iOPLjtXeBAg5Q8>JM+6k+_N zHCpLq_UQf@V?VoKjKNxqcMfYU^?I#;WL1ub8vBkD4cE{E6=XT;an7;(z$09`xtr&4 z?7q*TR$tA+?yqsdkNiBl9z4M%H%@T)i~oal@BfK#Wp-dM4;_7wi>C#v-}`X{g5zI% zl2x}{+^1!6d4`Chj-JA18Pkt^o$A^x>^krW8?LySwPRbBz0CP%A4euN2DV&$#xJt5 z1yhHgryy zR2k*u;&H}D)-WM2fAhD``7u}8P9^ZY{A|~*UHs|?Zs~je_7+9aD`ttF z`|6#1alghd;m@F>6RvP!*>_=~ci#5_7ur8BDH88J*7~5~ zXoDFWz>9aT1SsW5#)Ywma{-jJ!Hc!71Bk43SZhL8kqx5^QAivPVI+nCY_I`P9RHT4 zm=_FewbU;t@c6*$wD(6_d>&jW-g`vd;afmn_8bj_L|jUMA|h~$bQV@GJfwnrHY$Nj z(A5mzG>3E&vh&8u<_>4M-G+kio(DRIpu4Q0s?GNF^R0U1|$>bL$U z=AU@rtl6IcB64>A=ASUIwJUT!_RYU$Zr3Ah`mw)HWmUgGBP&`Qp5DuzV^5P<$;N0E z{_)2!vnOC^gtfPRl7i;+w^1KV(jW$UN>-McJ~AP_Fea| zIoB=AvJT^NPFM5i2r`y}ilrKv$;nB^#>QUOdvG?+q_cUw>({SmaB%PyJ=Tpz<5go? z&gXf%z{Q8LjPt(3kc8+H*I``RV8z-tSO`CNHUJxUD&XQvL2ZY1X)`ho=NyI0!?@gN zoVR%I0$WljEGDobE|dt`CfK}8t<7W!fXWx(%eHA9x{ACHP9ASVlt02Fha5f&ZP7x5 zT_}56Vvj4r&)i~Ih>K=~TNFg&mS{9Y_M-zEVP^$uz#(Grb2=0!W)f-+S#$VljjV@u zXH;NWa005XBM_F_<0a$`0S!&G$|46Hs*zv@QX-R}@(5SWkw%C6NidZZA|;k_xJ{eUkq+YvV%-CRL|6L~e%1vp2thMjpk5v5j(AFN zlAD|;3dd1Mi4u~mNQt5dt#ya}DNI3OELthzIE>2Lg0-ZQ^o+Fn+oX*# z?7RnkCz@7DwOUybxGX$-nCgacbUo?lH17NUXSnUEAMGw&U;7NRb``^wMfBF&NNNf> zzn{w5O{h4*%+Bz&C;ptB#RRM0^&@!aIDYR_OuXYVq*DEhy|tk?=g?kkbDrtFyEwF_ z%3Ch~aNmBrB4_HmUuJN}Ra94RJpGl?>``Wq?PGG?HmZYTuiA;lrA=f{d$Y@PWKTM= zwt&e46`{5QEpW|6RDI~IpVvCW)ZAg7*z+9(f@VI)1!LE7;HiwtpeKIhS+-tX zWzQe|KONEZIbH23&2_)~MP{FTkhv!xWaG#GK1q+od}i?k2WMX5(Eg_w&jbSpPN17j z;_)@CzV$;yBjc!~ibz3kWfN@U8s-hhiK1r5!5bksPCG9M7Ir^QlPuUiPZjm zXJIOvq=g8bK~~sO`{F}pict8n(n!Y=8Ce`2uY8#$Q(l1+m=|&x3JWc`LLgL#_!n`h z!O2T^k}t~_t;e-M4u!pv8mM|I!xltsuXdGvQfx%5nZMzn2{VB zg~btxxP3tBG*t?ZME1P*VgC!86Y02<=~6Z&bihg**mi3lLZM<>w5TTi8WiUYf*`zY zrcH!^f%;&%KzppSWO-P?I%B5tGn6C=#u%E7CP^ivyW1sMVtzX=RHY_QM0&>>Tm7QBEFD*?QF&#~*)&`sQtc zy8XtVa@nQVGB^-KqQ}1SB&*+hB}*h=!GfDqn0@jgR8rxkXTOWyc`a|I{)XzLMGUAas`OIlc%wIQ{1&*3N8cl>!y3_i_QrcI<||WC--pd(QmRQPZ(`_uGoAr!2FLLYw5?x%eh!=+J9bbM1#@$AoIH7wHEY%|JUsl0?boVRtIh~q&a|yv zyY>xvOm){m1GEPrf)$G;{&2!+D7CFnP%;SoTE?Cid;8_U`Lhc;N_R*IgJsS3M&N4~Qsc z>Y;myYePK#;y1bUwvRJD*cHs0R+AIo_&lp_{s2P*D?5Lj_w0G*n`l*G!-ZF&*H>P% z6NZdpY}P_0ReaV$t`yBL1iBt$n;A%fs>Ha=pa+uB-K3(IT_bSex+}PF-4$5>QC>Ry z6!kqXu$X7(G$LB^f#KxCU#IrtKf}UHdl>lsGYoCNlInp5J8%2@IBTeHzL;b8-c4m< z9nbylKWAX;rL243Pb`H%04(l#h9md<4<>H@0HfEw9RbXI|9%E9x}3fL{r|_>+doEq z%MRwBdy*sf-i;8Fkt=Ux^{pRy!z@0VHf?%U`ijog2ECN6S+!~v)oS$z!a!`>w(Yz- zhms_DMS;}oY3qw-=m#173*X8Oj6M1P-m^4yuKPGWk0AQLVp{AQI;T<87hfEv;-s$UyhL!5>*6yvx`Em ziSWB9vIOnJ)!6_6bjXrb?8N)zrAZTt_S{)wbR7IJHn`WWR zuwJX9ON~chf0man_CzwXw5(B>W5?Yp_+!nZJf{X1}lB|o`HJU+O5(KH1ozWXJN$$5D8Np5=2FLpqSw}un< ze}#PN2y5T>38I1JW0SeLV?6cf7dW!#akg%M8(VhVh>k0-@fky6TTNWnf-~%kswGIR z$Y&NQ7FtNHDP~R*4~@QJyQ75SqV-pC;@;2q#A%-2W*YNU_8w&0aq#n>V)UxFu=VHvDaHKs8w#{Q$XWV9Z(Fu(`JsLflu~Tl zw(Yz?%LNx)@P=j4WFJWBSx97Ww{Iu6L-bv}F9kfkV(s(-^L#4~8os)tL|4Ubv zJjO1#rnJQlWXN0-FC@r9ArzQe3p|)OM|v56iC0J~anfQ`7PLvu2SDRwiKMzfuopE- zA;b6ukE0+~Nyoj@&hqQ+KJ2dK0`CRRdvwXrI1fr`vOL3>f=EXsaTS3e%d#?8MN_ZU zNsV^fwwGQDuL@4lwlA|4r~G7vHI)WamJ)`Isub^QC(_8%r19^=?ozt8xM z%TGMsS&n}FFPWP=%E1wM*UdjqqyjV5*#82@zVTN~yye~0HZGsNA3D67yZ`*3GkbUs zmtXS%)^EM~yhk8Ekdtkt5(K&G%y}|GD`XO3(j42$@c19dJ}tiZ)EODWGw!QWM}ibVF)X92?m@FJIt zHkR^iOBVy@EJ}tPmfU7UI-*`3peS;3Q(&E?kOeA=iKXl*L==cP>Ex^wMHss%tX5jUU>RhAYfD*{#idllq2n z7GHRtcy!GVW}nj5DeDx@9=QmLxsx>ZzW@TVsUyrh_8qG0F9ac&ed=Mrqmmkjzwkd8 zz2k98R{-|ag|y7Z$OA%NknFtZzE zgs+bV3vvl2e7g&&48C*Hb${l|gj!cJ9NrVFN+%$%;s?Tr!v}YRAOMeco=MQgfS(tL z5F7|b;Btv=DtuER25oo`QV#<@)C)u&zW~xoa2`_xL2f874EZm<;*irX;&l^0dbj+e#8 zBK6upa2fSY9!t%UUs6i!OU+89N>LQFS}AcHmnpmb;KeydVG5jcXPik3CDB8bPFwG` zbyt!VO|%*gR%zi`m?;<@uhJ@8gul1@tK7K$W>i$iHjfhx_0!$yiNnl2c0W%y_i*Ef z{sHwkXlAA!`Wm`A$m%5vi?xOaAGnLTqc8E6xBnbhUjCjR>Jx@H23;S(HW$z8_W4|s zc-0WzS)!2vqR~3(kr^s$M$TR5;(h3Iau(BEBt3qZ;^Yxf8dV#>o0nM%=RJC0nA(O5 zz(cZXEo*N77<12j54>mO^6NSN&CjDMHP(ILC&*47!#l_L_5Cf@E>Eef-o)CqA*03F zf@EwmjG1-B#yftV=Ape**I$T?DhywK14r)tEb-_n*4+NFH{2prtJPS$cI_)#7Wjj3 z+PqrZ+O=ytqTAQX-SfHvF3Xc{m%;r$oG%G^EB&O4?|_~5V&{8jKs^AXZ`8EJjv=r8 zUvQ0spofvs7~XiCvUn+wmXQ0>W_7Hi%~Y>c<(&H=%sl zePqi(xoWvcS|B0ZmvXFAii35H<0u3Lm|6RMSDMHaKm=h)Co}t3$-S z3wjgjO0Bi>57tv$-&!^NuuYf`CW|r;fFz!@9(A1rN0H zlv<@0TuvT}JfpA$NgNYJ5s{9lR-l!(LT-$ZE3RLsN|TSG2(L9oo>LTo4sJ7dS(f3v zqf)Jez`e8BMy|P#liz)oRX1Nky*k3~{f}_vg>S<;hY*g%*@B_yI0Kt6=H%XI7^$sd z?7CYxcF&`%{YbwvXmQUjroR7O_N|iKcKfd)g(90e%FN^6W%BJG>|+EL8#8?G{=1M4 zu7BH4QmMZ_M0Va9q^=<23eK1_W|b5(i^Rh<8V6sXz9E3W%Gyzi`6jBGAS2cH*tXTc zrY%gXL4NWm`NAx&)xc&cLV&JR$Wq7Ru^DEL%+M5*3~b)Uzy;e`c>c+kH7@ejGH}u5 zxFQDu>G8vyxc|!xU3f_V?XxF4?C@z>gj$^tKBd8X)DkU_5Q6%K3)uYQ|A43euU{q} zS;dy0_(vT8{YKn|hlfd$q*HMCa>he%^fAgCepJ*Q6o@|7#V^sWbnLYqo3mIlR`Pu` zXU8gCN-?AqJu{#H8iYzv2Oun^t_0Mll5Y9#^(Vr`3O;ppe=?d%*Oh=@_Mpc+DF?u6I@zSAVowJ#T3>6 z9w{W1xLyjSf@4WaK{IWlRA6Pa)+9-#M?)L_Qmxg<^DMZClwJ-}N|4*jx^x=~1WA%$ zt?l%Rw4Y0B-M4l*=O~JTm+t-?7k~WY%UBwzgXq~?N30W$&F%-@Ml?Lez(kWg7c9Q8 zi^u zSxy|^!z1_qIjbiw;MRBlgV)u`!sQvFwD-z5!KMv34R9&un$$K2ySS8$ z7TZ`LpP8XpSU~7tTa1Q=iAN_9Q5=A{Qh4i_Ixxq=Oh)F1(IdkQtr=(XEu&m|X;&X~ z_^WfwKl?yWnjoSwsPar`-eDvENn*`WIg|Pq(+Khl)ooDtzpbg&?XDN+7MEw%VW<73eSy zbL-z9##CMer<0dRCrTRLhub-URb{V&4C5fH3#5rrRx6T*Jv*EoSCk%>e zu$CjyLU+JqL5gr1p+Ji`fDu#>A(tzC=a`gr3AxFLRD@OuLU@`*6PsHqakZ1k+a3cM zThL4!RFZ1AGS(4F>CR`N{TT_FKH)PH#}%?XEdh^QHa7C2YpWNX7V!2|s9T`u@o1$> z$5I(|C;|gxt))__ATNF|kNwC0#x;NECy-J9Vmtbliq6;f4K=vh5>3&#J+-%sulxOml(Nw{=}2 z2lhSA;}74>j?3P``#<_mUw0=8?;Ju${hmVa`w^x0xT3%nDK>4y{PH{ z*|9_D`XKShDx%HX5mM4T_#%xLU%=$^*j9rh2cP5Q;f&1HiE33Qwr^wAO;>WsMQhMY zg1A}>1BW(bX|wHWwd|!7|z;Ke-Q4|c9Vp^hqT_p z72rWRiMJuB%nB2lm94-E+ll^n;lV-;fcIfsB|Rq}t5VD;R$bRXXbX{tOmr4vUvUT} z@I_!rL<|@ZDY(c(L|{Hz<(pFlk(N!vBOZ}~Xq8v&^|IVif?MTKb1JYkNf?FMBKV(@ zGM7dOaIpm`I$cG!YKU5K05VeGv_mijCB!W=}0jg^E7Rtl_rX! zQ2uExd7gJd>U5-0x~woL+s6;Su*jir-pgelcnbq-x&dg-Loe~{@BFVcUfPY+@$xPt zYmho-!$*Ifkt;vI;Kds{i}``i{}*0x$GPRB{~wr}<>cevX4Q@FM%M?iw&2-k?qlDJ zk8tfxA7gUOw%6^6!W#oBL;yG!I-w}?FsdzW=c4>vAth!ZLl4#Q-jbg@imnaPIPg5J zqxdo`t9ubqkqNr zU-=EZvlI(+?Ell>Wq9XX8Nc>cq>kQPotA8AnzFdKcus|huhjO#o+SH5dtUV~e*ItE zx$Gq6m;Bki%q@U6!_|8z>~-lg|qdeYL{E zUP*nkfdPw`U}J+2u()4f8r}CV8i4T~3MEx{d?#%;tgm!y8DU6d1tk^6XC2p98;BSe zN)BV4fDl+;V7(#IF;4i7mD<<>=M7qFq9{R?1%}=`v@s*5k? zi7!5iG;<8DUCrTp?&6vM`yXK!7eX)43c{M8JMhds{RnfrzRBb*9|R%T^&kEPGZ$^( z=J)&qPJZW0$XcDToo~Ylc=VCGdF+wTaou%4!X;PUPJLkfb%<7c2cRLl4a-6)q|(T; za8V}Jz{Zrv!W9|C^fazmB%eBj9vml49mfx}*!O(K$;DAbTw~1@+t_&RWo)_jLN@Na zfK^-95mzGOdUe^Z%p7a+?88%JEyJcA!>qkvi0VLhaW~CHidIfBH%)%x&^ZZzy(zf- zfBQX>$#q17BMe@28F-kw|I1X@Y$O?-=;)L5z)+_wQ%Hrb1%RcJ3M#1rq3%Q_6_QnJ zP)P+D#Z*>rKqXaV6f>~-Vp@mxl;xzFnJ2zYWnw)izVk(fF5bz}ul)tOK14J)f>4S# zw{kq7HQxK>7dWrNRusjX&-+94yel#;owjIK{@E#Bq|-IzIz^0ShDe8TDcfS5!gGzEUhBj(!f8W9+qpwq*RIAkgV%hL7~M+7mi7ht-JtWQcX z<4T}o!s7*y6~<9!z!0~h09;D{vP~Rbc+82I{a+6bqb;{v^teNt2qzs*T8e4S{;x}1 z2GJmFyCmgv8BO;|j zqjBMKn)w3t${<=t9W6^c{apw_;c|q4D2h9oJqS-;WF?I&`m*ALpd&RovXnlx{fA^nKtXsoaCTSf#z{FeML)x0>JKy>f>a`)Rf6Gsxen3~v z`#5f6`0 ztyf7#hR)a?4d9GLDoLI@UV3r{TR1lE7-n#EWxMm-?#F4&Tk?U6*mCJG&;HJ@aq|AJ zoK=dh$8*^~{T)WGxRI0J`z8Zhwv&u^lZ}h{8KxfjCiV538QT8;XYaq`<+$$ie*AsT znX>Knj@|)wuy>IZDTykUMLCWX%eMS=Y)7#jM|PZ8F0tWn;@J86XGgK)k|<6j$Cl(u zs#6k4QLJDQD@cF@L3H2(x3?`bbI$qwab{D&}r$%+ALMtg(#+zQ3^yzOG%^wjMlgbNoPTh+JTL7yZcRX9p#;pOY)3()z{LR^6b|4B9H=R$ znL~BLDG%09%S~1wBS+tuqT7a57L~{>r$;7E7h(bfo(o`9rqQ|_7rp?r=*vH7P8>QX2ETgRPj_p99y5DlC+%U&r6YRtfvXQ2uR`> zYfWbFuZ5GrC{p|xh|Lgz! ztjY=i#WkB*_e1}h(%LP|=s6yF=+mrObt#u#@xC|x$K4EE_Wt+(K<~A;<9Bqi|IdG) zRUi0qx-PpOfaiYYBdq(Of6e$)50YQGj-hw{(`+4k{@_=b-M5P?fA8-zbGyBNvV*=G z--XxS&FlZ`cUb*{A0yW@i12;Z&OF!uDfDXdsW`?l?;1TH43 zoid}SK1Lq7m*H>SjS!OF>+WFijvpYIn`UnR9y%_*COy6{(S5~@`0Xy#uQobNG&xE% zK1w`2j)^MBT#;P=3i2z~xwh-`z~!ul)|!3$_GMtDc`Oxn*xTFtrk1YG1D8_)mzHu* zY8Gb!ZR$@o*cbz*t}RKOOl^|hebs@BZX`_C6QE7{ev>rxE^a*rtrI{vP}9Wh#6(za zk%`Pwr!kQDi7UeD^DpEEbK+UFZwGxrwx|Ec~t0_#*h+hO(-Msnwi`^G3bInIn3R&EU;7+ASKLHy z)keqaq>M;1H^VFc<==79ul)(-!>=*?;Fs9&BR`K#5}y5~4|B!u{Vf2m{?V_q>ir+( z)j#&F|yYKlo*~ef&SWc3zo=b2cTu*OS4GPEctQ zvW^mz@4#zPnZwI3@8UN%9kKtVNqk?jW?LuuQd)l02B8)*CrNpR@uwf8+;cNMEAzB< zhD^QmG%8=DwBdsEX2meFdpA>$-9!1vYb3KX@WJqzWz6?c-Id$&dtHSRF3VZ z_xi;>eylO*>Kvw8S+axaJa9Sn*tc(AmQKIeI9*Efo7K^D9=I&QdM_YO>x}{pNeYcp zQq!D(sQbH}f`)DUQSVmC*b3(P#u(dh#I+(br4yOvq2Y2XwR97+t_yD)J7`JEK+2^) zr+JQUqcw{NQd6}yfk;KTR@szY0fM?mOVhrEX$p1f%v*QxwbJQ6gcgqF2}%D>v5!tC z)C7{E#;>}GTPlghxbB-oq63Zfz>5?H(4IjVR}OL7l7^;6s|4S8Bwmb^5-S9O3D830 zS*OJiQXs4%k#RPiTWg7J4JCaFqC}N4RXyiS>{Niobs2>!Pv{9Osg{Mrb$Kd(+|!4(av`Q`7>ap9E!%P-|@uERt%OdO%Y9OKVCjPQNhw_c8kYSc~~p*DV!;`(iby#ojpkjzdq_43n{ zHeS?lBd(XC(#JB)p>>Q+Vn(01pPs93VeY^ys6rcFdneJ<7}I;6XVXvp8ndsz>=>PmtN2D`|f7wj=Nefn57N|Z~p)$s&V4mUn1xkpzD%(>CQTNLl^J%t(Q_8IY!vG z!m)d6H&a-%krNNxP1lvT5Oj36o+Byo3T;q0@2Yw>W6z#FZ+IOC4jg#X*_ZR9G2|jJ zV^R9H7GN98CUZ%|`wYY*d zu8fnF5}VjKiA-lZ=CO3{bM?KDTCLIwbZtv8IZ2`^muJyhrvhn(6oSAHG9m6#U)M!5 za8eQZe6VxkfxFMTMASUWhhImR=KwhPSAW#<8`=Na|4KYPfr)Dz`l~DcL+T* zMent5NBRNnTemwgb-qMt-BzR*vub^+zyK6|7P3>H9`wDsn z3rl;)$;KVd$w$9NZeTSBP7Jd7vM$1$!o(4W{^q~8fEIw)o*!rZMV+Sr2$xe*IZjR- zWp&?XPEH(dY%&NLy5lZRJp5Hmt-5fRf{=k*-%rQZ?TkEfFJn(Vm|mY;`Rt91(z>lo z?S8KH)C7Bc5wVF51T&@m`1V9W%xvZdiw1Dv)+hV=6 zqeCg&P(0se6c~=DP(a>N~P)eeOD4vGjqtpp9NikO&C6a=mEfhx&z@COh>>a8 z%Eu#?34skVfo?*Kuo54ih!{%^&j$E}22Cw;t30Gp6ljZfe_Sg<5XL@p?TNZoUz z3ZCcVdqMWKaotI3;dezeJX-`Z1us={xtx2psky6Co+U{V!Z1wRsAa}9RjL&Vh2p{} zfU_Lq&pz_TR*iI9qTY77ZxN`otemn>b15rPrgYWsZLN&)M>G zzfEz?7J6@Z7vK5$yAV<^bVqA^z=?;xOz*X~;}zRUW+zd(B7TR{Zunh&#N`?C%e@Fc z`2fAw-my>zP^&Qh+@oCnJD&w0*SnHKfBPxcedJ#wl;Y$=U*_`P{Tq;y$>$zr<$HdJ z;<~M@`^Ycw$|wIV!R0?lke6Kgwlm8tif5)6f94^&uX_)#JwMJx*EdQc2S4}U*z^;> zvfw=@56yDzdsZ*G&cd3F4B!9vTz&gp?Arf0v5x5NSlN=_HE{EL7=QLrifc9!_6#lx zVES&l6B9)ayjVkV-Bx_wn0Qv^a@ZtB%oBLGZ@U~_t#I<&U#91p+ul$~>O5%KbI#W} zJ3GtN)D#^Z9p_K*o5{E|S+^_zEEchlby=*GR0k}!!H!tlWKflse6qXZda1xPF)yMi zBEYovVT)`VDIiK~5mGybgS3dG3`mofh`?nGg=u$D;J}ekplT_#E}ZkN5Dk!Gz4Q*x zq_D0Iu1o{8)U_UR;yL8xv&fk}$diw`*3h(shHOw#PH$q7R-lZ)cowZJaV{pPIOoaHc=;aYs5XCj(r0P69tVJNR&%D0c`DI5T6jCUn zIC3SSB%wSv%k1nlN-9dFcET`^lB!`?Cj_}LN3~jQNzYxt0-nLJX~5$f|Mf`X$uW{7 z{SNver7c&YawS)y8eD@6LV}(_g6@6>-v0flLWy{4jNa?+VDg2XbY5^J-P>=VYy0*1 zZJnvZY?(YK7^&FD(642m*SpzLoAP-^S>79%1x}`>}~W>#tV#s27N`Z*QHb9DW0gLr=2RY#k@_d2N>9HvgCN-*?19E*>7bOj0pM!d7 zNRJJK^P~|5BXQkD5=;O}3*wx?kEGil;||a$i!u@;(=tYN8lU;?z%8M`5^z?U8o z5x(%yBFRp5EMh{N!xteSFeD9e`D@@puP(n6ZBSyH!B9#K+bE}9`uB1)xp*YQ*DG_o$~yO|J?Qj!ZpX6I%p z6bg+t#CeI(b#~`18y0NXPEuTx9;e4d)K4yPckB}*nzkMfuTWxaIAVDJ6dN{Jq$fGL zuS`5ON^BInzkNLGdfD85?s=1cgE&a}_=h zT$%yOX)e;Ieodq^ejQ}kOq|)mo@Aw_Cd0anrEwiej_Yxgq-(iOJB_Su3UPEGNk$Uw zX{W6)P5bGkWg$(An$$*V4N8LzQ{WV(x)v9ig0un?xiXX~Sd1`8-*pX1BhbpY+@ZFO z*h_u|D?#|Zq*WXTz+%VVSRa(3VXbc+K=Bgi@gf9hWwP>;vhGEF&}!w(g+iJ-5onB|JQwDHv7E{aJ^oC<*jZEc;cAf(Q?rQ5FuHP&^R zrBWMlT*F$Mno*rW#m8EzC#Q%;%cx>IW^(k6;})YqMfMUDf z@-sA172)|LvlC43d6t#$`;o>EyVQ=Jn}TlV5L_D{!D~M~eH~4XQa-SkHFy2Qk}QQT z&&*>Rat%SY5|pQ6wq4tYv3>Z(4qo{8KZYuGaKSHrlIii9bH+~62o4F#lSogXq(mzB zSXax8f9G4Qxb6KM+C53JGoXJ>5t9n!YsU|xtCfb=%=~iT@iH5>cc1J^hJQS$`T+{AIr&*~VkO@K5(q#>0qZ$8T#GfIq;(Id#^c>2f*{^o@PyzhclylwMJ z=j3axixDvH15%zx7`S%kB#BZzK~pA?ZGe|LOVbEiv;;v&H5E&q33!=)=?J-@Zo+|( zzU$w~v9J9lyis;WYgXLx{a_3yzbx=`9%~1N2~-smN3_Wk2;Qv~>k|fkb(dp*#N>FaG+E0T6cg6VJ_3o2iiN?xZ?=2!tRg zx{jY+|MA~&(I@_}W!E|`yo#B9FHuXIu2By+QzeB`UF{ih#W9DLOhW+rQN^enF=)p6mKRE7^TG`Nm$KYus3Ty_`V ze&KFzx%4gd)o&%`ry5EU3LR9C{VA!nbfYKG8qvE6)eK}SFN}bIbb;W z$kWs&N9o#r6DsE->7CeLp!`&fE*n{=vVA4P4}F<|Ti@4Y>R9(dYL3GYv~9eY+U(?a z{e*Qcm=a^mTe7c*4H1cK`nU)M~Y5ExUK`Ubb!f-VNh~mad{@Fe}ZkHV&Bd-{VPy(p$b4Gr2uNh&-+B8`ZOlOyFoE-a!3Uyr;`37m zCglQBX$Y#$4q4HtL1iTf*YP8&7MTKJlbXO<&!p|q!gV60fXH|jFG;mA(l{Lst|RD+ zwg16aXZ{C!CwHcY;o=9hbmb(^D2z(Ggp|9pw9=K95^2y<6MG3YFGg645(3Y9NFfOE z(IjXz66rdL=6zs30h&|=ol0=(fU@!VxW5w!gxT^WwOR#ZEK(|RVZp@-)aAOuqn75uv;t=fEUsO#7Q!IJ7?S~*Wl^xB z&#>peeVmtn_h)I_d`aq$^2SE{g;#R;?>Vxe{~*Wj{VaWjo#N$(4^Wwov2l%B4SKJCCu5I) zgW_Nx63gTZPh|UW>}#K8%@2MIZ=TUx_f@xW;(phvT^T-1u74#$p1S?}@ZbMW*8lL& zx3oZmYjb|}Pkti>F1=Ka9i%!v!|N~2a^k@+(0|+a)7i7oCD_!eoT2=PlMjEDptFyT z3$Ns*$4;}lqc~#ffu-cSKfLj$?$8K@k12aJPK_drH+77S3s#Vq`fCcM^8vse~zyH zJUv52*4}bGTi*YDgw?~;Uc8q=P^P`NK&dkzU-SvWw4997=tR{79d*S7IYy3@89Q2G*9*HjaB%#)a+0bu4SV+N;lP0d?Af#DtXY%M(b2bT zzfZ-U%s;;6f|mMtGla$e=opuJ_E2j}X+!H`=liwT7Sxgf7F*9JvUWjsk*K@y*8gh) zF_x5ZK{%QfmjaCtPX1z=Ce@}`0)YbxDoXVzp1b3bRe{YJ^sEbo6Y2AHFp}XCld>Xp zQ@KnGoVIBDuBBSdiOiiBU!W!}wvd*aq!Zn0m6kWsJ2c~yYFtvsUI~}yZsSP&D(k(A z(iYED99-A$2&Zwe%A!-%u#f^H48j@`3C3zd6FNX+6`}P>M1s-^En{MlkRwN&vN5f$ zD+1&01CgW|Pr_iWV@B#eDmHED5=~uW)&&|NBy?^J>D}(*=X}}*@@P@R6Fyh2>}5@7 zfu5qvL&}FGv~iv+o>UlXP(oz@#bqmbBuR|t`;9E4tllWH?lLSbcbGvCkR-9Q{0~om z7eD#J6ZGBm9{R3*J6@@S(uNBtA3l4^*y@;7ANX;)FTaVIeJ`>0pZp7+`_&&o<%_KP zzK^1cZ5fy_QAA zmpbUX={@ZHiQ5P|y1DE>{`o>+5j8HBHi&De3vE38bKi$e61uiu&!(UH^(D$H zh7%8cnZaA%j|Eh$E>!b66%jmq|GNxaBp6TZw zrswKg@!RWNNUbG+;tf|Zwf6=3F1c>eeW*lbj*ac*qDwDM%fMAWzXv|NEeBNjbHh!+Oq%*^b(%p`&naq3e|Gl%CVMSQk=6~z+nTN6C0@22jdRA; zXc8~MtEe=XG2N~(Xlqw$uX_ zWzDrg%Nm#hP_gJP@FyGDL{^%tty|Wec|*`Scg<1dw8T^IP)a9Sqd+AB>j^xg(8^#H z_*!8Ucvhm7d#@A_DNU>lzV*;TQ`9*Up@~#N&V(owi82JnqbzIW2r<$U5tAqHwuwcd zQcoI*O~oRKNbqcc5e6eIei{u>|IcDD!lHzi1?$x{H3EUgu@y@CSYfE?ssj^Vfakd~ zP^7DA-jSCjLdUv>Ny|N1YO{n|RL1wi)T@Qe&VUV86 z%A@oBW#ZXsFdDzD6J4zkO^p%u3}gX@^QkA3#7k->=9kcn0i9@O#v{g$mkIKUfeoFY z6QmRws{nBFSdy`D(OiW>$){&Uo?2BC=1yN*uNwy*{Hs5v_xg8IO!JeDedRBag(8Eu zeV}FenSC!~q6!@sTuH5xaA?mIn=fBj);j*c-L!AMjNdF+I};B`$CX({9E@hH1C`lqd9cq6}sB`=_oa8q?&;XJh4)e(!f6BHGe}K-; z?eM2N=Dl9!)1Ukus)N_@u@B!#b$BPg^QZT6-3LC#o!bY2*4NK=?Af!2yYBiu?!Noq zaM#T{_}rK8;8z}4!H&zGl-1b91|M&i&at zew$A{{L9?@3-|Nzj$S@<^cp^T!KqiZX3d%fuHDPsr=Pre2Y)#4crR$WN6Y1M%PvKo z$@s!AZpZ)OPjml|{wTlq!V7O17}@zd+u8iDzQXN)c$nutaoy<|mzJx%H7%V)^UFt# zCL+6N6{)U65k@rWVN%+})JsBS8Wr2bzF=%BrfoRqX5@_#4e(UI16N>cG>q$N0;4oi z2=sL00&BEDL}}^8PuUFxl!1bPxUq}Q4<_wUkxdhxbv`kwDzO1Asnf(30#|-Ao~x^P zu>&H?I@U;P0V?e@0+f}+QfHk{I;DGbrgee5@iACpWzojqp|V70Ep)a63W-TILxJ!} zM2u&BjBsTmXV_;mQExOR*?V7we6L{TJ5)p1l+JXqiSbm>IsvAFS(hT6proRfltBo* zdcKjc)S?Q?Qv}j^#blqeazb7!Tm(cduAw}Szz@iU1){j-a*mq5OJd&ayO^HEQyx+Z zDwPWPd_DtLryF6<0NZ~4cX|0g{R}dfU;eMlTD;C)F8KN1W#sX1P}*=Ix!xg8KJry^ zgRAM-x}Bb@ZXp^!$>G2K6t#&FR^RpG6jrWpxtm_h0oX6KH{G=hyh4fU@k1D+5ys+` zI`B$uh#*8LuNAa3r?02EU7{&hND6@rB;A8~y83e@ks+?dn8Y$YQDb(Z#@uvF@5&;7 z_5ZzqOv@}`!Q-cY&vgSW2ef3M44B;Y1ZzL^(+#HKl4~-fw(Ji0*@r2uzmTA_hslu& z(__)1pk?~Cm+=Pe{>K>}wKfsRbV9z}}-~%6H58K)C@f>?T z{}|goyp5gnNS8nTjuwy zLc9C!e*?fZqxZur{ru=%H_^^Ye)jI8TyPiX-mUh6k8%ybHMeum>u_^B@XBBE3lHyr z-Jjuq{QgG)_-Om`%0QYu z_{qQi>$j9e`JG>0$6x-dPS*YM&%h_{ITPT*JRg2BPyf)YW2r~pHPnv@rt!=bZ8`7*E+Zy_qWhte7(OFxw4^(XidV;=)u5Gi}1cL4u(rc0p(+OBO z%}X65h`MQ>2UbLSOv00h*bwI|C;^c(pOaRgrA?Ef z89tdS@y@r}Ytmk;AQj~tCq6A1wpPbdw*h~kc28vY$KP4WD+czz|UpOO~ZsP z1tF=rMJW%ZJQAHysh075AEgx4TA5s!ZwL{W04(z#OR31^@-9y#2wNDLQ;qH`ZswBz z@M&K9t)F(N^)!>4)d^kOZ)D5Q{0=7{{tEp!znALCBaA(99|O01A4z476Aylo;<~Mr z)@^0oM}7{gH8cBO;ir+hN>i1SN9fvq6G8}%?VBOUOV(^#*!fhO7-9OQr&;y=A3g21kG?jIAIO$#S*F1| z&2e;Hc0DtDchR=_Vm7U~g!{hpIqtafpRuxc6T=e+8SGkn%7Y%d;|Cdg@>}@by@dT| z-rbYyTfxvBA0(O>Vf@*LDX!j3*gHsJ^+tvtxSQ@<-pj$`FR{9RE8T5N1A%QH{zS&O z05CjBXS#Ujp!;K8=c!9+!|8J57B7<>7;HTMvFirmx(_qF=Q%$A`3L#_;~XISy~_fZ|H@acEo1V8jgJT+6JTJ2$OZf@D@JQFR+Prv66`QxwtPii&z%?~}n zZ#?%AYO`hj`xo}}|6ck6e>-z0AK7~9byO;qQ|@26TwWA_{MH9|@~h8&i0YOfT5!D0 z<4lfyxq6#Dqo1K#{Xsr)$A|dq*PnXJI+!#rGUdAEYFy^suq|>Im)*H)Lb5fkh-Fol|t4-4=yor%~gijcwbu?Ju^~G`4L!jm<_48rzL+ zTj%}986$V!W%j%FUTZ#cE($Zy>^D8qe4_Y@wxvC&hMiH7LYdTWc6`&sPwe54QF;FN z#kW7|u?UOFNpdDzRPy70Gk`g`IUktUZmR#yVY(WrqyUtiokZS$0!VK*TWh zmm=8U8+Fjv{BVi{7ggVc@*mf2yLTyJm)uy?u{rUqk)%s*rr5JyE$~xK?xO7@TyPM- z7HFP*d{>gHFFO2fKF){@KIcEj010_#HYUXO%w4DOE|Q$%W1yCq)5rh1?8~&rX-+iX zhx|*8A8h-FI+CCx3Q%SHdaEzXc$@=wH=po3YP(bFD&qiVaJGA2MK00tM%U2D`O)L3 z{RHbprLk=v5<;^%TEN@R5MkEIacK4?Q#%TJS5LeY{iz z$a+K0yG+I$!+h@RS3|o`Wq}UjVx4B68=E+xb7_I* zSGS~Kh;PsDpOin|ZhGEvA2+J8Z$X;1WjUC9o{v<5zQ?1gHDzUG zhsn{h^;+XTI+?>Yif?*YtIIxJw=M)zZm2s$G5F7@9tmUnPX&+NGCzLsIxMs~ZGmrX zI$rj=`Iu4T`C9#f0tEagSs0f%SDRt=w$0weR zCi(6U}4K?eNT-l+O zHAPlWRS8|^P0NH2Thu6cun~QV%VL>op6c{X=cEINTFiR2GF&atf^3yFc$IrYVzf{N zPYeVvE+o$tO0LL&p<`n;jpO6f#56faj)}C&Bjw};?@1zruO^-*@JRAtYAKvk#(e2SnE@kg}IO959lo()D^(^5qk0UJe-V!goR;E*0tqXau z(^L_7!+TCS#a;30p>=9Dl>e;8W_s9bJ#IhH04sgq3sW=TxK@w7u(;VTJMO$*_YBcU zYPzWp%6?kpKhjAl;1!TEUXXyzoSdmc#%pY5Bj3Oa62MZ`{rs4+eVZ}VOKo2r`Qs9uS6+AAV9)2b{UTQ#diV3uj5lOs;PQ<4%=v>e zuIEj?rss-Z%f`!diNEVSu~T8{>$qIvxV);s8xOzc=1b@#h`h$}Y0Kq~l6(9g(z<4M zOshMAk)j*nn)6%Gf9hnt)m-V>b>o!4Sgp?$;n~UqhR^+@p!ZNN#n?<6!S7ee_Fc_f zh^>dsAK{-5xym1V707R6mFpf4l|AoCZx4U$_}&&a1t?6@@ zKYQxp^w%)Jz`#ttOV?f)%YQ)lZeIgW2mM3cM`O)A5YZ>G!p8L45Bh2 zl5GmG*oVc*^|2hteuEGR#)#ckU(UGWN%KCSNGcNb-r?nji3~8iG6zDrglppe&VwXK z>SRm{*U3;lBj$R8B}!H?cSj}Kuq;FJ56HhJq6Yt%Y>h1`FURY?zq+mn#{&nSEp>nH zM<2n7>&T08*5?akqx@UXF4D%5B6Et!j&Ii6pVm#wKi|yA(XUBdUmXCwi70I=wzbdd zzhkSN*(-rybh1V6^0(SXSp_Ult+gZ%6RUZF-YJK>L5O`=b%d$@01BEyh3 z1_s0s-`7YgI$y`UBW?Pj(4-Yz4tZRU{~T`L`67Ay{r%)n>p9mCrgtEU_qc6K2B3t* z%?d_J`$n)snb8avS%SB0pJF(~(>#y}8VUEHMByJCJgu=XaSt9@ zL0d#I@Wk6<35iEf8DqWqyL8;M|J%ZcCWf7W=bDE99I^>hul)*$gOwc?*FrAAFH%fy9fW^O!jg1yvC;-K;PJ+|S@~2Y`KW1kgtJjqC$ zF0mSnc_jU@cpxe72TbjdW!luNNs-Xlla)N5Jo{zEYe+id@z}7I?DlBG5UQK0iL7Nl zu#hjhj8hkmp3vAJ(_m;-VHs4Yn_}TbEoLz(oeo5(b<$HQC_-Vbz%3N82bB>b_X69U z?xZp{QoL-vqU#)>XP%haF|*23Kpijy&AhKKV@-C>XVNtm@fG@t0N<%DRe;m|Sqn^1 zXhq<7TJ*<{Fi_fjh#B*nwjm_GeZu%wK&H^5K73Ku=?np2;Zo;2u#l9~Ot3UE!M4y1 z8++0oYsjKFzZ{U^JAufr)cp_TXda^!1qV_!c< z(;n2}Z9mj--p{W+MX%AL^hrgSnlyNHblTRePRN*{>DJk9)$~T(vEPUUn_vpQsz`mw z^NHDbz)Ze52d1j%zX@q)H9p9%bkRZ9m|Z6LAb2b=nx2vF{jhEcA&?j51d8NGoXSAf}e~R(C_g@2nY0jY0tEs6)c0}XSM!?gH@3N z4~5u{Xma_>#axZT(w{NCz?!VaBkj#CS8ya0;#L)z23PD3Ryv79HriHI?Aos(Q4sCg zE8MP22hx6{)T% z+2!94{wc~>8z|xMOD`>OCpDMCT_mFB)Obs3O88{gfY^)6p`0ECq~Qm7)~14-B$S^K zb=6UCCo%Io{w)^-zDKcTK6`FJWa^%%cc~YSTot2|!;QLXo5y?%{|NJ6ghVIb3-@;tg8)@JZwY%eL zP5{kIgl25K^38STl^kZac3#G)AiLXBr|wMy0^ExRCcMJTI~m`1)#`j_Vh$N5=_2vp z0)V=}{QFSbxuVxye9HUV<~#f1or4)5e! z-0^#i%PPb&zlM3t%`uBjk?iQ!E)PY(UKad3b?;K?9E-@z?8S>g66wy8EKtgCZB1)w z;dps@(LwK;GL@p98V$a%^_TVY>p6AR8#+2VGBPnS(e4$Oc`j`d{w#uE0Lmq`<48KD zP7}k$Hec2!kBtfbXG^%Pl_{d~qtA#|+TtV$$PIza@+MHana*CvZCx;e)tMAcYjfr| zg+;{|Sh%U_cDpYkyAW7*b1x@b1*wyZ0Y4`3(ke~J@H88{|GM z^#nT=O>F(L<+-JvZ6HCS&!J35$V#dQo1lS(!R5j;MHLTWw%$<^ub>xYlh-n9S1G`K z+H^OD8mMT(cS@KZr zpPq@R{1rU+PS=$h<{T%n!_JSesi}^BA~Q8KoJ$vG#uT(MkXf8hCQ~?%BC-7}pdwSq zMWSGGh&HDtVhzsV2DbMD2c&bd^&=O@c#Zw%K;zurs|L&ciOYXS57t9*wzXl)m0f6m z01bh5(R>vH6RS=_b+ryzw^~J@D{k@}oB3lIe6^*DNU$vxBhDuUz-SqA^Bc439KyF> zFG`!-qq6)%^4q*g4GMC$Uq8R~{6?&8QUb$vzn}g64zt>-C-HpbJJfxP+QGN$qrVY8 z`WX$8o7$tm8@E!oXtImPGH!9vr>qW&Avd(Hqn&-cMj#K2{nmd0-oGIn+VkvT`*y@g z!jEFZ)}ca?n@N<3L!65zy7Y^|OS?2X|0}^i_K?NY0%W_gi}KNnCbHQ_R26i^6lL!3 znK*qBhu^G>fA}zlQU3H{G|IO@?nDt76k6H|@X)Za#vsj5fB`CR=;{#@KotDFr-LGw zlr*H2`BinY7F_nGnp$uZRLN>CyN?LBAIL!X_qMwde7rqVX^PG5+17vTWT7(cca=(H zO-&87?X=IywYdSpUDqVBjr?M&UL5`}{E22JTDL!3qOwwjrxY^a z(Huu)n1hp$^f+mpP*}RK9LA%wR6!%cIJm1XmB}zPQk%tnq4F!@ByN89QY%=f&`Zdq zd!OCsO4T&{$gDFrSnxFc`P6-t1<3%kaCf*rY}}0zIZYl3auHb>Nu+hTMqG8 ze~vCXqxs80XJKUpkWv%k7ZsC5fSTORt#FypkhfGeu}joia+1Ohj&xN?;4n!6U2pb4 zcG`t?4_34B^4Uql!K!I@NOd=O{T)~7YK@os`AXAr(;1hwwnxl&fkJ`rNnGPI>ATTh z!Fn>s7ZttV3IFLQzJuOn&&uC`>Sywn5yspsQ+gdQyp`xzy$@t83S-JVmBfnUK*Z^N z%B%uuHPb5-z%!EhcGW&O*>kXk72~cOH@_sp*u{Pxk5Ih;ix}d&YKAxrw>4(acd4$e zujE+OE02D@ac-Yy774!bUJK=V-)iS$H)motx6|=(gSC$VN}tQiF|bXqpcciI9wMh0 zOq`BOQp9V3b+=rv@28+M_{>1|>qhYzfYOJ1dXu;a+K+kMJdGKeo%eF^VJg*3Y*G6O zqk`V~mK44bFDT?@hNpqhH*z8Wdr7&{(#ufGyCiEN&p$uLmsYjiY@Bs*T^~y5JQPvfe_83$zdFsGG>$DU#VGIN|YyM#8-w`e2hZ-n#l`~;nfOa zMz0}V^}YGA#^$9`J{Dp++G|p-qt59)>YI~>|JLd$8V~aPqKre|lZ_U9q=IZ+pZsU@ zC-^<*tA?G?UP7&k-dcDwW0hW5jXJL10h)~b)EJYb6|fjvbvK&NN$|OVUAALehLK3H zE^{X{258lf`KJ=cMhQ5i zvk%9+esaGwPc_`+e79!b;l)%+L_dZeABW?C<+(!i;tA_eGXApttd(Q*3ln&px_V*h z(}RAQ$q^L2f$3M8uglYX&j-o#v4?5GDYx?tU-o3hR;QU|om=B?EguQ|CoIz3-_Fx+ z8p(g|K#bfZyzgn!+2*AROBq|zlcM-W?E0qY)eJ;#AS3!2$`W>{$^Cx&T7rzt;H=Z# zDLmGmtt4B5o|Kg2fZ&**(%`&5+PKlmqg0VLq*0~iq~V==X}@(-+0zYTo{E;>X|e-D z!6Pb0OSaU3>d2t)X`vtESS`noZO5n;^_piV+G|lKmZHukGt*0ULJEh;VO=H&j}(&Y zgwNnwm)~Xy&Ti`kr^7Fq!XNGq*9IrgZYLVMD`C40f;Y$6%(fKzTs(qO*wY!#`r^3aapAOwq*jLgWeiM1ePz`Lp%N7}5VVnxt0 zdQq8_%q1peRe{j?PK7N|jZb=MiOK#_TzQXBVVvj)XL~mlKeyJn@r1y^Gv{96*)>n^ z)Sc4yRP4=rRx4kiMe!}Et)dk+{}Z*Dj6#Ljyv?4gxnYT)uZp|oiz9+#T0|8`TeVbs zzi5PS>$*FVZqWxm3g7`5l1poEzOy1}x#q(xZF>#55AlA2@v}ORy_DRQ=?ve*d~b=LY4wN%YPjP=IIshkMOc#>hHX8L;23n;+qypILE&;%%Bh>B%XYu7JfEc zk6`k@sqh*U1Zz^YZ_1g)t{%bv`U6|><-57_QqtEYTX(rYR0}rvo^Bh0Du4oIj-p2u zA>xP4SL+U^N&eUKYyyL{TcJE1>S-S7X->e;8A4RxWBIlA_tvP^GX#s>>6dptMna#& zg`WzKO@$VuQ(X^4wB8)!kl2askhMx$znx~@2{U*kN_wImmf~jGP5vYbxs6P9S0|a; zO|!T z%coT?>QkYOO4@C|CKJ)%%LFN%Em>AD2lVZ+@i3_kk%1WZ(z&sOEa7|*8--3*OiDtS z*wba{)B-X=Okxwyq01}`AgZ(mTC*sn{(3Gvs_prlbMw>epHJYGY^na%@{dUHLE!xMKSt#9H!OGY9*xxnj-!!@7%Ud zRC^@RS&Pm3#`{~UaanV^ir3!UNJqS{C1TKNXO%1VS}o{{0~ooch>FVgtAGlebu*rh zO)$C?HTTCVn<)O;wWzqA50p9;Ns6Se5vD;w4CuA=_-t$!x&gjTEyAJP6-8h5IE>wz_3`B-6eX?Zg66xq*1(hNAT`NY z^oN#~3mE;M|H)$)Ta{$2NuKBWW!VEEYMz4+baUk#-r1hs{rmU}tg%(n^7oT{gzef# zOlLTnkhx1Hs5t8AH+IC{?hVjy@cSh-y*a`BL0Ux-hvrtBu4pb{kIc6xx5;r`u?$ni zL~>l8DdbnP5u%N1<`^2bdf#FIg9;T&&%CtV9S%@*pGv;GJus*hNKMZv+yl9?o`6aL zY?eO()-tnVRGn!3K@4+endS&iM%WJ0%qfmpCkp^BWubzA}XV{OE+Daf>a zhb7%)J3thuN7PD}U{Kbe7){64fohnTTA`rSp9<=$WM@fCZ#e8yw!XL@Sd!~WB+YbY zKg`g)`MSX!Vu_LdYfu7<;$&TF;x&hY?Uifn=dMmwNH2JneL#*pLFr{;>EpL(PJ z_6W%}#orAG?+wtJQ7n7Tu{)72(8C5?sMG+04u@qDKT1os--sQIX}k)kb}Fl_A!rZJhRen#|DYf)>e}jik(QHH?>0a=cH8w zZ>XwPkhB!|uAu*O0wGqM-LKURDG4-T*Uk$syLcB-V*-V;{YFeBgFKhOO$V()DTGsj zJH)}``?wH*eUvm)|(O}Na*y(3XO=`x*I})T-c>d-hd=}#fSVF9|80gPD zg+#B8DMOgy*?`UE0Hd2y?p)Q%;z$91l7*WbfZtt@tHBTitHFI8bfaZz4vw&pan*Aa zpNq*UP~w*HI^#08M)xz%JRHvbbJ+utG1flytMhvf8U32q`O)nY4Uh%f+QPT#c6_g< zKwu0EKwb5n*Bc&rH+#?t)pJ_*-?&cetrvcgW0e2bEUz?}jXh($U?DGkvD1~~$P%M> zC$?m6VxgB`O*!B=j?S<$)|S&@A(0PoKb|F#){Yw}Vbt9P>pxRQ!6=!p4cy73X|dLa zr*eIG-SY?gt4*0pPOk~Sd-m+)FWLluCdcE~QWBO1!^Wc7gW*a}B7#~kJ}LE=_dsl* zB2StcbDqMAQaRbXrr0);mOY?sP9;e$2n&;nbPg$hUR8ugl{fC7hG4kH(pV)YiWYNZ zJYJ!ce*BB=LIxf!eFVqTtZaa6qwm1GUGX4BuIxI6#P)8%G+TO#cV$yc#3`qB;k&r1 zj4S_#Fb8)}1jQ9e=9`I*cxz!vu&4%eriDUU#xi@eKp8XSqGhqQ87d1a&x}@{P36NC zWZnfhtb1YxwJ9pP>pfsv&JF$EfAxV2v(!v)giSMylK5S3j^+3zhd)~I7H)6>f8@S) zZ$Q+rw8uLOd?kQn zx~$QK6P{iPLb_E8L*Z@gHEa1TBPg^VRZ$&)QQt9e-e_S!Lm7+8W zEKj1BF_tv0P|&|9y*R*J#M>jiDSxTo)TPe&2;A4e6`zQ&CBDoWK8mf6cpp*J^>!s3 zXqqj;Kr$Ys*3|jNYj6w;xYLI&wQ$a;_@u3NVM2S{femJr2?ex4_wF@21xwwNA!)y( z`hVS5tvT~=W&nHDu{UF{L=#u2DGZk3oyMZ`b)?E#($B zO(LVb-FE(oR~Ck;r2@l>*wX63sbW(=caDI3>rHq%_Gf9XWb*3MS~kT}wKN6-JR*Fy zYoQMBp-ytOllw=@gh(F=0?e9~u@aGnl%>bB*dlC#hrXaW3wwK(++a`l+$ieqKfk#V zv{RwzJ`!_1Ie%(6N`zb&eKC^6m3DM_zM%Pxft8Hel5dQEn^a|heNob?IK@T38A91GXZUZ*(t8(I3@SuPJne zKaBOD^zy}n^ZhiCk*I}OM0gW25RN5aXnv>btjaZOYz zl7@rn#k7rVot9UXU<8BY_yvD1;glJ^gR$v}<%3

    >#BrI@GMn0JIcgZyW@vRU?@MeCrT9 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�_JLSJ~$PbDj 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

    3&?HUV!0K zHG@KwSQ=L6^qI2Kw6Z@W(ykbW^}FJz`!KZ}_a$hjnkL$TxQnh}h(_+Q>c`=0f(!ko zQSFD9v?vv-T4SVh)|3Dn9Hzk!MuGj}CXz09Wn=F-iF3^EXHMTA9(3DF~_+lpq%~1DFvA<)mp@5Qw>^VIR zAs5?0{0%7LU#x7T-AuTUiDxX6RwCHyhq@}=+T8i`Z%7v{cekq~^Km@SYN~DW)HZR{ zkMtg?@SSITg_6fC9*G28G<50e`2bx79f!rk)0j|%wl5P9;CvWjgK?v_l@ihm{H)J z1mu1*Zzt=`U(ZIJKmXx|F@==@6^;*xR1MwXx04Nwv!d6hHMIiwJ=zq!UHH;5WyPRLc`Sh{1Us z5Eumh#o!4qeuIGY^(iTzU;TiRg7FBIng1<_3y>U3@md8&N%%L!UOYR85v4qm&ffSy z#HJ(R>6*=PiBf~k&DC+0FNNkF^_;o8-|V9y{z?~K)%cl#*mWDm#u^Cob9mBtO@ znp~4-Q#)oHIf$#agIA?mOMOTI-8QZDr>3v$WL#yUwB0 zHd1K}3#b6Sb92Ww9Bg1JS;V>$^uyio0fIR;d4*4#o}Pg(v;Wz{nm$UPe_ye>14g8G zI|K7F10O)7dtaSYWGCtq{Zj;ko^}ET&5XLhuP1PPqJ^a7?9!0RA4tn)_wwL(R4Y!UX5wR*a*jsj|N!!B`iRh7xTG+s-&Pd%l^b5e&6O&W^ z6ey^h1DL8V%Ci{Q`kvlyuh9bzE-Y|gn8v9SC!d%1$RT=A`qi5&kwGGjDR zTEZh3`kZ*Pi0uLEIg9hHi!6!oC8`R#71{bwVg(|9lObtdrF~WOP+QnQMDt-N5ex5u zB8|ajN(r&ifLSxf+~5RzY+M*RcF~ljJJkvFC-Lb+(8JS+gbec3%_4`&O zznDHrB+23nc=7Q#Sy~TCi8C&S56lLeNVjObYmJM0W08uYCg8N zl@HU_WPf2Sl?L?(Wtm8$740wLK7WY;dn85oTn7TgL< z4me{}=SF8*ldj;HC*)Kmj>)NKE>06GyJ~;NmxO3<#ER+Dde5VBdB8?$emQ+U)%V0y zU)}Nrcz7lD4BRCWnVURG=b4vRRgf*Lhbi&lu6DVNAYt(_*@||P>9fL#G@F2bwt@}g z1#Uzf}-XNBJumoG~jerK;RV=|x^OW#OrCgV_l{_z1-pv3mO zZvpzfk=M_p#Jl$hts^RY1r0EAk@r|L zKVGj95K0W3!t7l_TCtIVU~C+4xooy#24b#2e!VEp;x^gI<>5=X&z)*5aCMf&?Vb<; zE5Y?r&&cE~`nvhPq|iJNf`)E;uNgEDrH{D~(HY+km?JT+l?nXt5@;;(i?dBI0hf3* zPB~R!I%&p{8n-YeTG0iGorA0EIsST?+s#1XvOBOw&Ih`k5jpNZ;t$AJ#IO6e{X189 zBn_67!ao-~^HU3@h@VvpXoD)%DF4HGBN5SuzN5fjU4fo1)q@yZ9#dB@L|iztoRVVA zU<7V?9?^I7^-9VjeZyNzh?-#tC5&>(qhN4mJ^ezGI1lKdu(Vmb*{RanAISX$% z9{ethu1a=9{L2vI?Ox$x*>$WM-=#bnSq``k%Ax3tcN4kn8Z~xG{sJuvJFmMd1uSIy z1Op%Nf*h)05k}9FnQuDBc_G*u$`Q%|y_-Rut%x|J01^%a%cR6p3`X))ZZ@XJ+;A+p zGE~SF85X$*F(xf2iWPybJMAqkSp}`43uL6Ya}g%&-k;;cLppH?d-E{~dIPm|E!CMp z$pFHieS2f#wVYTEWFitEc`;GvrrnSr^9yxo!E;CGOQ^Zk)X(-{TDB(^S@ESgee!<@ zVP~Mt$O&U5t_NFzJU`e=3V-4}-;i|8@hd~yZkN?ATh~3sN{VhQSBLo=$L}Q410&I! z?Y(`$DM@zc5>D9^V|yBsiz1EnhE+%-rC5>hgU_~#VVL?I@Z=vWdyC|w3L+^= z#`1=4NPb>Gl;efu3GCF6Jnx2##$T-lj z;WU24L~4Z2`ii!tBi{TV-noVxQ7YJL0!=}@VUoT>$a9iI@nD^CH`dUNZQ=qk90|n+ zuCJ$rf!ST{qI}))GX>p$Y7-q>&wAd_@FR`PHynsZN*(l_2)S`cm`30Ggyy+K+ecZ< z4zgx=#$Px*ZK+s-ZOsIyK)1ae=cumhx!1G`0`h=b>UA-uwwSj6t08R6Q?+HD*2>ep zs8c)~aKvNzdrrAFnb*I3o#qgoWgnL`Px4_$YOxtihISN~n#PIG;>NMUk8gOpDB_pd zf3~}*YYEUYjH*$p|6crT{A;a4Pr``(L>g<4X=DbDo4AG}yrnI34z3PiJg$NMFu=lv z`CH8=!W;IYWlyjSW>;o3Jgp3ous_R~t(t7{C(gZsa4>~RtQS*CPAQ0e4^A(24VypTQE}!9evefno*ISjenFOII-R@F>0y$V=FL2a_j4GZ&%tK<_jGD%3=#kYaWqhdZ=k!snbZF z>Y~BQ1=2teuuM%FZOGCCVc{>j9J7!{g07~s%rRYu{cH>4Kkg#R7seQ%Tp6MTRBuBz z8`YT+cy#^NOk!P^8Q#WdRdAW&)+?%1y=zdE6;WK`k&uCg^R{KAA@xfBYX$~iQD~)8 z5++b(_!Ijg0|fBU1UdrImbj9`!Rt}IXbDo$Q2|wjqkING3AR58NkD4 zU)Bop`KEQdb$kw~jBD%4uD0dw(iA9O{_pFUgelz)hyFruHL*J_ujPA$;T3$t zlE9p--#Z)$-5XGlWA6C={J&k-IP&7IJ2sFd_E15RKi_3_KQ!ctR1|OVFTqw>qUCNx z)~?4VrSnV>gzQuydv@wC(3I|*uGr?EbjWmQnWO^H*TcR7 zA+!evo*u-h2z!|&A?|)jQIO}29KowwC*PVK?9~-1&5w}<@VfoWq}rZ z4p>v)`XblKT~50c-}=E+&drQ~|J2OAp0-R5|8LudvtUljqAwv67vs49cC9|Rk%T9$ z4#I**s-GCgutCWNU}uquQ3Ds8GWTPR;E_}LT)1o7i^OIiS0c>~D(&iY$RAa`Oq>tz zfv%^_!nDH020(I|ilVc3BF&_xprdEgv9CoD2}dkH4SIRbs+|hKr?BN2)f5V_NRb4H zkTlW{H{=Y^Fhe+zH!}|1IUgj64~VOI$I-kd!|l%`5t30%WpRYeNRk^DioY7gY$bdo z>p=@q!G0Q}WYNAD_0{-+M6LV^4HkZ+rA|_Tg8~{D)n}vDV3wu^h5Aag17sErZFD54 zz_;o--A*ukZUaq`4lYim&*I$ip^8@4tB(WWtZw6rLjNmZ}Q3(PMzGpcx!{t5&&k#)PI7j)7J zIq7N>o^l8mK8A^tq{jJ8D8?)n2b~;gHPp;$^6?*LJQ9$lhWOY*oxiLea81(7(Q(6L z=f`8)qLLX*3gMp;a5xt0Kyl&PU`>@8QUlap7P*|s2ZZH>Xhhd+GBcQ=OdlpbC-R5I zhp$Zb?CoD?xl(Mv#6{x(j3LiJE17pbBvB1)1r>$?qnzLHyy~lsScPo&eS4s?^gpLh z#F^hOx+ZWm43<~rKR3LNAt@TXv49iFIx^SY|BP8FGc$+p{5rfIro5_usyuT_;>dNi z&HfBFu=*eRGFj)YS`v`%w1-aC?1i&D+4ClZmLtB6XMibHv*%B@7jKg;ZTUu{y8z-CY5(p?>z+ zUrWwV<4CMpJi*q9|9x|&-HhW2iqO$37o)*g_cK)L{LK-LiOw+;cOdpIoDi@o@&fqJVaM`#kA%kxQI%XGKh3)di6na zDm7GLy&&YpP>Cts!T~=m!X%KkgzY|uLqsS)QWm;qiDVd!8(LSVGA;(P3 z+-G_-yy(D&$rKV?@F}Gh7ce2g)fLRjK@?fQO3g%2B(dSkyQIAZrWn5uxZ3%qU<6bV z6aX9n+e6|>lG?=i?s10s#qP!)c5SPLrk=YLm>rxfP zKNk*(bTk84k=$g9um&+fRT5?J&QLPta1OHCprrB9dX30hgsoLlKhbBPdAO?yk5r|% zSUqbRpGqn^@DyZN>H%BzfI@YvAA?kuM9wc{<42h3x=bO8tWFhXomTcXKNdmeysmC3 z;13tQTF<70yt9mz1nOw(llNO#;J{#1clZ((QRee#2}xse(G!!b(CeGV-egcL%?fxo zsq>~#uS);et1y1z#-aQK4?1u%OIa+B9ZX6}sVvjnP z3|){d%$$NZi9#er8|u^}n2ltYfQC(qi6|F$QTZ{Pgmc6G*F)n|=VbvsNaKV>tPDc7 z2S&R<5;K8f8rrL={8V-ahPeroG{iMwn_I_vh-jWDaz&?>opf$IsiO8NWev_00Txqi zqW7mD42WS485whi7717CX~H&gNt5Sb0<)Ga?n~?hnSaYhOX$z8ix|k z5B3DV&u@#ro4MBW*CyxV$j&c`0f|65u85wW%Qg9n8bF?hb-q6F+uXwO9b{ukI*-|| z`_R;py5(4nKL4CaOY6^sCV}ynC}$q$fcfu6ZS3w*hfbk^441fdkPtMbxaa6XGOJq8 z2lfB%Yv4l?hF^FxBDyEkkt?9l&Ki6r2lT{4*KZjTC>B}*mjoJyFU&in4g0?Om%kyd z@_nT&Poyg>ar^kHPf(vUa?`tok=G5kx{&@iRwuEc*>YNXNpPHqE4%d_H7KTo!zo~# zs949T&EE8tS4>}wOPyM1@AON3B}vD2FwWr}@u6O)l>ecB&Do+)MF^0NHy@_pn4_4_ z4jEmZ1J_yM6h5uxH_=NvK#(hsWwaH zj^OErlFn0k*br4IR;_Ti^PSj6;3EGW%O=H7|Gx|jl0WSkUR%ByGQY#WnX=jpKYk6=o*tj-8K4D*zrT<}}-8L=$vrKtC z61l$b{ik_~Z`eA1P$VezeKCikOgwB6;ITKRtgxO1Zq;@OK04oU%Tie#qm5nK+h>5% z!+3qd&(XTnZzKoZnV|ob*^k*N^!@~ufB)GesK4l=H_fOt>62luRzGQ1sR&Gk#7?M0 zAB2`@iLDx9SLd{*A*7TnsL7-g!MmSJn3ba|uSPM*@1>y=V5-o5kz+m@xtVj(hM(6W zZ7q;F$#P-h!e+q)lr_mc zcbQbJfYRH*vfE2l44m$_cAzA1OvWWx&1KYk{<_>gKab?)d40D zq-B?LG*<7T;it`;eyi~mOlwhbC6UDrC={{D@(z2ezqLYSD8vbH5LiM3EJGhCSyD&5 zT#kn>N@_|BF-p}kXVB>>q{@h1%15Ydgq?UKgr!q&iJY~8sa|X<7^$VgxHah<2Hh#l zs%7x%Op(=foq&izS4i@*)(OB!Sh0=Z3e4dK51o-3h#a2);N#%TcYg6PPIG;IVw82O z{SwEKd0j!e6_zND1;B=l-RT)c@zl~4Scz&a?sMjXJotz@f{Jxb4~pP&01&$2uVOY% zL%{yafpi4Jt#VnD5Qjrquzif`xA>b3c0bj1@dpKyE}CvCsyLLQ4ZZijo83^2vgpyy z0gXi+u!ajNmEo7VeRK@okpS(rvC-4@=5L~c zhVoIFn83-doaNo@Y)E{0@8^GuPwSq4_i*l2@`?sgq&pKIFUiDFEhW&__kF|1W}y5ien9%?#P2N5xA)`=z7$`Bb22yDL9*osK|;0VSrz*x%P2=6Hx%v$+b!Oi7lXUep;Z0tMMQZddp$0P(Rlcz zE#K7@96M$flZu#3ZsR-}Xd1{v6$lCTU=Eyh=&~!}G8RcdNtemu$Lel3|J*G~6HL z&?@CYRHG}uM<8!U(S#y82%vCk^UQ7+uSo=Wd4pB?B!T3mY2XElpZBx>M#qdT;(|pi z%{pz-N_F(mM2^X-9Wzdx(q6769Qz_kZZ=tAHiGJ!^`XOg2NeGKJ1hFalePU6k0mqW z(UN44>RAqXam~-Vrgzl-xJvR2pLgW4j*uwd+5q0cKD|jlGs5caJ{Wf^4EQH=`$hAK z$Gg5>za$V0w}wn$blY^D>bb5Ql%Hqv5p$8%_lKVhc*9d|Or2tv7~TEFZHF58-?0bE z%d}rsv#4|b@~SuKPrc@(os^0PtGx)OId`Vbk5jD^WV4R)9&hVOpWmt|9jotLHA8uz zi%XN^R)5}$5mo$+tHwU0!2r!j0VN? z^-?bh|C;eY?WQcXD(SkvcIm+~sQ#%l5UP6U?U^pAU)oRZ0$^*!%P98~18S+hu(vCN zf|yPQG9jpwHQ=Q2ym>{v z@lz7>BzuI57fq5^O7q3LV|s(YT|n^xbi%$B!><|waTtCG-Z7=E8e;ERabp@>UAbLL|Q#gc5Yq)BI|swAM2 z-`dg1#v1Kw#jDxDv3&BZX4{+6m{XUU+95phyj+~q)o9m`43e5aHz9<|n40Rkxs;<# zY=Roto@7x!6w?%Bh{hzZDSos)bwV(ydTW9K#=>0J<1*_)1 zz2m;o5)*@oV-nnP_g_P=7Ror+_!39-=3-}Vac&m6uy2L>ZHG-)&J^|A<3KEdw`lgf zBPNz}!H>Pbh$jB6te&qWmg+D0hV|~7g@HH)l>fvcA~yBibHIh7G)qS)zTo32XYU@b zH$ov|7_{3*&HAk zZLFz5gDQhb!^E=gTG}XIstx!hDr6zY)D(MUp`t6H7F2@y;1UyVGJ z>Pl~5tH`l2RPcIiz<83yNf*u5&qzdc)B_lJ>S<*%;Dju1#mA>=3VL)gniSxx_Z%U_+1^jPXC%-Ka!Qiqb&V!po(25i}MwC79TC7u_WliPB0wrcP;P z{L$KnX{QD~yzRwX05BWzGhhd4T3Lcc8R?}RjfB?v8;w=w_3R+lM)ScEMJ`h@FTRuG zSz1D?$Ef6ks)B>XmY(^AphaTFV&eAbNa3IX6r<9gs)6sQ3qKL%cvSRKDVVfsxtJog z`WuKhhM#6F8HTS2yJFK=Sdis0yjc1oh82CA^rBI#d_@MY$Gr3SKkfw2_ag&;I5l|~k4#t3E!PE5sbGc65<3EYkSQ(8A&gDV4*_AHf{%fK*UQb*=|!GMKyTm| z=Z-{&aSgUr9%a7fj#oOyQJvUC)_2@P`bVC>C80GwUn*RNT!tlGU0rcd)BVH9^Cf5| zQI&C$=pANYaoc!S;P<@CUF4oI@F*>e6`=kCPM;O#8n5OG6N2C!>G#nFt5Wv@G0WMP zISrkG5d?+izyO7_H9$LmyZ4NJTb)O6TN@Tq;`e7(TK z5T={m|B8_Re!bwN@_1Y2H{WZ6Y`nzEUzw^HW|8H?atKSY)dGv@ipa?F(QplRM-1!~ z+*RvW9tk29nV43jtvUoR;v#Z&F?Z`QoFCCLjsQ}`inueHD=MXDb#msrwEeJ{0ojE? zXo@((UlM7|K?rU)_)XPgAjNn2RKP5va+AYre%v@)(0sK!*yP0^cvL`Y7pTdy$v&HT z*k+G_J~XBYoVqOh(lk2J)HRCK z^PQ`(IH8&ZKV4e2dOVI04ya*@5;ZYmMQP(zy?gj*o-=b;rHsC#YDRS`C0vxf+p3FI z1w}p^O>5QP7=x3fHGDeJQD@-9P0-@j%269g@lrv!xLBOac!-(X?>dq;>#G(=y9tc5 zbTxH0sM@HrSir)wW6Jh7 zcVsNf+5cV6R14zj9#j}ZB)KMK;5Q{XF2q%!j4I&Te^0v51>@G=&LMeUNz~saNaK!YULSPqxv=jq(z60jRpTPiAidSx{|z30EsZ-(-KyJZerZr zTDlOAl`zN5r;NIz(k+AU%+ju_c2!m(8In>i$sOyMgJL3|Rqhn;CbKj2RVyed_h=-u zo8QVCX|t_OOR6ko^8%`Y{>Vj;0{53^RwG;d#atiu7$$wTkS?0u&8q_4yQxbX+M|@3 zhuyFaupttrR>e)^90%#+sfX$WWy&&{1sv5L;uv<#EXgrO5$6*CCLvA)J@t6?5*ZF1 z*Z`JVt17tF1D0kJ)0I{u7^2w43bw5kn#MdiZ7<(EPlS&khu!j1wyO44J2cb$su^ze zA6nSOJyoC#!$Em8<6TIVR=<#6h=T9he05InL;2u~!q=?u{WaZYS)=x!(`-~J;Et6I z%Hk{XDTG8aPHStQt;&NpRKyjaS$6_5l8+O}nu6U+>Cq5=P$2q(G^wvU?GaU7A>EFnjUxHt%8HIjX;e>wa|7sYM8WDVL7Qm6D7Lq4f4U(7`VaP;<$Xzy{jilq%i zyi_=L^^R?B*jV~ZwMPj#`d<+6k1Qqj&9{37M!7kRUlf%2*+VX8i~T(3?LL$t76{Dc z*gYJ`6dW&o2gbGtv=u6@>~T9WK5usy&imOAvYz@2dN`l*KlhX>9u5r=2i%nR&pLjr zX}&zg!t1$QP`3XnhH zzV`#)d_T%RUG?(n#)EwYrvvXi{~aq9a8F@)ey|jNew@BOd~smeU+_<11)MkB?0rm= zTYOIij`kXUu$`841M{@2WXS;uG4&Xyv;F1R@cKQ<(BuF(AWU_j!YCmwA*=qRR>iwb zh#WOUC#;RFvBkg3E0^>w7G#vQsM2Kd8@+PTE52F^-{Ugv&rp>C!uUyV z5^|U@r)bX*MMSIpf;Gf6#ar>jbp=p8Bjrlw45~JPMm9^NnO@bD`XHX>(?oT@3l07If<&H`8ofvBz5Q{C{4Uktb` zDyN*Jn_g+n6$?I<+Q{p)Fa<)#U6rIkV?ef52WuHvS|LcN)Rvu1fH?EO8^xV98&W5+aO=A#{bA!9E)RGPU)>7XGMmF(_!)ajfUCAy~<@~6QsIC4TAts1bj!sd5 zoo+GcE>~9U9E*U$2~!lQ+-fglgVwsX%B+InH?i=d`q+dU42uznM8D$JS|!flTf!-0 zb`G&X?o%RWYGC?Tc@?8=%vVuxS_)0pL_Y2tDO0&)Z#>qhu6$WWb}CYAfXp+YNkd0w zIOgnBI72k9v3)FUz$t^51xqe=nQTNEtEtZ>728E@kyjOK~gV@0p(oJl$L$lHXu?TWkZn-`#tH{k%>`pnWf|?_69hnV;`ZEslEzPyh0Z zwRIspCjD98UymC6LOxmTeV_^V|6_&E%?HHzUy<_Ny!vW)y)XNj7`~WY@B91R#zJp= zpDVha*1x>=dfw9(cIEb79r(YDSPBmAdc^lG1*G`~-h;dg+*3czgY<^_9mX0)DEdWo zKd(KN_tk?x-@f|(NiF<@@ZF2Rxj9=b1;z&e+2j8gesU1->>O}hL9tx!l^FPi9(YgM za=G1kkI(Ia{9zcFYxt)46{Z{LfZYGNrFlDVTO?cBKi)rNDc~nqDDYt}(0P&X-_HY# zKNwHI50&g6Kn!#b-}CzQGpnDsKRq-Aw(IM0=@mR* z)xGaKWO>~K@O=X*+Zy5E-~sxUn(Ra z=}NXLvr&n&xnty!AYZ3_EwNZ+|3=4v(@O5DI!gK}>rbC7U;6ig3YSp*gPAUK#C}qAS=G z)JSPCrQ!ZF*Gp!K!3~p;WPkmnCJQ8_lCoi7ua(J2>dE@eldB1JnVvJ_&*a zhb=>vW6K5MuetOR)Mdc<2t4fhg&itU=0ARrJrl+E=;S<@Z%D_s227|3gD)u4{ABUY zxS(f?n@~(dsC@M@XqwEk)RQDhrKoy0eyGEZmT|K`dOW<2afBq5-)io_n2kHcma|tb zUxX4@MGO4c$po|2mUC9*49&4~qZcR8f>W4`LYN!iNE-b_lUqgLRO@{}?Nn7_B6?JW zFcHn&&s%QQ-Nv9B%GuI`c2~ZLg`s&fMa0bcZ*dngwIK{C-Po;`+FO6v7o`(MUXVak@ zLbV1!vu%`MonUc;aF2mG^Pn9SFWucWLMgKxGl{E6Cj*pjn8oOE?sPQ{l}ulZl@4^n zqq${w-g;mXelh^7zPT53&B8)|bnem-l5!XWvrzzh1Q5Y1`g}8u_de%8vwh<*#<1bL z=?=82Fac@gKv6uP>&5~2Qbs3AkLKX|I8J-MYV4msKjm(IfPGqnzs>I5_C783d*!_TgX{a;;`lA_^gU(yn;oKpZ4HQ4 z_e{`P*M;171k>Ap(G1A#54^B^?bRi^Fh|t*J4Ey%n7Y?ZZ3?VZv$L~33AE1e zHrxvjJpa9;^L_DtJUQ~}Wu&{%m?G5r<$nL$`@HVF-Y4t7;r)&(%-$^83$*mb?0x%N z^Cxq<{tu)5JLAg|;RjgY^H0wd!dIT}^}?b40{@WjOODx>7cMMSU48xIn?J+Hub;PA z-~At_*RS1v-|Yfe=FOkUmaqR710(yJ8ju0MyAu`hK3Sj>Zz{~=+d<2eNCnXysc=$q zm$NT4TuO0%qZTf%tAm2FRbohx^OhBat4YDa36;5#;mgofdpD;EO`}AW*aS%tlhg3Y z#=uxB%TK0FEO^-bs|x>?qYh3{SwlbgS!JRpKB|v}R@Zdc&J*;gkN2iq>g`Wa z1it4Y%%chbS#LH%U!6>YVPE-_8Fs1G*38V$m^F&ED+r1x0lCZ~iIpR?7xv`yu?X@) z+$~y+av>hISdbt``^_^~q=!bD99!vtDD9V+6DK8ij8#^R&#@NaPMfF&%R<^9nxgoy zPkm_x?SbDAVi>E)BIgh~E*rX9A|r@l=`x|NZIv0GTz`-t4jXqWr%yYhm!Fa=04M)< zd8u1`wVsfXputrLQUX3g@3itZWRlcNL{LRKG>lqB01h)IlP`#t=cP1lArd8<0VkZo zP$kbxr0GVByUqNIWA^ef=k|(tw2EMQn++n3*dLWx+B)kSeS=vCvH=Z-c??ol9B~%Q z|GWxqDHu+g2%>az=Gd$7aFGf+U||>_Z(;|+W~1{gKblzm<_vcyd0*b#NK?;>Va~1Y ztOr8b=?bVb_35Sb7>@$w4{2#Ow47ell#~1(@5FZ zdoXt{AZvyxl($a+=?khBi5^?$`p(EbFF>U#V_#ms zKKb1p*3CiR;{0NsQTPIy zx_)i>H^S4Ab68>sK~To$+kdG_lY|9Rb+>)#E=<#)PN>UYc8{~@vO^b~NQ z`68!(;dUeN@AVF$@M|VtFG?(0;pgz!7!=6o&o9{iCtJf~|G;Z_K6gi2^eSnQ6tdap zfClw|_EjItH~Ti7I;KL}lOSmk5wFH{GFZEJnEtOw!awW5lmYip^*m3a34R{myl*^L zZaik%P+I~+fuC27ng#s6*9Sixf*z+C10@TWm-8=DDHWFlZ@T?X9R1R}1MUMQ3A$bn zK0|ECtq2ajiRg-@ zFC~b2>RJ6GumFK+H$sh=O$P!6;t#cR@xqxoB64k7DqX($(W{(CX?=(rXkhl<%rg*i!UW35y)2K9F79+ z4<`K;PFz(?W!IzyrziXg)dAZ!@zIM{;)R^kg(Te+%?J-nME5+iSp!zoM}p#N?7Nwf z^PNODG!2a96D4v|w&FQjn^mK+u+u#A5)FnFG|@^dx+xRmWM-V?SMPu&HL_!(ig_^n(ujE<@?0`CuvvsU-z>B0T)R3)7~WIzrIMtd63Hk*21pD z_keo>B)Zu~+dYAQJ-&kP&x56s8FO!wH%r0qzpjJ9@wk3Luy+3rJl*j-VRa1en8CH> z^|;*MKm1Pf4fqPQm>2w@^!roOzpZEV$h&=i%NXb92rP83e>eF&u4>+Y+|Rd2n|*Kg zpJ)cYf(G2~?(LsGwQBj^bi5Mwe`LOXl)mrXuAi=I8qOArMr!fivVZL=1_tZ*-}m2O zF&Z8(GJcGI^uK@8?|n{dx;&O=8iY~3`hR>P?+ustKTCexwtOFpj~{LLIew58zUmhK z0e0V?eh&q>-Zz|rzRN%`KTyV) zE=fsO%P7SpmdzsA{M2oVh1?r38RZkR#@b1;_HEy{e{0GVl}I7jyiBw4Sw;An*ff{O z8?eXQtMl&O7+~McJM$zKY0CYLZiv1cd@h6PfpK>#=_A1A$s7(~tnOqKCE7mMt`|*R zB=%1ML=s;7X%j_Okqe{?5pF9_le8m9t+J>3h}5Y2Pqm*>4rXq`=6%kMM$Tt)cQ&08 z`J5LYF@bZH3btDfLUDCF^(Pf{3L2PAzsr!5WEBck%EsY%ILa!;p+r>+ku4vT2PRd* zY_5|S6O^XPt#AxLLwNjkRvcRs;fr~Z4yIL&(E)k``}u^#f$5@QID4Zn%2SoKYiliE zgOV#xK3Xl5OQcY3##_yo!1GUcM^dc#maFIG>=Z3g+3XM)A*wv}=tfZfcbCImLHC%R z)XV1;L@b1EoXiS;gVI~0;)x73XptuePICAHj;dVrurAnTWj>H7^);;+^-9k zDln&80~=v$9wBqIgc2-RMZqNqTl*V-YLK$+KfOh56!K_GD+j%aGUyoOlCu}XzKSPc zKgMk0o7B}FZ`!QJ8S|>Djg_7;@OP7`ot<4{Q&X^O!sMhhPd*axTlsDF63E;Z&=2G>V+q1Et?s$D z$(UnjAm&r>yrn_DSZB~;Gq;(MEV@g;kS~`PeaZF)W$JXLq{I-bN}-pH8DO&r*Bwb# z6HC&NNo0jEt11m%H1V@*s}iTD#ONzETOPclWiw;ElpJ^znZXsyu>M(M@<@ZItaxhD z>VXX)joJ4$Y4QRZCX^(?!zh*0rEL+zVEvcb=L@xEZ8t|jb0FE{M3@J&id)Z>X~7khkS&Zms$I18;wJ(Yb1>qrX&_h zV;VBh{!;lFgEnCAq+d46; z@H7#hSIUJg4+~o=&Uu|YkdER8R(SshIitI{yAyBh_HPoZxr`zbcs29JlpQ)pAH;-#y9O`wgB-L z&lMl3ck%9i4U)DNTjGJ+Jm({j&6L+4Zp9rX7(_A+>!#k`*#Z6YcP>d$7%8de=jZYu zGrYanroVfApB2rN`+%O{4G!Ks6V+!gZ+%z&h%0>Dyx_ZG@+6fp)N!qI9MQ5QW{8_I z?FCIDG4ey|!SH4QdlvZ>3fCQDrt&ZD)wm!D9JGodw$>Dk)iO2rBr$38HCcY*DlmUB zO}qRt-@K4pGM%Iyi0JWb9-_Yaao7ZBCnIetPhd*Re2dt>P_B z!{iKaWDpn&Lfs@v%@Ij(ITF95{|7l<;*{-wt1nOf4aT(ZE0U6eL-?iaOzicPwk zl53P!!>lDu%OOfnq7@I3S{AId`XeglQ1!#mErEP+B7R8wg?2JrM}upSOp6@;yp9e}R= zPsAjt4K)eIfQjBV|?MQ2sH`(#1A4cuWN_n<{qsd=iV9^kZ+ z#qR8V%J(Up200cGH6YQTsECZiQX&`3-VW;U^cK40w+`3=Nem%w81z+a;DmX{%Us6F z8WBqyI#k{*eh7!{Ix8Cmia?HzL=A`C*O~KO)z0!n2gG|UUneCeGBC6Hj*%=J{lC{{ zj`e~-v&WAMG{zmkO#KKNhm0o|HF$Z|Y(Mu|Yx~@SHa)F2WLCU~pWvV+41f05VhuXfZ zs74uwcb}b1GEc0D2+6W&^q84_&+N@P$e|9XRCVG{BT~4rV6WC?JC@oi*|;>efp`il zX1kASWq=r@Atouc!m$?ynWzaKaCxJr*|Wdya>pJWB-;xTvK!L)mBQ3HOtM*;J{mQ; zWD`VA5UDu`UU7qXHrDrO7Ns$rnw6b#V7m?upJ~D#cV}wbj@Bt5|aSDM~9@P z^QrY;4A_(+5Q=O&!iA3poFEK9_G$-}xC#AKg#YXvU$aq&xBIkC>tec?ygk8B_Yd1L zbc!5SECL7_PDbQw{!qRV-VU_sqZh3!uJPxVy!ZgZ!gm-V?7Quj-K%8t!47fW=}lBc z%giGBGU*{L-uO6T{nr~SaazR7%z%vXdE84#whr1d$CP*Ff5upHxjiQmKz61tVyw@4(_3F0< z`x1pxITr^jjl_q=n#K?>?VS-W481#3n8Y zY$E!0$=t9<1S=w286qMmToCIUMCXZ_ z1By)+q&N+Di`(T*?B#!3$!!RThwB>!?Y7w#3 zVAc9@SHSkh)-KEJZvSAb)W_yh=h(uu)wV>Ej?@XqFw6sHRf3NVK9I@0pq`Bbg3NEn zQYldgp%|6ZP7^(oqO^l{!TQF7PaXaUliII$z<(u`V1gqsMOdD1|df_ z{J8r*^$%iAYesEIP}yn&@2}1d} zMqaLIe-GAt1xkEVC$Ud|w(16P~Vf0VIq1(4iz z^VZS7?*C89mR2Nte6BJXk0Zcn(~?$syA`E%j@DDTA1?8Sauh;6=LMd<=0}^f3>kU5 z@b)?oUbB8Y`hLt~W6|8UeW7wtX64gALeilZzfz{mE}fRvuzC};#93k8Toduemba#t zNr#b-Qbk5)j-xCb7uC5=Y%X~-Mam;7tMb~;CRFwIT9YM`9v{Ei8dsfb7zd(#ggzmA z^Y^Am_yPs;DjkGFN*B8DY5+++eCCwSpAA3i(!<0~K8mJQHTLf-PDOkCJ+~g!+!; zPZ>m8y)B**%9=4}wd1y+U;_dG3tV_?TpC!$!X`wvirfb(Unf_Wb_0Y|s|sika~B_{ z%sQFSai0T$u8!>{PkBCt9Rk!t3!RKJSmkn0KO42Kf(Xt6(e#9Pab5L{m#CAPcYfNr zq==kpb)H9_=U_KE1stS>@|9P-OlDpA2H?kA!KM@a1C+LRUmVhR^R{U`McW@8f+Ox& zT3feGdmU@EHRfuXo+6v%2|U-=TrlRC_b2aEA1ZOnd7yLBbgwTFs8kQ<)Ij&(OyVQW z&clw!VRz8@>F_#+^ItPAcikNi1Xg(3X1FBiayTLQBvjd7$*;>6csI{16Ljc8|E(RQ z8;>RofWONF{t$ent6kCgJOACI`q)#CE20#xbV`FOBa?+K!v7d6qmW$)O`14MB-lRo zUM`GnoENp3$DnGgqP;+E&=)&YQkmEhG|Ieo3zDknn$6uh8AxGe zxbe6NB2l+~*JEMxFjiZa=$d}3HB?6g0!``_dKQ)SK|~n0G-asPb)>YCp#T5?vtWlv zcSc$#BU+#ON2b`YF6F*4MgxuETL#}di9f8N~ff%N@t zvx5Q;9Ir7pE5Sv|rqQaEW5^_Pg52Z8BH0qfZCwP}6!SomLyRd@$euhl;?=|ilNN%t zx)~<(cCs`H>h>f#84Eeh#-({J2O-v~SO1sV7u$F%(i$+dE2&G%j?J?UoDA(5QT8o(*D6CK(W#5I{Hlt|B2SY3A9pIuy$^!Lr8L)w&!uvI(O% zsT3&U)+Wt<#Rh^s=j(C`FasLlXq(EU)5p}}uJ{;E#idkbOXMfnChv^|F8z(bF^bTb zak`B9tn^vY>ajm<>HviBpA)W<|L`Pib?P9l!v~2hla9%v&1-i=Mq2t7;ZM59nAQ}e z>*#w8F$q7QeC+bpJ`{k-?sBL0emXeNd0c@ug8x)8wCbhY4(M;It!J-I#v=m@QWLio zcR$ZtG8lo}<641tuJdh=l&Wk_h+k39bb`0wP`0#}FAMYb*vAEtCoc1EE)tf1zvp)g zC3REuPyP2h=DAUy`-o4gnom06z=MY-M2v}GgdmKPNvJ!>wCtmgnm1KCx-u7=?IwGD zHngUvDR%6;J2yo`WmRG=IyTd&lTpm2_aTD7Pm1AOiz(EKD`uvqxc7XYB}O*7zqv&7 z0RMa$X=z(n3=8yWFLtmP|Mj9eA4-h8j&}4n0EGD3LmuJTGc;l@k6n`4ea|8DUY{}> zPahqJmln4e<}Eo3gD+ldGFhH<@X$V)i<;VOE7v;1={4*1I_n9~z>M&El*aMGd_Ib3 z8P0Z;_e}cKUPYp-$y>kOBB!G)y6QR|m*7@9E9HYFz+h9J@pp&3Wtvq}DswSJ_Df&^AP5w-n0!O=Uvi4n7Tr*475Q zDf&9dwmRi4M6T~;)0qHd1dso=%di@cbi(9R$12T8glLRDU!hJ3ATRYms+k4HwK|Ql zry$rPpIxbIHHQ|QK>E}RRr@cZCdltz$O_#GTh(~E%=Bs0$~l$pAYks3-Nxn9E@?&> zRwZRlbxY`KwK9W_)M?St8I1Yg2xtw&g_*Jjf+mAmL3?6`+VGM|thiLyBxnFvpDWs3hVVtH~ombw5#; zE77dxJi#ex!)w7OCGKb(VGzOP(X} zW7(?=#gI(6eTdWmKHE~`Gzsk&F=F-uqTOW>8MMW@FA&o@SqdDL3x*9661I#*Ef17x zr!RJQQ{{EUG?KLPU}iXXQ|4Svhb|2!9pi7_-D@b}p9VwO*Z%nTspG;#Y46CUE;mqg z_`QfeU2exv*i+ZwcER*BZsHK_&hL#3=&gOt;Ctus9l`y-5>gGnMDe`8N2~NLC=13v zR%Czse}nS_SVjFkz*C32i)RiV8yNFOs~7{JXgl^IdmVk4472qrcmlgZSm2J`UbO9M zxy3W6T@4pKWbHy*_C9H(8}s2dm{;#5xeHF&7=&~ z^FoNJ+V$8KQx4q4Lv*u&{|a((pjDU^mY;Xh#B@#vb;6FSixM)!6EYr2!>_=ZI%gDe z0vV`=OV2LekA~JnIKFf(nUnFuO&$m-bNh?FhLO}|T|DQt_c8?rR-N9CQdYdOuFY$erchVBP> zRxWK?wPIBZty)&hF8&DDa-U>u%`+)P7xL;yU?^)FFJg;M+%(QO-%1r!GVtb?P+g@A zh+hH-o>_k5Ba9Kz&=i3%N$ zWSL|u>&Ds`a2I0L`O~J{FT9U4JAd6e z76bpuV!gnge|~PQ>FF{x>rxPm-yS;uUKPvfuWaJsfao&=1cM3v+}A$vH1&poBL`5` z=rWkr8CELK(?8+mAte~fn>TsX57qmp*1Bw1s9P!?Jdhd=+{t_H-{kJPYwyKgzyZGt zrOS;DbKN<1P<<)m>nTva+Yip$huiBv@g0I;$JSr}PN&jo*ApTbj2qWGN$Czl!J_Ei z+IZttO4E(El=tk`G(~9Nn@dOzEW9R{(VCc+BU*p%K1dnP>LWDJz$ZAo(i+C8TC?($AKd6S#7u$BbIAK zfX^f-Etm2Qt33cF3F5tJJQl*f|cnMYfpV0r@!%O9R8dC{leFt z>_3dj{%+K2ec>GDr%qtw#fMRycpe~)rCaX6^3mI2cI|go58rtFv-q()9>Sj0 zgL(JLl`B`SoeW*l!9m~8rSrGWD0|p))CDHv8kqigJ#9|e%y2jQuXOrGdg_;y=!`+6 zu{NSOutTpkDe-=Z&!w){O;Et}6*OszlZ*fs>8?Vnun|9CZ$VW@@sex|4d;`>Jo7Cq zP7~6$F%bX*D;5?Nj4FHUMm?Ake(8I(NY^;HFC$4{P4K`G<&-+QV;Mx=DApzWkZ*fI z@AFsC9u8Qrnxm!}jFjFiSasia5g_agfF;@I2tpQY1WH`YbGHS?l>$LYi5h~cvastF zNHoe_m1|q^twNS;Tn|F>`3Zx`I%SWP&X0uviy9X2>Ld>}1l_hA>cf}Ncx2F^MuP?d z<8y^HRA;{4b33lq-VMpgbtwjaGS#bsu&)Xpq6iDia2&ec7*lfuyU&D*%^4x9-P zM{6jpP&F0AI`xWcCux^gxqRdiLtTpBOBUy+!px|f2J@!IdNp^7pyQ8W_DBCu$o%|> zDHX8s%r~+6`VV05Lw^P3>i*t4g!gv)q$xCjBC22Jb&Xk7Lo1EKC=|xHJLH52t1fO- zF&;ZaM9@UgzU85+8wj&&tC|*QEW_4wG^d_N{p`0c`UFs{?nbe?8!NZm)ecar8LG3V zaPGTb!^Vl{0i`kBe;AX)H=^8k7{x^->5$Uy7}7L;H3hRZi>9`it`=Bc)mPOCarx#u zvFH8=aP9|>V9)E{hGGk~i>+q3@YMHF9=b6qW2CV-`T0k&eA_`R-*Ra5d1t@(4Q#yd zH1U}PhzTx-up`MuA!m& zMbJt7i5*V8HY5i{Qe&DVIy8YiZ7g%^M-$?hsbgr{w)P~JI<3kkP2~}Vf+lFBcFF^& z#3Zg%rl6k`pRzVc06ehvpaKLg<{4`6J?pPeEtPAbQA;s3 zsK(rZ9TdZO>9H?%ng}%F-x8phj;#=Frn*y^I8TyB8ra6SkdbytIzhpsTIXZxe~XjU zq_7B+qD0*^-tWZul61k%a6M8VAw>kGHK3jPBz$4)#yPCdPh(?tZj%vnjcV;Q)=nKq zrB@Q0o8HEu*7P>4kI~wTa0K(Z#<`6Rkhtk(VNe)_)O?0|ASL~LLrPM3&(3E;)cIMK z&LEqaQPmD)6q6>OplQ~xJc@s{3`zyHc}frmC9gkCs@ z+41Laa!=aw(BRNb%TRh45q;*XJfzN8>2Nk|&Z6ILQkEb4)x z;d4_1+^+d9Mu0}3LKI`8Te36SdWEiPCWS*vj7zi;Z@e1X9sJt|RYfBe7(U(@)Kv}j zjDUd@Hc4kWT+4;@TC7?q6O3gQbTkTX*WGDVED=acs}LD=@FfqHg4eTam9fe~;0But zDrpVck-u+lio4AL$sihAmh(Ig{U zV4Ry$xE3Y}7*>GNlrYNpL>Y4kpd=9!w73f%3qus7}8C@G!PmO;%u54?wT%Yrn5vb>s|t-9J*Tq3=k5 z7l?orIMt11fwdMJ^BSZGMky%m_Jvj!-)%v(mKP#J89DBz-aFQcQws?|%X=^D$)eb` zZxCTzpF4y3spGit__r{7`Iu{CI&w31-Sv7Dt9xKsVf{Qq8^P*+b4`dWmT$ZbtGC^Y zQxAV0t9QO`;Q*7H8f!oN0VaoTK{q;$s!d#6@iS)6`p9n)2Vj;xV|+6Kn!s7PTDpZ*Y$x7fO^9W2U=NOha8WTy%j4 zD1|-!6rMEl8LixCESrOwJF&m93C?RJzNAdzTB z3QcV5>?|P%^=sH{2kYg31E}f0q=pbXuy?&$u@&8i2yWna(;h+`bY@ zys}8a0S6UZjHnCJq=gt71+1z8Fi12Czsov{*aoaxBV0s?)4~)h3=8L}Vr1exSrjKp zSiK=`Z?H1mM=19dkN`v zFHURLFJSHE(^&uRqp;^*glwF}WZxm^`hFDq4x(7ybJe%F9Qg4M;F;h0BsN}rW+8O3 z8*7-o^c?oT{U-sXasCG{pgMU0`yaXodZ``YSEo+k#8>_Z_30Bh{N9gZ*IlpQK1jKk zRwJc+@)x|3*w{-dh$cu=1HtcU2iNIi8>nWCo9`X^>Qr-!GcV6ET`e$K-r3vXmDc)m zPvQJi-@~5!9>Da-Yt!~3Vo{$tjinoI0hyhxMw%8&c;|gTh3`K7MSSfCe}uQ+_rbgq z=E{{T*N%fO>0oT3K`yr4ax?~CI!3zvTewL?ve0l0+$wK^XNq*xIBmO7GH9VB3YlCR z(!kUgZ8}pJ3`@WLCcJF-+&0ENyR4Z45TDUQ&fwM|9S2}68i*3tNaPhW3It2+ z$L+cWJv27j4Lg)e{xMR3l?8hc;?lR2pVKXap*9t$_2^klAjAHxpfI7SgEz#mF2~2U z4^gqD$tV$Fq9@L5R~S}mKmL))scF$P^l&l|t~id?+4R#=`oBV-nVwTum)Mg(%}R~80304BPa z52?4@N}()XTaaNbqpldjQ|!L^X6(8377t<8(5#&Ul*0Otp1}IEPl7FDvhM&UH{6Wr zfg4aPYEOENYU%JzSibRgoczjXF+Fk%%Do2$^IUl9`!K6}Fg7Zk zFezL}2l*YK)Q@(S;dnTD(S+%QLJBnO{5GJ{7NXQEhfr|g+EJwO9xv!7F{PWw(<$kh z6vu=kl8%uslSLs#H1u_9kA7d6H`Mj*JyD%Pt=>g?v_?aN$-x8?HQ13%+>IT8u~hrS zAc7GWL)}X0m1_VZ_P~fn;6gf@r3kqcxs)O%i-u}g*u*T@LSSKJ((cEp+NJ;cecxFk zv^b4?JC6mC0!sssjxY-?du+EeT6hCRfGAk8sJVhx{<$Ltue23+38_cI9(0Wj`TNhO zs8otmI&Dn}m`yv0;J}2^gsN%K%q!QTqjgO7p#U8>RqA-2{=-)Z3rm@8MVTst1REC4SZ__7`4OK-wx z>rtXi8B@Q+R-TdeC+YPfrT!otHA>HbmJ)N_undv_823AM&1`!HyaD_~NYwLO2ocqk zz6WHWvPt`?(w3oU)H~AWCDc=(_;oU*oq|9r6l#Ljn74%^T5E5vYf;M_1^Kw?Xbjw4 zm-uVfE7)%b@`F#O%1}a3N_ShldYpj>P@=t&Y}zK$H?&Pbf_CZ+Sb$u-@Iv{6ha6gp z7!l2|(2^M2s@8y6jU$oH*C4jizzx2gXAh%N>nKooDB{zaHfa$d8hUgLW+tFP?M!CX za#TQAshwdm6bfCm`^|`vF!>E_NCVIiaxjjqMX8Hu{2P>An@dT&iYe?n$v!=FU>+GT zj%AVcy>zJcWHH7qbD<3^Ga9x~il9UEum~EqV0P*wMFg$Lw=1a@zlzf*)lC!CB!HW5 zsVs1IeFKw1hM)8Ta3SH_oEljx@&j7k0nFi5tz}qoYM$V8qsX@opFIIM;xa*DB zbyos3Hr6md{Sr=n^9z{2^a7-*P#!pn)jRG(xqCm<6*AK-_a8!e=tjK!rQgTOZTCPW zk=GZV{0{W;GRUmr)E6GZ^v3;Ix!ZZPoc-R{@zS6D8|?eB2XXUX_=Q(x00ylccmZ!K zGMAJBs03GYu(F+H?|>I=KobRCKM$*mD-!>ECHBoz$2YKkzQJ8@J}~%RFbhr|+kgn; zz|p0A71(Y#oO<}rP_LcG!H0ed`YM4O)#($^%d1e=33L$%)@SGOJD>j~{@oA$$9ccZ zl`B`S9S>dl1IJgWd`ZyBIDDbrYs$#;XqcKKW0&~UwgaW{(;f9oY#*ZG!uQgVI-}&i z0dKnU(GWL%FX_OSj_O1fY`18z*>ffyxNFkr=c1KME2^5A0}bS2Y$a*k5x~VS3!!1> z8KTLw(siNE@(X%#ziE0?G<$W>#gJ(s26dOURs2xQauVu%$|-s3Z5KG$0)WLjZOI6X za&gK61q~gCcgD5cD0VP|RIA`2j_pdaXvjzb(bwF)gH%Kokom!aYfD3t5OZzvY3a8@{M#Yr_OJ2d!0Vg#4k`e)hG7wR)Y@Jt* za=Mj)PYjJ;1d0gEW_Q^M9dq0c3hl>9Lk4mh8YCNeg^MCobsb?up*2jZgcAmPPoa6; z#3c?2lyD3P-cFV+&eo^!$It$2R6N5S`|raW55EH|<*woJZ7ZQkvVBwV8#Pr*q4a4> z;uD7$&g&(7U`i=yO_-K#E0bl$ylSwvF$cuWQxqCnDNyjlp%&m=QP{$Qx@MQWRVoza zHk22-aPW_LTkoNlRJgx!?Xrn4fq7OE=!`w*h1QM^9q;)_bx3!*kH91@^xAHZ}i-?ySJsN zxms(sZgK3H^SJ$udq-6)v-JkYpE-|v-g@A=FcaP`*f{guuVUqvyRrYR@4c#)&91Lu zy6?zECl|Tnt~+PCe-^^xg9jY6XLbr&@yBNN*D}G6%%xR2cy5~-jjdqW!g2#<=U3Kn z17YiL1~je>RT}rY;$D-50e`LnIJU5pKh8uGd=OTqd$4PHAC8}TI`5dda^=c(-9VSI z!Nvmk()rV(d5BW>(oI;|0>TJ&U3RHwra2gMh8CpGf(ZIvw&8tAs52%UBpjs%yy+-i zq|-toiQ#T%!}KT%Nzd;lF7$$St%TO3{xSWHuSB6RB`RCF7-{8Ff5P4WFt$~2gSc6< z5y6XsZr9tZe`ut|Dz+CzTNwtxFsdA;Oi9YK{BtQl1@Tk6%9W^DO4^r{xVD={RX*jX z8){Wy4ka!D$gM~Fdde$4!Z4zuxi_eF>XZR-Nr<8Z&k?d-UEqFiHU#INB2=f`JYb9I z?gqP#n%1vJdg_+sGfmrL+-04+Pzy24Z3J|hY~|G}-Xyc;3Jp2` zuiJ2qnrkRg-uGp(sjm17PaOtgTlW`r9(SMsr4pS5lCLlyxzBx46sVd8bz`A*nr`Hb zK~?9q-Nklo8#IlJShmctwRO|E!pXIl@q^Rf!1?M7NC9{4e*>1w)lNIn7<|J;`L6T^ z%mf#0jp6qrnC@E3F$HQ;mRQ!#jJj?tW>pP>h0;#ZL*$e{!r~P-3R-Ji9-B!4H-e@X zC_^Yqbx}sRq@2%~Ndx&I(0 z2XDgUz!8wXG?DinmbQxUD(X5?^US1tl$`Amvx(cr5s7}5FvwJV}^V5a%C0hB0W#z4_rHPa^h?L*CO}$BaoYK2KYw~I;Q7-uSzBg zmh?U?PZ?+EPYO!=$IAcH23oncJ52?&)-Xy#sRBwF7+u2X0$Ldqx`5He!WO;DS9nD_5=^R3yU;)@@(hj82w|olnLG>I>da#$Gc?KW2o+GN*tijoEm zj5sAscufa8x@sLJiy9S5OhBUCa@Ypz)jI51gMtc_Q-g9vLzihA4Hm0NC{?()EG8D~ zOpqz4Tx4|IpAP0jOtmv678u>89CgG-qnpKh;IMT-N9h;^ozBs)8!S&u*?}$;z*q`c z`e35pu|wzqnDp(AE7Lg`TTy*BA7QDu*}fPKvNOF z>&|;c#g?V8o#Rhh44sF29W7Y*P4-Q%BnydPEbU{r{_XKg5y5B`lb?tPOM4H$dgE6S z*jm7rp$m0M-WT&zF98rt_8q?L$whX)f!VR=FhBVss#7n+R&z`a9KrIfcVqeJt=k)m z+6E`T@);ceqkoR|XP-iK=H<@8T}_rSJ#r)VJ@9TEc*h4I%vinSe(34tZ_jb&x(!4C zWww9cgzFm3g)=a#dlt4E0WPAqI&~bR4a)t8aV^z}=hpD@3+uS;b$hYAYltAvotoph zADqQqZ$5y@@@uQ+aViLlhHD2btOFQU8Z_4Z&eAwFg{@(^ZXt(l{Ja*{*8cA;-~c&r zF+Bg0GqcwPXnh^>_+u~!4no~_2S{A3y@HMqS9ukNR<5nrf&1{-!+u3xsiD0JPdU|X z1RVyXT%w**8b+CILyY-LFW~I=zK*?bd@isvrbCn#ll?=k#bol?Y#yP$NJ zcxL3Y9f_NUzk>z~4eftt2a8B0u0CTRuRFn_0mDLx@e$T8F9>idAZm3ZU|3W%M=4W3 z02ef9FsB)eXq1?C!B!t|q(6Hx(n7AqOTgaPn1*nq_j)w;xw($=C*8)2t~(fz-%7S=jQR2tLS76Dky z=W~!Eltr?hLq^qu6`kqCml`31XV_=P*Bc3>(Lv z1<%%DcJ0IREq9{avmbi8;*4dR3der`xA4qweG+zK4Qi{1T4r!lVc%Qcjobg~$FXwT zy;o|)?grN)7Zv-=O^y2eY3Onav$A{3&&1s+?Tr)#;_11%+MuxHFC8ru=eUOkH^5yV!W~ z8SH)2gI8U0SXyVl=Tta*-}E4gU3>E=K35*3=Jn0%o7eZ6g)WzV^}B@;=g{yLTNw1x zCg!TiWExq7o`K7tBWgheHKov_Z%Hy@!W+F|;y^JO_=WfBjVgnpWthU$w$lV|P5L?(Uh?uJtD|E>3-36cM1@u29JgrJA~Bk$(D9vSrCjfx+=2 zvh(@I!ERSZ6gs!GyKEkAlYwpl9YbSH3JogMJ~^nQ5`Y>)n}P8%b-;^jN)dqA!y*&g zj~I-GoSCf>9WQJHSYVEDOu(w4FaF!a6zjW~Z67Yp6)q%;CmHXD$KjHOchh+;5m zsX=g_Dc_@%P>KaRRMLG7U_42|ZJ!(F2Y4ekP4= zP}MbzG0;(+EQnc+uxvuGYb#6Is6R3>NvWZ7b3oCj9a9S|N z?uauk!h|b8R%Pe_MH2Ae#;3l5FyBI<$in)&)p+{-#MmqjXI>#Au|6$w7*Y zTRxv4rKk;gUbG*lULlfvST!nt7u5JcMY2<1ftl;b@02{JT?f}H6;wqcE*@L^!BwXX zi`wNR5R`VR3Cq^`zL1lIkG}sUjT>p?Te%5b5=4+vsuFeM`~?IGTIqO4+Z2WOpOMXB zN2+q6#ULqNP8X1*TXm6Fl`%W-73nR0FuDy&87xr8Yzkat{D9l;SMGBz^~DdMLR!M8jk3WaA z-~I~JUH9PB+RLb$IoSJMSZ}iF{41PV&sv-8LpB~;IXRxm0C0+jmWet-Tnd}g#-$OF zit2~Z>JgL{D*9R!kl7sbm!84u{-c;ocY(;oeLD#2;3jrWv9fDF>T{=n%A(k{@2VWA zpM80T(f~(pT}4?AVVP|h=TFu+aKj2#c3nTw!)dMk=y6QU_du^-3ez}4S2Cf35P zU%=$hjUZ!?D_5>uxpHObGBzlbZH;xtXOqRiW(>rPDpj^)!Yhj)Oc?xc4PpB43mIv% zkP+_*!T24@G<`|hwG-;~?ZgzOJ`|#kXh6d_={3($>ZxBg<+edo&~SuEB^79F?e0*L zGj)YZjAdh123Q0SFln!x<#lo<}uwpU6)J0AY9f~{q zLkfP%qUkr=J!;t`7Wa$6W z2R9=T&9nv7AP_Vui0|>A^BgAh=tFH{8tYSYq;UI>tzqH)Lqc$Lf0J#N+C=^BGJH>3 zz!$oQlorsHMSg-7r z4ddY6n;>kXA4c@X2%bxqVSp;uLKVeDdFI&JI-2!07%HGQ@p&ot90bqSQJ+2OR4-T2 zAh?<{E}X8g=fD)ptK;gV6VI=qm?-StfBgX$p3iXV;Xi{i1rELE!%*hhFc7Xz9fw$k zSz1A^T)A@P%9WwZR`6w;07hi{;AZd~uZv#Pf)rb7fFuf9hOI$V1R+omiCKq?AkT2_}6;nK-bE&sHi9;YbLDDp9kGMuebk z9r7v~7IA-za&R>;JsoXH>MWpmFBKUMhI<>-2BTO26Pozt&|ncXVqK!oU?)P4zI9vG zg7nc{3NXb5!m?*s+??FjiRT^pmKux%t>Hn*QSX@YPt+#3N-5%U?x-0WO`Mo zmM)xj9!~p?j4%7fT8-IygT05AV9Kkzo#xf9*@+i$=G$Mv?)x6V@=dp2Q_EhRei_gj zdUaR6Qor(h4j%o@U%_uaI{w%DKlbOfO!mG`ot%Jzx4?`n0=LV<;r!9)s?vd zq29j*Af^8gi~fx~CmBii2G;HK$ca4Mbk%z^MWgRes(p@oKDGaX#9Jlrp?d4#pYM86 z(q#$HO$_t=Jd3tP`+G3c^MfX$&ikcCr$o*NqAaIqq;c>fL<+~}NPOMUH(z)lQ2Uf2 zr|M_{0>idm07|vXpb*z79sIj()?Wt|RWsx3END=)wKq-Yn7bvt_hFLvBk7A@X{AvpgF+dI2o=BoP^7$ZZq+ofeqc}igGlEXLW_?tW5=p3j$dQIWeg|<6Hcu) z3S&@~1tw*IrD=)f=>(Iqgd&2qjM=Qh+QtkUvpMEfjjFEEG$CS@qlxI&Fi2pnz*Y>f zpq!d33S8pinF3%7k*o7$IN5&~cmC3UjKlB!x4dci_7;@u3gzAdxa;5h`?%qQKmVF7 zKN$lm3fS2i_#)!DmC`8p9fC9s?E2ak@T@?wdoS3xe!SKn=EhosjSDsQA6**nNEG10 z=?c@O0(%c$Un-ZAU;ATRc=G!=^zM&bbHD`vsFzZ8rzm=qIeWx&FynhLe8LF5dD1K{gC&#PQY z?V!`Fp2axhQO}u_4ylVv42~eM^PO(DYGYk2YGDdY$`V>B)XZp@x1hi6??l_7FSPLW zHZvN&=mRnl3S%&xlvrMxVtHwT>9j;qXc*(Z1C6zq*EQB>Gpx_%*r=)wZ0Z03E3l2* z=BCt8=C!-iugVET1@ot?vzm={?0w67@w&hJ|Gk%<>AToS@lQ zgRp%~*3~wQ^|KXr?Vn(}Jg&OiIA5c#7<&&*aJ|(0^a&jM!{5f_z!4n$@ee>xuDt;= zH?>n#t?mZt>r0(z{i%4p3&tzJ%ZW)lcEk zS@N7;{~Vt7Gt8d;G(P!>Py65f^FRHldrbgm9{m)4^^;%1vE-dU{psZSkA51z8lV5# z)tS%z3f^_gyYPSbzx^}(KI-Hz-@-rm(EkPJf9Ze4=f3|r{Qm!G4IjV#SMa4Bv?o|= zar(&5;_v;x{}sOZ&2Qq1|J8l?f8Fs{@Tp@v54Jq^*kgF|$$yUj>fXPI`fq*;fAH|b z_>+J6SMbz3cH{5mB%A{}O)X_Fu&8?|utUU3dzQ{>pU6?ZctYpFfXBzxf;Z z1^UbQ?$7+U_}zye#`iz{>-hMCKz;tw!P;xrn7y#4W)q+iW?hhm)U`wC_Zp403?@b#p#YW?@=zg|0eJkN*HMH)-R={mK>H3=P61(ldrGbe@DI>sMU z@;)Tp4QjLo(G-=PJN1iqH!;dU^}K5+HMya#=LGfFhaK^Ajw+1UMIi+1W1$N&AZoK@ zC`2E{4eE_z(LkXXZsURPP7fYHL5YJQlI|-5aFI5k1rHeMv|WJ!4F!cVf-Otd8|^As zG~QoDcTIDFk$7lYXqYQ$yHYyaVBN5_32y*c!NWxtuJuSP=Jgy6TW6rF#s_JRp(res zOK7-(=4di551GYBi=@0qM>P<#*(io$*VMNvXo3ucRX-C$A{TOU|xJ5;!P z&{z}~eMz#PfkC(o*4-!tK*uyR5x*To&@}Dfm)V;~D-597Yj((226&AI=v&qLb5G&e zXa6O3-Sb8qc-#A+$_e(r^*!LaLUrb4G;8Nkoq7qpv4-N{5fm$XQ0&=%RmRw=qJT_S zu>RbWD0c6|^x)BLKUbF%NTb2?8K@{-+tQ+WO##uy&8sz3apk;1M1a|b1qj%+Z~QyX zEZA6UFkRM|t`ykmCCoVc{jZ}weF}%({bA^9*bAjOcN)@EFspl!>*}tLy#E301%T-k zc>2@$^)H68K@t777xGt zVf=e{*QjgY?Cu-z-sArSk3aK&##?qsi_{ZOJOO4#ed>?#fB%L58h`N2Zv5Oo{xy7b z-yHM#&e_+WefC+*=W_sWz%TyUKf-_eAG`@~`8t5xKZ5`KUwjomd&eBlJo5~0x#gA} z##bN57mojL@E_bi$9&$v9K91CI{w>u{F(WV*@pvEd;008f$w|+zwwhF#(($lFXM0j zcmFfKK<~j{|4%-F|Kvl!J@?!Ly~%aa)eBv=JI>i;tRylrCLWuoXZErc#G$bir1(}c zx`^WpiF$vNL2}dB;CpBk+%*CYrn;TPCK*X_@RvOF(b=`o2vY;qBhNzPMk5UNJF1SG2_-Eyyhi2uYoZWo2)P8Vje5`X9oTZWC z!4syD8shy{K%-;i1-!ulk$ParD}#tF@`g4-?OtKR@=?EIrA>6Qu$apR1dNHALX+}R z78->Zi@p=I0LVnxMwgiB}@<9h?8IaES7J+6T9zy^Y*`b#sG@IO#=mSCddoFrUX4%0yh=7 znmbT)1t6bo7}Z9D-3KS21-?hsMuVni95}kP;|IR=g>&w+zUdAede4Wi{q;G21|ouD z&;Cp`uBDpp#SOS04}Sb(cwm&5Z6STwyBGK4QJk3pH(X-^t?6{Qz(rA@SXqL?cX0en zf#MK=6UXr_6nMjAg2@gM;O*bPA7{^=MRDXq_|HE5A^c|mp7`%yhue-ljAMWQfgQ7Z z@7lEsP1696`~$r1-#Lf>`TO6;-va>5@s(eG0Dt+$-^S-Y{tzaU9j2_D6j1mYPOR_7 z{u=-sdjVgA!reP)9|nNQWP-_L0@fP%>^ctqkN+wD(a-;<@$>!p7e9sX{}=aP(tBLp zIeZswsEg4E>aI!e@S>l_#sSoYA_EiNbg-QU0m;Z~Qaf-OGrwH~j1~^-gdBM3!3C1Y zPkPhZ4P{ILG=j!9U};*lMg$_1BrTCM&Sl`j4}oXDypHoP)F4GzJyPKQzpxACF5SYY zkhYX6eTW8wS4p4-k$aEeb)v~QFaeb)R%B$`xV!v{2wDtmXoU%YhqgDs6^QqBadFft z0VyqTk(O+M!Q%Whlp-h^ky%kl;${dKh71bjQh*$eaPMhU(Snq%SR^e1F|@5Ae+t25 zi6{17EKC@3b*EBQQKhFtG35n`ws{M@Wvvr*2Q3l z6rk?+S-}_uZ8U6SQ8f)pV+dzbrhAy>l zqq5FyebIBt!6{*eG?nx2xs0E)2rye~FkLn%3cV1@Y+Puty0?TWc5Zu$h~UDL-@)2* zPhn{B8TfKqEp%3D( z|BYY9FaO3@@V@`(^*Hk{|0g{2%fE)7+d&F}qx0XxFTMZM_{A^%IzD#$6lXs7EBM8K z_E+%9M;_QwyZ4bJM=+gEalC#X{?42K27cpTe+;ktw{F7xso%kG{KlK{3xE0n967RQ z2Y#=A4j=z}AIHak^>g^huRMT9e)U)I^e=yMNA1I*?!EV3oIm<;{DY6Z3%~I@AH zwEl#aD*<5H0h_`UE~+~9^XVfe8X=G9wg)mZW>tlWkB1(-cL$~l8f#&#bq2!5j3&FZ zTvE0{h7ur0+dX(JdL7yH>2#6#Fq2&euIghqR~sO+dE3h6tl5bdaO@BMIm!b^aO5Zd z0(80a4I#O%aO$g{gWk0pd*ATRZ6_PWkIkF%ZtF7>aq|;4RmfaQRdb7G&X}wiXiei# zX1&4s`5OC=Os}|M^cDL$*#;-R_9q-Q|BiA)q zbzNgNb4D}M=`^-L=gO7qx-Gi)pv!iE%EipL$?9(gUbcK4S*&E)91zLEzYnJMq02&0 zBQc!Eu?L2=4XSz$qg?`#g6e6@bmBEB2J{nuP0BB_U#$^>ZP_Cqk(8RSJp+lZn#y$jqE#t%wYMg(; zqFhnff2YCfk;JRTzkUN34-M}D!^BvjRS!#OFnX`yOn?oUZtO47AeuP<7=##UMWenh zqy8MATw|FFjC#~Yk|wgEScJ+~CN>BlEnKCFG)nU6UZr!ukg3#eXx z8p}7{4`s>(wosx9Y2Qx-Xlw%j(Aq>*M#@X6sHgEX=GDnUTE|K4QFXvqr|7?pwlkZd5clAo;Ff@Y0sgn901fH ztp;s8mmjt~j~74lFJM;p;KmR9EcDXqb#X z9gT<8tDBO=%$TiNlvBM>!D5+l;Y@|4l>+5N@5s+{?MF}G++*Lw{s$hyRz(UEJw?L}pxTzE?#NkOi&WZX zl$zKOP>Au7*zk};I$k}af&>E45H7qRSbIrOuQH~4*+CcTMlve_EX0}0dS4o?XfSve zFe<5`f@v=LsXN2ZUz2h^D&pIZ*rh6IXy|ls+EdifCf|=Ci0M5yF*+6jW@jv({nI(l z{IF>+?2lDIAvpLZgIzc17&mRmKb|fFdk(knNs)5&wh48h1hZ402pC!$=gHFdv zJn{voVuBk!@N-ujUS5%PT)zOR<|y_Y%$Ml7a^=dEYsZwiW|w>upwb@{ZErqW2ws4N zTxK+kMMlgXg7?edPPdGtGeshhz?bw%e*7x^yYmTraW5fZEH+3IA|jB|Fv_4|3sK^d zYLaCNssk$)0)bZAdwF!1CmIj?_tT^xP|(tq`!F*sH<;Nu8mUoG2@R*BVA$@;^@hNd zen!zGxc!h7X$UvYON1CC)b)QE84i;Gx&-e2sfkl?!1{Ec5m}Ot(r&nku!!Qax(&u6 zXv8{m$>>dk(e+6oNK{P_LBY6n6Gp=pGoGVVCA8A6af&u~2Ob~W&@j3@0YOB9a<8D= z1DGkn)_%WHz^)?&b{{C5Ckrj!=i7|(;UB06jI<_b?M#sCrbgX3LtN8Qt_&BrX&i|t zjOlro3?(MiTOJWWX@x=y$STa629u(IQo75eWRv4fZ<|Xm6>SklT|jXbyv_Cor!w-v zUkjqeE0v@)KY1L-KKm&sQ{v{I{Y4bJc3_|N#hx-rVc(nHg>ygnrUNezeHh9V7yBX? zb&7`89o5Sv4aOS=6v31Vi;y$3z}Ae(lHMuZHnBF2KZ`Tp{37-}@NP^G-?U@*(`I80 zB7*6GBl!wFSFT*Sa_yY!uxqltXq#i4Q6H4e=G&C6Z270odo6rT8CmQtTaRR6YmqGQ zc3F0F3+Bxn1ea`-4*Gz;{xM($ptPKTg-yBXA0sLKmBlg=n10r1Mx|SZN@_ zP|B&7q*1UlLA@am2#RHLo;?M1SEHYz)aN6e->I_=C~aw?Wc^rT+frFh27_}JMpac% zN}()^SBfU$RAxq1*Y5R-q6={@(%0pp4odykl1&-f_FvUQm!(}-dD_Rq*0EO)w!HX9 zzXLN}#^Lw>1(dt@=Cl0ZBM_W_{99Oi<_R2p@IzMyNQqn;coBhZ#DQtEc;BgfjC3(k zJI2e!)^nWu&eve;IrhKhy-+*Y8$!h5^f$hMX5#`5zvrX*%bF`!u3Wix40AC%dhMte z2Q6F7w{XI?{?r*rjlO1YA)?uAPq8v=Bl4<^v<+dimZPM-!s$W6%t_ObkIp9LW29|^ z+SZtuR&s7(Va2Nu(zbxu@+3)HhII3@McS+!0cvT$!cf$d;@^gX17LGJBTtu)HQ#Y)es8k4d}41Q@b1s#Z$7NrtxBVJm@_J`q$ZHx1UWT&dS zxVDkk;-GvPsy=@PFZ|v=1%z<(&-^u*rImboU-%IacHjGEkS=iY%YTG@Z+SN+ms?fP zmzG|{eh}^(U<=@4t%t?M&H*m<`7=22h2O*8*S!tPx8A+u_f5O8f$IEeO!sG%ORikG za^>1twKJd#VS9>xdiB7|W`n*#+_Wrsa<8R9MwT%Zc?^Kg*!qmcW=F6?o%ao|skQbg zFEtvm4mOBWxmdQC7E38hN#3LN>Yx$dn(*g}E2pF(1EqA=RM(B*V^p&Ea zbc7i-HxURZQqXYVLHu(y+;bXfU`WRe*tS5WzBMw~R*DoRC^44`1cjit(WFsv4Td-m zmP8d)i8IYDs2H|~3?iOo1d0$arW_f0exVEszg?U{$iKHP{k9vn5>-v*;;>1f(8jBH zkfi=lN&&{Fb->OxOl3BmVI0U1xp?!X$<)PbHx1_1Jno-LJMW+^zwop@)k=UmjkQ>x z&9OY4Ea;G0a4ZmvnCEQOpS0PO;quGadUPVJyMH_T{jX#8@{2I5d$4lzome`0>yGq& z2vwaqiDRGrT@V3Bf9fxx+`S*UwpY9EdOh@X38%mH1?+p%Lsu5Oh-@3Yh&Y(yzWa;k zVaqUu+H}5arUW?q-LIlPe+EZ>;%A_z%h$y|$+Hdc#yZLaIVw6=u3WitW$1EEftT%? z>yE;dEo3d5{yBM{i-s=?!3!neMS26T5i`(K)zN!x>aY=l)=ptkRWnQ{%V?~F8-*!4 zBAuYPkq*sqf1pl748Uwr+1e%eC=XJkC&ob#QIKmdA@Qvx)LA(KL6pYC4`R(8ekE7T&FfU6Ve7j*DKj%(itAath3i{kM)Woz|LEZ{iin~Hr2p{2lyAK% zUucuIFbw;?t}Fy}6VUC*trrKq(r=$j_@0Xsd)E@Wz4&LxyKm@_>t$?O=k-Th0f_nj z;P=-ZTLH-xqTiMZ4J6{M0?(G#?LQUJJdCjDA!6JOd+B!O2{gNUy_Zxx7U5|?hsYxD z(Z*(`gVQ)W3J9moWita(7Bb`5{g2s=%l}#$90mp#6*R4Ph0rY4CCph_?^4DW_ak)S zHzS|_MLC^gZ1ps`klX}N^YN&l01VEUljh;bWYlICh@ILm9rwQ7BUK6xV&n+1bK_o( zP5=||{{rr+JDEQ;OLAeR{z-YgAS#vdemTxPRkMb~tDJl(ce+TwE;KbhFDMqnyhW-{ zmp_)OtKi2a*=>IVTrgRqFY;bfd#0DI5o=75mbh)y(#gDvj}6jZ(>)J;^MlNKBX8_34>6hh zB}_~(thjK()j%6&>lUc}r+(!`>TQz0ChQ>L_egz%mo9pvAbGvVHwrP7BEFHeb9; ztwjs5a^x$}?T^q;VWGpb0&9@v$iM09k=(fdTrvUW`F!%tV;}m_%Mz9XKG(%{J;Y8PJdb(V0<0~1SY+dudo6Y73SF{3tmIk-jAfo*9eSaaMX&L@d z?qr)+NinkeAN`pZMj5aYCQPSaNAG(OHq}Km6LUCpkFrG3->x{KnZQE1pxQVuAgR7u zsqN{f$04MPU(u9JH|UO2q|$gW-aUR?8@P?59(c1xP`Mm{$BZ6l>X-4IgbhJOQVzUz z(Z~@EqZGgX#qwuIXhEN<%~&WT$?S$h&$)%N_2j0m0tk1!@wf3-qmygalcPfrq`%zv z=j1Pcz`t9){&eX6R9}zt<^F=E=V`bz!kLp->#cM~B(U%6-LZz_Ps z#$eYO;#1Zt$;bfX%<8i(C^DLfbaZ%_gcVyx)_QcAe;sFu3~J+>SZ^GV16+~*=*C51iU}*@z!!p{Fp(UOh5Xb z8og_5jfu*bkAtjn`rK#uZm8F*BsNX6{S2p4;*y;IdB>b7?IGbWu_nv?YP_E1`>hG( z4^nR?oCqlR`l-+<_|JUkV(y9~1hKq^X}c(U?D@XZ+b+u&(q#TmEJ`)%b z9j@uTK{SzpTaW#IRjX65R+FR{MV1>PKq>Ek4gz-rja8N zG9zlbCS3jR+Zl@nOBuT;rD;yM)r~LoGq)C|GVK2(i<4Kz+o~1wAlQdu?Kh%$S{5Xc zIe_I?rqgQ#Su}!^m7_Gmf!^0lx?8pAWXri5Kq5Z72dn4gve|a zb0!YD|Ejo~QR`h+6PSfR_wASHjKGTPd?#6DGkQsiK>r0_|NI(9QIrpOU~u%zigJKu zV*F$Xb+XFWP2d@R_q56Yl4OP#<0LMb%(KKeUje1=o-*SY{ZAamcy=jhRV&IB{YU`1 zt)!$cyvRLSX1>)x{M~jMsK|nSZHE=B7AYSULBq;nW zxVv`Lyi-ldZmycdvK})U2mB!U(HF{)e#BO!(bX$Z*)M>*!-9f_UJ?rLjfoJzVLD)> zE3%Vq=VFd+mse-jL$FB&xcg&zE%3_F2+U)GW+@O9Q~gHm%Ik=IIkRFpF3Kw!L@p~< zwmqOA(Z}_Q#f>S|{d}|56w3Xz&uh=AUYwGY{5;Ah<*X$eVsZKDuFiMh0RX+dH~12G zAu9CL>&=58d9&({`FEI&At|JzAozwmBI5D$|gHh}8@|O# z?&H7zNSMNzHFwetdis;g_*s`P4O|c{6i=wO*805eyh;v7u-37_(sJ|&*2yW`pW4Uy zkwo6f1f(K-;mb?5ca;}|otVjXm>A2?I_F&PI+6K)wN}pm(dWzEa7~`bRh23xxawKY z?|~=(X~CK2+16=ky~;4!Yg`f$P*_#_+H6Sz}4Z$Acb& zzoLfWsz2smpC%bh$NdhKg`TGWxbC$FQco?*|IQ#0d|`Uu9vJoZ>87T8Ou(|@qa^L9 z(DnL9*Il!xIE|B~>>4$Mymse#oCU%=DDS!Q+yhMPE~}<%Y}Rf4SORGn+U=AE?}0i{ti3GRY4TYEp$pP z^l{DiIXj`7H#L@5zjL~>KZyGf;k5f=Oc||)?XS?FrsDNr32zxPO=yV!Qnq4x&8lYt=^B1Gj`^8gb^hycQoiTJN8nOmy+dkDkwI<(9UKm1a%1jd93pls6#uS8Lk-BUs2}SHzt; zZj#)nS7lc_Xo-=`lEJ8p)1HA2^kKT_(0@NTMKLAwibw3{qJJpoZ1yd+n#6?@Onw;Yz(j0f7iF- zri|#XGgE&yVw65y<-JSADHd8M=fA=4wekqZHvUVNWS<-B1&ZqJf9)fC<59&GvS>YJ z(4P$PZyZcjLIeWO{f_>wIkZ*50{8Xaz5L6rv-N+qd?&Og{J6Kg3RD0_1v?H$tcl zY137hS3H+T{ldTxEuEe3RAhJ!WgK4M!UV=W(Chh5Ib(tZY?55_32qxqWLBJ>X|pK) zQF?2(+PeEf?C0$67{YV3r1pHX{J&0~LH2trA;?EZ?03Wc5pZxz8BxN36S zTcK(9LeTUU?dr?UdpaMVzu##Jz_D~F@i?!_b>zft`-RfHU-BgK*9%d^6FEr+VZ60P zmHtc!TUP~)n~@3HbwxB#F+&@fwY#1!?E$b7C)X2%S!ci%BLX`TTc~+cSkCv{ZSz+S z0*CTL?aM~-3HkY7rARekTy3<+E7IY^G+|8{QWzZ$;YG!%VfLtlNlghceJf0dYH1~K zXb+6bL4EkpQ6~!XzEMr&896r{zpdriDsHo|x8B7+=Y-I8OG4#3NMz3FSAJBgpVT=b zA!7;U;DhBE!1Xq`2xQ$vGU+P*o19#9gbRuL2+uASR#n}RY?=udkq4cu#u#e)w~pAT z2yPy<7>KBAUSm5!nh+y)IMgpA>0(H%|HFV|S?IpZC)_jJ6uIclybu=^TbcUR^;xoG z5^joM)vlh`7*iOo1OQKyZ;QaG{lt%SAce3PG?uu=>)h5(raPKwbMYLXH8Qc2sjutG zl%_6v-%Tiux%7OEYGjN)E8zUO)R~$l9WGoeo1=gidR~1n8z^}C9vETs@KS*bUzZm} zE=V*G;p!NkbHCuH)R6(~LD)h5oO?tirG64P@fAvO_=Dtc z3%tpzPZWBRtAh9>2-|*(MaNEo`wF`~I?d;fL)*PsI7pQt3xl0lpw?p)`Mk+yOE*p~ zsLM0L>B-!})m%}CO{-}XF|iJPEdjryg*9$bvO2x{(rlR(28HB;g&t1{W=a*1rm{ZL zO>-f%BZ}eDS`$R4SYDjB>VYgp9@ay=>X)WDCm_%95#xX-2+Qfp8d*c1jH8pzP;vP-a}RCh>$9plxW$K_U3$M-Fz-rBGiFpM)UFkug{s<cVGRN{q3zd%U`zr-Mc0##Ed9ppi!5}hZ8<@1zv2Pet1uAEp-Y2-Qgmkm_^mz=n3jay-NIz*JUHrv&G3d@jm-)lp}a zJmV2mzDfj7lLYH@4td|{Cv}_FqLaQgr%gS1agrUXI)mupCJwt%3EPkW9AAGlEPEHiwj?o;NniuW2%ABbw5GzLQGk)Aadin57>okQsb}1E$pu69XDh!g_ zcpktyBZ?8e zty)Xat**qmkzN*i5{n=`ke`}uXz1_TaK<4ttcGr3;ZZP$yFlBvg;rCZ@?;@Q7 z(6{M32Tk<$0P&6BQ7}LQY>hm9?|{=Br0h|4FzhexE7dwFfXl|XlpYxU?ed~SOn+u0 z%_#&?f5zJlUPi($M>*-!dUG+z)LRWw~S(tx!vazsbMcXGG%B#f|f8>LxQc;T??b{`i=dPnmf zLs@X=`sg3Z#rJt+%!SLh$Ue>K<*8C|-q^Z6tmSJ!`|IW0TJ9oBVrd+pYjR;lEqA#M zE?StKaBRq!=2P4o4mL9KFD0i5h1~$aJ7w%mDm8Z}ilcVH&3iGLn7X(DR$Ve=ASS{K zDp%M1#;Hry1*sWankcWo0W+Cuj_-aO7DiP{TN8ZV5643Njup$ThCm3{CW+bQB72Cl zkp6U~g)T-W-^W=}#B0O&zqFAGr$k{CICI!bBYWzEie_QhKKXcA7PA7fv%5Lw$r%wq z<6(3AQ06T#499cSRrk5lVmGA=1vUy@ZaMqtp>XmfH-T*YF4vg$fB+clXROoZ;3sid z#R#%1y^)`t7K>m%*Rlvj0f6i^Y(Cv3cOp!?G4y!(7oI!8I#$vU@voa_dSuov5_?=A z&Rbq0d82&zFXJBy4a$%r90cdo>itUKwOQ*!RT-5Ie@p#~Irf)D>}Xn5^qcP1D?$_F z8;l2^vPPj=={dfb#xt1}Z-N(37H{Ak%r8XGgY}xD5GzhQkZzOtAnz_hoslX8XksSIdTV45WM00Fx5~F^T6Cd((rjN)n;fi7_ zhX&{jg+Y?$gJtZt+ydTJ0&rt~d~}@{c~#4g4_yWy);)Gufpeil;^zDK+?r_43w&+~ z!|mJ81cQryy0Av5rcJwp^DyP_cb}CciU6#nkux|{q0z)s~y`_(&hoBoR#T#K*yOmi>Z1w4m(FpBOsc_Wbf=5q#`Z~ed2 zEgu%1`+rDK!sB0u_xuhwa+?~zM=t(YKWwe3TcR$hs*jkK_*nfb6SF>;)NL(A*T(XI z1;{I%1ifyx7NZ5C^Qb|`ijxuH8&bz#JWUGfa1@}CX_6&XVp*~bFa#|H22OIHEH@Id zQ#d|UhF7kX7N9vv9N$k;ax0&n#+revh&@DT|2S!k&axV|o!e}*+w|m0G(!9>O#{n8!6ARhmv2u95r!CJ&7W-v45a5Ith+4W&UMMAzn>GWtY`Rx5|^CS zjyE&%b`-lHRy*cL1fkq=o32SqXi4tH!cOML%g7~N zWA^l3Jt=DLZxd1Svh)77f#MYi6;Tm{HG^W8`i}W8F1Y@;db|Jmw`}M^SOTrD#|7el z2t1N1bx#zWX7;>)*BLz&L|MCw;}Vx}@n2cMKBr~{nIlC&6z^Net}imANK?^9@XbRU zNXrhelvKco;xW4sF#DogMhZ*q=vvlZYZRE&Vyil>>8#a=a*_7 z-BOjO=$RDuW{@{L^qTgpTT!W1-fRzqoy#RoT4?5i4Sg@_}C#MgmBUjP9s0a*3Q?j+umFab)2)!6W1L{I#c|%jyP4sQN7o7Ys8H_ORiC* zR`>Sk3}gfMc6%}I_#CMrQXd9{8T zAu;bb6}@4aofH(6&ZL_fOS}b*?%7-bEUV3zspPsZ2HMIcbq3NfN7Q9ew9O9KqkzwB zD$z=tIvt~HwO-NfWVYs}grn8MI)L#F{oh=driqi%BXp9-o=Q4Zs@@kJKF}BNHl3ep zBi>h{7S zombk;7q>jx*%>zc&JZI+fQf_ut7bn`Xr-cI%yt15+*MK0j(2i`D14KiEk|<3 z>~X;l#n6t7Y;^b6m9U~{ssM1248xc*&M71PM3$PFhi^Uv+h*5oGsZu}{Z$+pH`k}f zj2ZBFHXJJP;a*6f9OzB88r!rI0QiuGMH=F?FrW}k+3Q21uHcQeWPoa08Et^aGcVQG zBd)g?)2pOBZl(y9D;w%N#%*yosgaYVHIbYTZa)aSNZUDRwL!=^`VhpMl$HOTGq6p( zINl>c_MOkIQTX;j&xa(xV)B<~VvWY+PiakGG7?x!d*VoPv)%%W+f&X*;^h^+*F+X~# z@43AP0%^+U(8J?Fh1r=mxH-uw;idZ9s!kW937hl8^$$s1<~Ih-iZ5o8&kEGSbf-hd zH4^vSNT7;@NDn>xFYcp128O;>uPU(UE^8FV2+nCc1(Gh9*y5*bg?F|;)aWqva%c4W zu=NQ*s(5s@M|b&Zu6|7T{t`X=ngVjwgZ~_Eyb+eNTYEQxpI_pX%bMPFZr9VG`>n-+43(TYVb3$7mc?FV_7f#S>^pvYZ460oXJ)99QrvS^dL}?q z3xQIA`k3syJEj5^GQZag|6KUp^De06WPWAod(3-GDDyV(UU5--g}-#>*|uiSFeml0 z<{{5!`W)H(evJf92j%8eX=?F^26Z}zq2NMHKsT%60UX(={|&Dj)|Uj;#izl~3r`OD zbzJL)X`hY^d(8ZIP2T@(nPO?^;k?sxz3VpNE+*|Mp9TZ8Zro%1R@u%}5L2lEe&7gTnwztg$*GDT9lq<5FT z=Mgh;%1DcCGVaGzaabNvErw>C+>IT!I7lcWco(GaR{ppph)>6>LghNC>?)4iR3~_q z9DQ@Gr{<32<>MNuarDCa%^dmS($SJpWhD)SP?qqOO_nHnObzlqRY(siDV=aAIgR*L zQLLi!dY?#QN*g9Mwx>Ct8@)FA@IGH`kBqCx*zrXJFp9gBs3ws>Wf(c|In+-`mBQ#?+o_oj9Eh5wz6M1k&HA$N={ z0bbC>IZ*#?8lT*sL-F42jtrkWG^>p1jyxnWWC0~eC>@y$${o_;U-fvp!DAHNF@bxr>P^LvMA=-Wi%y+mda27EOk*Tt<%EyVp&`$Esw_A@P!KIe z=6_}K!Iu2ogOrw!O2VY0DU=fJ-W8UN%=(svO|~n&Crqn;e!AvO(lA@vzku?8{=UON zS{+AKMp!SqA!9~5a9ddxq_XaiOg0d^nj{OJIrk{oqO*CQp6oGkL8|8 zyBW?zf8?B?C}xpDYEDOfgRMZxLbVu4tY8foCvt2y##NgTckk1DNrOI-H54bGIGMS9#Ze07eJ_ zjMAPvvTiD-El*uaL^2BGELUzC*)#fm(sJRp{YYv)wlPHA1ZRlzrvCf?|JZh3#|58e z$+jQ};f#EK@P_P-^f4`;WSW!QR=$cM@JxT%>*Oe`G=Y9QA)ug`a@^2o53rCHYO~J-*jxAK-LKAF# zE$dDW{z^&6^R-hPbbPko;HUKO8`Us*1VOrBk^S{{Ak9!NNxWVU^z^Kt^VEI_@71?5 zy<01decZ284f#U#TGb|{EO`w<7vh{!-=z&(!1P6ub+HPKY~UheBi#>&y^Uly9~0Ho zfzt*n7YEX*eHuj$4bQY1!b#tLbrpt?-{5lw?Ok+wzIhymBSF}x@{`~f1i{E>-2hmvKS9@-*mMBCbr3teBpSZye zG(i|t(ZPU5AZL4pDd<8lhc{DZ_js>5#xBP`9?cdJjA!~7o1?72Q7ZoprUa_15=lXx ze?vXn%Qu=L=4kxICOM zLRgxI+d?D?33*V3-J^aKbKeZYV!Hd_$oH$f7GTPP#4XLg{Csdc3!1edw=EzQGkDo@ z`tQb7>}W}*(;ekTa^G8Bu_is9O5?+*n?nT{?1|W>uH5%?ehtV__}zy{Txw#6LX|>j zpP6eeB2j6b81I`$zqhE@?_-g)OHnWS_sT9LNnd;hjMApnVOx0562tH*siP&_zDjf( zJ|#)@JfgC5CX)xT?UPTHDG%nLrgR?We%OI^P$@VBO8?f7W2HG>zOCzGe?6F`xwSSq zO&1Ez_u&5W`?eorkHA`4ugUnCZC*5h1EqPgbNvFqg!Qt=%BCS`YjSK!vjwA+!7PD-k(y@C_<*+rH=uEPIOA>g~{pT z7;s?Ae(sBJsmI;mo{7x2*hC6#1 z^CfW3G8JowJ)qMzKg3wYz}@evu>ed*X?sT%5qJ4fcQAZoBdyrU_dxNCSmkIZiHVMcO4HUL< zgx}C`Orth4`R-w*qkI1nU<50($AmhM#xcd-QL`9?ib9!8r+wn3@evyc*h&g7usCX} zrSsufQ~6jUEA|c~h8WOd|G6kYV6I9{S_$zo0qQ=TBU!WYTB&>ySs1{(sS zom@F932Fl9s@Ag}zi6@FkjH*tI*-n)_HkJZPDWDsuPlKx4idV&5ek%WuGIg$Sn6yu zqKWq1G0zRm2-Hjcp|BwdLYb{F2tEiCzHVqnkDSgcbZdn!~xu%~R_1Jjr1?qF5;j zQj|sUa*Og*=6+}Jbc5fo2K;Gat}sKL{pvGKJb_vJ%Cd2(riU5_aS6JdOCLE`uC4bo zw!GR53M-uV?;czyvv*DlyYJ8=8_kVGnLM4Zdxw*<-U zB+ouWFh!M~PPk;N!uUxj6t9Tf3ATrcaR<|T22vd)?O2NFs0W3}h%84|_!SpV@)0XC ztVWl3E~${Xm#zYb^gsQLk)A8T;0Q)KtXLGT*_^3-3lN#gNG)|+ zM8uyD=UsB8Q})xyB|C`K}DE`#Ii`0y%Jy+7Vn1&)*SKw>Z-XuY0@~Ah5PMXvLA5{rrP9K_~S1bRjAP-{Xtm+xE;jGii zxVsqd#|R?id^P5?q7q8nCe#U^2%{ti#cLDrZn)gP02whYFV)(_-sEEhS_0 zyV7A!tp8H>A|X6NKN>q86)8%~Q`s9APCW4y?Pu=E{DPV2gt_THL9krNcWgrlVSH?v zA>oVYm|*aU@gUt`a-TE>o^d6bAWmUfmnT}agThqvpEI5fL-ZWtKe#;pwDQvVQ{z-b z*qdtc0ET={39W<#Pc_11OD!3!-26qfAGu9oJc*?i_xwwe2NXE7{>oZNy2NT|TO>S% zCX6Dbu`;A`Ro*Jd=8KHgjI6AxQtzmi;Cz5l#?Mcm9f&sJ!P76AGg_ks8p6GPYL_LeBWWcw;$usK8i&yK zR_*eq?YK1Ij_7cOfr8SNx|S)$xnf#HpTTxW5APC8Y#k$K7K`S9?6-5fle79_&_yX?Z_ z{TLX-&yVkURO)rTU0$@)Ge^aeqJB92s!r1bW`j}&GHGodh<_e^qrMQ3&n7x3 zQj(wPawZq5NW7?Y>1tE0->NPNQyXU zf!!!HZ{DXZ;wmzj@NSNdLL-F3!E4nW%i#PUC?W6>0vi9d6iVU|=_+HovBqoOqE(CL zq@c#x-^zQf}CsA#*TX0%EbP0?cUFqwY;6pjQYu(elLNkm?|2jj(*RBX_vO zB+Ls*(I^tChUXK?+0Ku4{PvCW_Jl>In??_d3$sGE15@Pa?{S|sV4qKHaGoP3@Oq_wkB+`8p?g{6sN88{_5mKkE4Acq>G7HCy* zDL0GGTp6QZOQRGi|8awIh^eOmEK5(Vzv5%|i+O7rYBs-5A%fLERX8&z#=C&m~(UTSniv+K0X}fTc2uT+irD`uJt=5o}`;j6$EqYY5ps6C7 z@M+FBcJ}CR9Z`PgMZb2ntfe%H>AB$hU{NF*$YS`-^h@vgkb0M;FpS)Q{l^~(p#NeG^0F1G}eoEip;be=So4Vz{BedX|-JY^t_=mwUv@;Wc~ z@Ucmo=L~0F;1cD5L5}Uj^g0}<&o{p?`VA~QpReN(UZI26#j?E=dEX{QkR+W(5STXm zt?!jck66>;#^#ecLpsySN9!YA+$#PL0JB9==R`6xUXVw5I6>rkn06RwQ9;GV`;}H5 zR5#*+7*Q^Ye-C15pmA%X-nGZAX4lZ{N!E_YYKAd^-La z4AwK3;`byKAGx1N#k6irYIewSHBGM-z0SIQ=%VQ>A%Km|yrA$(6LX zS3k-dySM2eVhe95ma3>dSnlRsz24aAZ01Hdn4amRIy7^~D22dTT6l0Xxk>GuUP@ot`l?R>>$` zzBJO&pUHnfOFw9!(2R+th7mUc`eW~sWDDLf-FZi27@-6Quvj}19jGe@ML)IDD<(!Q zGwXz=M9AXP4UY9dX&~xgi z=BWVUMT@B$`oi;?=g*8jBG!{Zs5?*_L3e8#7N9wk%aJbEwBs(7&UdOCVzwJgF=(hp zdbJqCU?ih!*#gvNS9jCncv5Irq%b6iwc!v>X6w{897aCeAkN|3>iaqmvL zphtbgEj4Ia;78CX0@|Q>X{A8J!leINYMW3>844*!<1{RqD1vGM!yprg?H80}+q5dX zhVtu%ts}@Y>TO833rQ@U*S4VgfB0KCq@|j0{p)7~XQ7JcRkHMv7THeF;vjyK!gBLn zzWJMHjLSX5$3a-g3g-u4w7?Ci$7($Kcqy9x7~hscamb!H(DS8<$N_i}*V(Q~quc{2 zmWe#!G_Azhu^}Hf!tDS|RZ_-CsI6cr%PeJ%sj=zXmqn0&kt??ehda1k43nxkf8s?j zeqq&lBS1KZlpN+J@-W$&J0pJ8v(O-51f9wcqUY5R-ww!y*Ky%} z>pq#vXul9dV57DeQJ4j$RdU30ACH~t5f-zfNhGc<98Q~_VuBJZHG?gd07oetNFDsD zlL6C`j@z`#P~L!5^RJZM(Vjc-Gbicf<#o)PF%`t>UavW`S3DA*XjC6x&cj*k(9IZq zTWg(M^cn=E7+06whUB2UC%4j}xqfi`33>6>L*!FV6!#h&Krd}PA1yO9a>Ww`gc_=p z^X>LG&ubVp#zOP4@cSc=YQfSMV>n$*Fg#)1Xf0p{e~j}Cry(VG+Jx~pSIk*(7^L9B zTB9+n-AzIuU?(fx?`lb7SMZ`m2$6l$gaVFW%D25qCoeaaiQbObw_=;{x-R^-Y@ISq zCOfBVnc9KmKC`ueNp3O3?()4&T$;vBEUc16Y~IA$@hnfdXCvv3(n923*<(V;traRG zJOE-Bt%;>O8H5~53Fl~I-p|~V$C%QVXRvz_MKDRG*`Xi-772ow(o>ImZ_q`7gRI@h zFTHP~;OGds8G`VAEp5iw@3Sx8(tQJO43asCJ?~=RPK>N_BA)VSr6O?h=@OvQZtEr3Vnrl~BixVamtz5;tK%u3q6=_2#nXO>Xfppq5 zeoc*Q_r!S7gPQj9tkNg3z#^2OM?et~E0q<4Q6Q--rUxkubz515!_uXivY>E?)#|0J zg_o0Tb^G9-Waad+vFJXOoazg?5T_6uf1Gl=TxJ}Pjl@rbWGn>nv-sP0Gm1?prMbQY z_FF})VX6@m%CNZTu>5G8vcb@rU7my_orS%81*fT2`*j6(^U z)yb8{GV*Ugc(wj~V)^T5&lHQ@@^usmqhEhfV)Tc6NT=^Op7Y-+!;+_WjNF%(T0rjo zB@f^`d2oC=hyEH_?WG~13+dId{Fr3t3E8MSAp0NL3=buQ&9YKp~!(BAlM)+3w`KbAdF-pmo2H@JXQAwUoJ zmlo6=YW9-iy0)g?e1P15r4`8)s69xeKKz1G9U*)H?6)2Bd9-u{jdXDfreEJgGtOU~ zkj{}bUvw2^$Vla?>=}gX!-SgiJ&`S5>O|%i75L`O+y5kt=znQa8pgSAMawgznl~c! zhP>Pqmf0n@KMx#oWyZBM^qNr?z+xknF!A|i9Mr3@cg80xuZ(PMIm)knZ&C*hTU1bG zqOI}6tWhrPqF?s~R`0G`Vu^j0Bq1tsw?LWfx2s8U2*L^wO_Vi}#@MtDlU+$I|Kgg= zK9@pP*;GwXO~RwQgu`&+gIXDCHCB|ZCQ_R+Ss&Re&}Yv6qqy$I>eZ1|5mL;;K56q0 zKU4WGtmgoEMv4h~C~=Le?5@w`=l-%E{-va zM4(J$$FsV49rLmaTN3YzauKvGBnMz!7;%_{8FRdZCj8?S{h<^#0pR$tGV&$oeu(1k zHuCmZB)k9+4dgq=@dML`QhYId5V8OAO8W)EY65~Fpcu=9np7lUpe}b%x7BeCHW3P= zn4lYBy%v~&Lv2u$(dLnrNu5y++VQKpl%daraC4*nbg9s9Wd`Hxf zo)FM-WA_Quyb*5CsxQV@-hJfMTtlB1!|<&t72=IgOk<*_gn_EH{Pu_Ahv><)X;VU zRd~-AtD#KcjCMu2m}wQ(Pq`m1KFJTJC~2ia0%Nw=@iKhLbv1#E&eaI@T66l4x(jlp zb4+Q0Ls#TQuXvflaVAYgYnPAP>!fH(+Kx!$ceJBm^pG@p9RS;IF^cmiAT_4D1f!|s zxSZe=ubzvC5CAPq4})(BX6fP6*eS<~&=%xj#X#-C$=`czLuq?&m`2{~E1l-vhC4>O z)Jr>Rr;T~PguSDMInhu*z?$F*!|Xk0IPrUHp^R%OYTJq2wS)J82}wx4mxo9}6-89> zDEQVKHN(-_AK|6qU09>Tuwi=GmAqdZ0BHX+wlr%$lXClF zVGIO~zJS^ClbG9csO=1mZBW|^EDajlz;Xj?8;CHP0F#pTJ@P6SotWkZgIui&7*k*> z`!HR<7xR-VICIv*+A}bv!t$;Hd(Irhu0w#`Jp-2KAO^_NXp)iJ7z#MQ0rS`k`DRD1 zT)C3-kVSLjK{Ri_3oGpO9GbArx4tJ!iZO!z26m&D+fHYNWlB=8%E_pLN_gKZh>rR`If>tWVIjRK63|fmu z40OXFC%tpp0WaYizei6~Q{C=BqPvx7(Z);0W@Dk!(#@8R0~1N){(a~Y@8q%gzHmQ{ zRaCZw$Lue%LyCh+9*a^C5m@WgDBXDhVM{->fmCccLX7D~a)%GwHOt8tg}E*}Sc$NJ!+?l7U*yoT7ut3P`|`qlwpDq> z`Qx#PS}!C4sAoPm1Pbl(q4kO4BxuHi6=rZB(xl)#`JV9zD3cAUx6)lwX zG*Jp)W7`rX+oOA&?izDbge)TPW~W_{+d`ON?oAzKPun&n-kYZVz2h}AI8ul6Uwhn& zHy{%Aq~KL(e@fISF1bg%S4)5tlC<=Uv>bK7ige&j1Sj4vCG0Q$gyJKbrDLuOzyAvd zWfUjvG~OpHN<)x-SX@$HU@Ky=Vt)ivyvYL= zcOxU-aAEP@E$Jr?kWRehblUEW_9l)Zkf!!=yrDxrd9c0au$W_Ay@X!_KwzPGj&d$oKUd@I%N6Q5W4dCX6k)nz zv9vLTUTV<)gUIV#;1T3E*UX2mPrh|_ZxO89(lD49FanvRh zIpE^biMZMT>bevCtQ103zxCxB|7#f{<9Kg^Rk&#{ol=yqf(bI)SJYKx|g~)ljc+kSiwGPD=A#U%!E5)#( z4Jk%xvb!K9@&m{)=<$$+lpl1pDM+p*sfJyz!SfmPWC?200Hy@7buCBQc+jHTL1RZf z)E!VE4w^zgJ8i9S&UfQ-T?WvSDm=I|VC=U8rizws>&+sS%h-8~5~W9b{7IA?Y+D#Z z1n!;kgvXXq;_)NSBi(rh1KkKA+Elu5H=jkiX>5IPyy%*(d**1NNSx9F81EF~*Sl-9 z+p1R*P)-DE`w-omr7Mb>0TI>ulcvx`&`EaNR!c?a9Ma+gqC}}90(g_vps;MuL)&-{ zp9U0Lc-VH^hdA|1v)z^;=1zMMv-Rqh)?8Pt?fS0u+m-s!(afFpVexQA5}y}%xF2sE zq}(z1eED;J`g>HBfLtP;Vvw?c))2N(+PLpvXnj=*!p6_L{WKGd{VCj2@c;a^i=Ph)m`z{6+R|gFn>p&H zLTxJtUYZJxtx?-Knx;;`OYO~deIgQh)vr$_GTOj!=?rn%x>g|(h&ct`^JVO9egf0w zRj?J9LSbpO!0Mg?y!$xj#RiNu&}3n410C)PYXw*f_0l<%Uw;y`G0%65bLGkfKwxh= zfa+#ZqD$)lq(v`}OU8Qda-}a0vWiT)r`nt;kJR9=0$f zc)tW?47;==78M^W5ms26G9^`IKSmgM+Ai>5^%msTOrdbzaIyMP90zo8hULG~dNrS921NF6*| z;(!;eM@v+S1lS@02O$FT2xU?rlRUN-ASh>Q8d_U=QbS2xd{c$N=8nLUfE9EA5Wp?O z56i03M7*F{lD6HoOV2<)-Z{dR6tH;1Ritsy$$VW!3&;5+8sU2H7w($yB2~4-_mPe# z48>(g;Y-(CH#teQ+tarULurt*VCz8%S+KRJ&!5Kp<>LT1DEI6K6%&vtoN5GcanR&i zRvj#|-ELD-4!S7q&N**KbEkaa3UyP1x$&x1@i&@W8WBqgmZH-t*ea`> z2j1DkpF?ru1V)$8W&$x2Z0Hh&nV^soN(e00H-Wj&YU!VSvD>1EZa^Vz-?#!lR-cA z1|R8NGADZu7kZ(ks0Qj9(p0e396VbGY?CNe(rD*4k*MR@qE#n0nv#|xMXe&Hz1UIF zzeOn^O(q&sw4`bl>M2+jwHL)*LUn-(_1a>Fz69Gm()IRbkrc#8Oh!mkN0?o&y}M=) z{w|c5>QYQ3V&!Gy>?HM;Ikp=KGZYi72QtBQS5XUSh{zl8y1Tec-aMBD+*D}l3SKs?7M};Yg6lzr*?J{$Jxf4U~bUh?l=avD> z;JYRLHQG!enfz>zyKM_r1SJwcjC7CB$#bKLt|Z_I=pHi?_yVuopHe24NuG*W#}4 zng|cgbE9`m`;WtOF*Mh8=bq$xfLky_zNOR|-fHh#!XPmqQ$Q6Z%+j(u|4f%bx_~sb z`@Eg>HAzFV?Q+J$yjQj;4_~wfDFaoMXllXw%(c?&+CPCZLG>hqeIo3etzTTLdU4ky zZIWUz_}9kItJ@n$S}TxY2w8XD^^ij#4tj{2ZoQ{V!!??w_AN+r)J+W#ph?4+GVy>T zDAFKO(5%61A)3MB;-Gc#%2C{=6rq1C;OME7&y%@w=oe017sol%YD}@^ z08}n!o)oksgHq5IuW+#&ebL3_EB)|9u8A*Qe~WkgThN6rsbQ{@pEY1>o#9s*~M&nC5&Z;3h>7IXlljLyq8#mtpH8!Vlj&nYBGT;Cs3wzsu!(&(u8#Y z#@)*Vkw&NGND?`^-*z4KOETEX04CSA4sD5dg(S%lxpF}SygWhmp4YkP=T`_^h=FDboV^#A?;-HS!Iedn;N0EG^^3pk z(KBHAMZxYLdX?)d0Wj8izEtnL2j=k?VSex&sNo$w7BFLZ+}lYy*mMrsMEaXZq|;l4 z-8*u$_yTw*!ISNNK}J897PgG16OG(uvktbPX~?lc-v#w-AVw8#pETI0Xu z!)V7pN)pco>fF5+uYA!OQPo2JR=QKVC@^`+xuUkkNcmQz2x!PpbJHE5p+qqQ4{Drw zAS>|@#=#e9YS_j_gS)n)38*L_rhqa|0!~UpSOGd*gepYWLh-TEDe&rgm~J1aWbc>j z^g1FLEXF8XB#*m5LV9=V+j$f9OWK8!C}qNNCbaTV(vGs21*TFL_fRPX>*fDZgQupmQo-PFq_ZJA2%xTi|HzK_kK^Est-T3R)mZ8VyB z32yY@nNj_s!hlgCaB;_3uNF}bbW|HH!1wVvotDga`ts`;lAJn5=9}L3NmX}A!c&Ao z)~yp-n5KxLze`wl6~T+NHw63uKOU=O0woOMx&I?-qgk~7>zuPrJ1ucXiQ^9>@X z<7;-?iy~O@uqI6>lF*8mnCr5nJ}}8O1Oa5UH=T7c$gXv$aVG0lL#zR@ZPO1qnEP@^ zbsK$kR5*8d|1hm_VX9FttwHF7Ukrk&_5-YwbLYs77Lw%i3Hy@3mZu@w?TexaR#{xw z{Vl-M5s)}oN>Dy?nv{kX4QB1HXWA4Z5wA+oZCa5=fx;yRdI$(B)K#iYnFYYw} zfJ@-QZG>}o0eU9b`vYKd22K%ku>eL9n%CU~-n;C4t7g@XZKE_`J5;cwz3{IP5TpaG zPSyZ*aKUg;=KUh5H&Bxi7_+61#ASvc7YnLh;Wuq45=tOTC(*)7RjFgPXWfOJk9CA? zz)cOQW@u&`kh*d*S*@Zx*Ii_}3jv)(LaUC43qh0eu!TAi(E-Gy7q4xbQs1wot89rE zQa#Y3s3U2K4`WPZx`k*6M+meKu5@h~#)03qKP&0q(MD%*74FoFf;ZBIZw;b25LBX~ zaW1oT5{)=SLvv8dxOv$6*YG|s5y&vXT7g!6H{kRxwpZGSfUSjHzW}Q?pvoz9Ie`=f zl=plgZQNkNHOPZRx%8uWH{W@`h^Jd!)7|z2WW@ z7{tNkSoCuHGa1k)Be_)RA`6f2Ny}rJhU8x$?$ZPS*5CPV)09%s+)s&V)o@)unsga? zL3&YGFAn!GC`n6`Bq6A0K)c!ZPZDF3W^PbzOxn;pcWY{3pxv{z=^WdkD1k0*n@*fh zC13kQiPU<(ce1FuD!S2_?_OFF&{a7q8n&sDz=nw71hm-1|HGZjl2#)Rg4`ASO?;F2Al(F{6jFwLD}YF}#`>vmP;1!i zOxnqm@z}5Zxj?M*dvWPXwvC|{@0pW+Skbpl;rK4Xv-{k+VQvV5M_Prb0Lo60-Zn|& znS-iw;GGoqbyIooHh*103JMxz!%ZL^e+IRcQVLoOSXmU>Z!ayaT$Tt*8yH)|>Jp4L z!n;+zD4$$ZcthO+Mwci|>0k`$2xZj&pS?c`k}OHn1F`S_^_jW(?j8{y8CzyV?pc|& zc6A}U2WSA@Xkq{YAb=TgE(8S>p^(A@ND6u3iC2nHgmWQ<`hCKK*! z63D~UfZ^}wAj3Mno!(Awr?)g0HU@5S);B%v!_}PJ0=pN0^=}i{A^|R+_QowB4PoP( z9&8zI3eNrlFs<58oaE*N?!qb#|IQCE{NZn4KDh(ntC!H$NZV>EMX7b~fG=_^43Ro+ zTzhC_poPkanaZ3~12xpYqtjrE$dn@b(L7}6gaC>ZJHI~cNFG$1pZrhtcc40?xqt{8 zq`;o=-7*_e6a3~*+7>ct;o2j(@e$n7As{xzDRL+BnLs8c0QkQr<6P$S_`=UcryWr? z*43NvqB|A7r#_&iWV5KzM5XUQFVGT>#X4zc3b+!PHBxCk&>qRkg z`l5QLn(Lw~Mbgis&KeQyJqVqym`rUR0F%QRj1LD8%g|mjnWb9FH$?&Cnkf>EggKro zRv^458>G2EnWcuWQOl^ZmkfG8ckkR>NKK_T5iiaE>>uTn+$hOb$V)V-ma|X^(}@fq zV!?Jlu{}C0mISCs1p0kXap^WE8?)(29t z2U;wGr;7iZ19>J=V3|1Uyy0&Elb8)iycsSUq~{Sc*feO{F4I^3JH4IW!i?uIdG-mo ziz_~g`C;~50PcMYIJiXM_A`2e;u$mJCBp4jft9xeb9Ww+^&$dT!T8k|fZuxod}|ZK zAHM@S`sy%W8fnL<_3nT#!U~|JGVkjaqnScY;Rhl1nvTRy@QAa zOq98&mX-8iMaLG){W{)i0H|GN+GwS=TlaZ|zW!kb+HrrYKrvE91|@2~FRWqPL`N1E zbk^3wjmL14L%8t~(6*s_!zDu{#wY?imxu=zi2Vmy;Pp0!Wl1r32{VGK0mjBrqkK@Y(>P81^g}YXh(% z0%yqsE|vl-#s#(v;H>qV(#V=&32gVAdgKoG;Ewja-^*|YJQ#x9z#AY2=@HlghP_d* z23|-AJKY zGy8X$n3}iQ7mJ+CVI|LNX}$@OEWS7_89Al&BVRMFG7ClmT=IKPX173KymTyd6-#CM zCl&$hq{05yT=rf^W0c%6dN(F2Pp~9%N;#f)gv)VwSS`VsP`gM zz;7v{g`q%o3Q{K&Nk!o}48V$#5VXB3wqwY22mo&yZPZ+Gv`qxUp zgt+WQ7XA|#3~MC=F93O&6QpAdtr=UXDIe#sjsbH6YbPE+v8|7Z9yo7|8~t&j{}G~W$an?|H=g+t z!4<`Ti2#fTUWVc484Sz-4F`!5H!wUv!>3G_)7$Co^j7Ul9-_P?0c-S0C#>FhkyT741Vzenm0cNgue9kK;y;-c~cuT#FD#) zI=ZqvAyO7sy7L#Qq#T9QNV~BIB(!5k=|@A#7^KQE$rk7 zG9ClA^_v%?qo1i{xR{()lwuf}VWO`KX+vElIZ}+4;^)*!%%DrnY@s3vhWB?2uj#V(WbM@a^!3V`wJhNQ$9eVS{gt&R;YW3veY*Rv(fthzjhD?b-jUS5IW zQmjv`fS9mmxWIVvU<=^LdeECoDXE1)E325X_Yf!?g}H75JghB}jzoO2pk~9QvF+ko zUji~^I+8zDjIpLTo}5i%E8V9ge59{09Wm{c!L&B5&KF8&JXy!E)+hhCkdWxaCHACe zW!jw1lbC9fen!n)>uH+J9$drX_V+M6x`2rjv}6IYVO$xkT>o#P9o@&_!aF#ae+R+_ zPCSs}ghQ;g_cRkWa3o+700u$=W`m)bK_kPIT;yE%EMfzww=^Rp9}7sqXfyhIu-B;~7>XelWPKe9)^rbAWP}(LJ@FNnrqE!DZm#6wDcwnQ3-q0 zAWJPBnx7qDes-V?Eva~&`0s`D3+gqfA7H7$pyS3b4@ z`{EIZ9u|_i;2MN+aUDW70CiF`Tr?v_B^_my+$%Pe%*gd7;RyQR)OfFh6kxGaa#kW2 z3{@-B+$j=Ra-vLIIfF=;A|+DND{lsz4PpxuUYiSHQ9wm3nu#biRiIdR{-FdrF*w+n zMSB!{IwU3zXK=WuhfuW>GO0Ws~NO;(a`L;~C!% z5<``W`!YCG8R;rt8vmV!?|@y{-uUD=;?g&V2yjB!r!@>@8!U&uxEF!Ig54oV6wso4 zSRgL_my(B+e@oZnr84Uc*Hy81i=ax7kQNC?npvhLNreg4FLgA`0RRHlf9~_#g&x0~c7sasSH17z}3vo79HSBxx?u*Oz~PQJx(= zSrqURWJFB>Uy{!Y4=`+ofdwqqmOjM88?kzNKHT{g9RA%OfUmEkdHW{#-Zsd&FBJgO z9Bti4?gvp0grzc$mpTB;^bM?7Tj;NCV5YQD;t^#C#Gza6UEC?ArGz*^GVEh&IqGcv z&tA5~Ig*n@A2DjfV`r}@+NlIQ%Jx_XY$-dnrP*OY@767Q)v8NJs=%16jn8~5(fscs z4pj=XJg5js39hIj4$@9SD$xWk$cqqw1`|OK#YjQgq(txpCCH)^i;DCj?nsgHaWjjB z`XoilX9YzJGzzMIpJb>HWa$H1>Yoc8zaRlhMFFN#luCd{`4c<<06La7CscuNq)d>r z)JS*leF5i-Qie}KN`5b#4RjG=pq+4fd^F#U%opoow~<4%vhx>eUmoM$OW8bBeanmp(b=ZqW~-;>Ui{L%A$T7IP02_5g8o&zWknY^;) z-U4C!?gFgkAY%zhYEUM>lKt4U^e6f><=#h`7DPtP?@CS-&1l2aP_SWi>Xf92|)eV1BCsA}(Z4eWtnoST4zl{M_qVxxrM|0%S-vN%CoKWdRT$gY3^K0W!%x zL-3wn5W&E%W8`iH7K|(WU9{nD0#jUO$+#(oyV*#;^mOSn;VmMl^97!mR-_nKg()@4 z&+cWc2>vH+k`*O+k+Vr!(?L=jHTvdON+HZn&f|XrI3b7=GlK=+6~13d_dsHNs?G zu=o)$*aO%;0`sMHa8ImY{KN{-7|{L^nqPhZb9WnbaOmgnFK}(pm|zT7n%q9P$n80; zQ#xXjy)3w7c8F`?j@sP815%_Q4+a^KF^y-#G)(|(f`3G0%W!7FwWgU196|d9yZc$h6#s zi9ijPdUVQ?A-^$z+5}eyxk_^%A8!=ng_OjoD=8`^L=kM!jFv#@%sjmOh|` zxhwBUtQy03`-64-yPtlHzxkJ+#pMf2$rqwv+UWN)4QP27&?T|ky|f^XL81I_M5O)j z3Iut{PxkxIVE!lGvxQZ6mBbeT?0m8jk;|Zsqnu{M-t&cn#K<#WTwuotED<;u_*xsf z`9b$?ZD!;E!Kk;Lz_t_Eqa!q<5ilG9%>ZZ`kQw;GMEkvfLx-9W1H84=Q>ZGYPC=C~ z$eJ(3H04A<66G)cJM-64$yku0OD>=$11GU7pF8w9bp=U+Q2Mu5em2yeczaw|SHJhR^){UmS$aBAQ(gFMXz?ky)y#6?#0R5BcZeQcb z8XWGhf4%kOaNoN-;^Z(uvpM~e-8z| zxKeVPn;^BBK05K=@!Y4zQJO4cL&h5(N9hw2{2ZNtAWFbXj35R{_%}2vY8i24Uqt{b zoJTLMAhKMIb{5f0D$pBF!k><9o_3mG<;{NQ;^LjA{gw_rZF2Xpg2=&1d|)e%k8m>&NO zbTsTmk@=vrT45K`!we}mlT`=RPT=eWHg;Kvz>SZu<-s7ZV1kjS;UrJe44N!KiYqIp z!mj+JWwJ$-6lH0TD>fPh0OM*JZ`ehp?yrhK6=Z2pCq1B~{3boPdj0tRID9u8J{vV$ zb{I+Pj46RE#HIX4Cl)a&kCzl1UHQI5W=jHRP|1lnZEWLx06Ov_ke2DtLjf!Ozx$2- z{=o$Q*Z#(tPfVokF#f6zN zmNMf*{qL7fa#@h77o_wW5)={%7i3528sRLZh(@;}e&g?=RD(m*w9}hT2je*Tw-}bd zaNz{Fct4jQRSHrhVn7^+#0FN6mvpSe60j4rdoAc_3^N)5gCTg(Ld*c<8jx|G^+Fuj zYn&X-J;cPt`IHWDMpHWgCq#r#Z;#esNz<7IilfPE$ugI#_q;UU=6qg4n*Lkvo1U7RreKa!fB?t zCVuW^8(K1hcR8Kt!@NsKas#lq$FF*Jx0Xyp9k zC^B7w+(=B`6-7y#I4}G1;9@v;E`u!2N%7fGd|qHI%OEU=_45i=?JvRZFg0K@sABs~ zc%y75n((TvHE-*C;{So=@0H2htx-uY`DC~LSdY>tl;2)5^cf$g(Dgpnqss|G2$3lHMF%O@eQ z*YNqK1yfif2_)VR&2Vgpq%KEjG_f+z4a^n=v?POF1-y`Y43TGfr^cL!+8@a2B6NB? zy?yO(L0U9ufYv_D(?9~u-4u)$gIW9+WJ;m1eD7W(>|XPpFH7&Au$G#(Sq%}|?#v?G z*(FT)SKYSi@vxAgoq^|}Iw9rXsi1eH|2B>7?L`FLa65*OJp94ObEjCCo8dw9PV z_CN}`*kN~I@`*^+IxrC|N3&cnMYny_0SI>D(2fI$WrGJ! z00*1`S)iC3K%b|QQ~-Mh-W`dT8MW|0eqf6@M+tmk6XqXM>%OafL#SXXiC#aenIanL zQswjJ@%8v#om!(@@@?^~770asc)u?C&-nS0SwJpGri36an6F1L#UUihMTU#ZtQQTu zB#=w9o2a;U{N0S(^j&}fLkAeyTUd1O2LGL~53#N=<}FNkwd6>f>*~m9<*SrH7^j%K z5qOE-LCS+jk0}DMvFsO0DYLMb&cZ%>@zG>O z0t~mjpNo7EZBImjFIR!t+k)9U!07&`0ALgdBMT$6&tF3O(iLFR!hEt0^Wj~XyPGJ| zl7E|^OJlghKB&z?{YFJjcn-PPBo>w?Ri{x>1ab+yXf}*X8|X-6_B%*tTSz;}d*Wc^ zNycPZQY}UDC_u@$NNS(3poWeQ#m&Ds&wO!lPHCb9-7P!l+SE-pxf3_#W; zV@(nVu>?!((~X!sP-Xp?av~rb3M6uV(x$Lsg}={IkUNpf9eokl@c~>r2G7g_!x^x% za7_bt76`sCBHHLOo9zmG4l8k&eQ+YLms7^eBZDoeBM(#sw`9X(1;}VAm=sKy43_8T zMDQdS>IOjDDLD~Rta%xY>%m2vjuV+Ot|K{eieaM}F%ERF9QUwnE>USuESQKJE*0>}#A3n~Aae2!6oHnr!AbBuNp zqva)o0tzUI%o7Op%9K(RGw1auF0&NblGX$G;s7xo_%#xkZs9Y;=g0R>icN(oJxM1r zW$;C<5fmp!R~omcDC@8Wri3C1Kntg4h6D>L2`0bfvZP2j0xk;BvQmI9i4AC#WXlHW zlmcIz%b=3P&yD_+MFL@hAr9#&>@-)fGWj)z?k>nqvMH`+wum<2Ee&@i05aNe7X_nC zN(K#}BtMFQ1eL_4-m|fUzxW>T^9zF8^Cf%5i4DfI8E|P`o92KFzLXK-aes11cQBs4 z4<^R$;%h0MnZPi{fDogb87xYw6J>`?LB1`iX&@4TQ&Ef?%0>i^*>6^{_{o7p()BVV^n&duzAU?oJw=4>D$%D4?Sj!C=EnYH!H*;n^0}KVpB@N092HBt%I~jkcq&?H_05pmkhj6 zV!v?b%hNR4eR!^7-8cD{m53=a70qhSKo0{F#bK<=DZaVE&dtgTkn` zk8z@XR-z$sigIS<{I5-NBVbei9aE)5F%~?%o?^P_&({ChAMB69ea4m*>OoZZ#ex~4 z0I$Du58Jy(_?=fSVs^GE%tSKKNQogs$1qwtuXB8kw0fRY0F3&XvcF55EJdg&AOUq9 z#3I54kT6Q)oM*MfRHT%A2W&Z}0%@SUkd9UWx=u!kQNJZi#T9EoAvIFoEt&z-N%>JAeRKUC@Xk8K zwt%ycqk{mBhcPu60s@S$yoh$`Oh+~m3@4H|YB``}+Cw#|o)&jUg z--O{KEXW5~w7*H|4uw&!E7>n`{AVNGEImp_yvV6xqU1&$Bi%5#T*br!a)7}%ZUXZw zz}u^m(~O)p(zURzEsS=Z^Pr3$*Dj4WX6>UQ5Mu9t;sC$|$t{8>3k4!61-Xz5;R+c* zNlm`aURG49WWMeQnXQsoD5Rb!rIcARZACSX`ksq|K~ub$(}nKzc6vL#ecF8<1A}eg z%rAg@-v`_v%X_}4AQQE~WC_?@B5W9dC;mMT*9CL805b+=wmdlV&|WZMkL%W!aQL@> z0KT<>;g8+{9UcN?K6}u`1Wyo7#Y_(i11I=k(gVDt;!^4RgMXdCcXnI>v?!xPRtXKx z(?M%fLETYxsq?Cf1P5syoQ(52R(Xg>--oC-5_NGN0Gm$A4oOv<(^NJ`X24{SC7o~1 zMLq|XOlG{W+U%;=Abnf~ylBdIED9I^xB^&m5>dzdh4X(volvBWbM+>?A81LSlA@}| zB#au|JKnc>I^Yq(mM8;Y2O#6#-YigB5Yz4qF&G_zcv6_; zCOMP10))?opo$rTzPRZCxY!AXzxgR}xCdujxOU>x^jxc00GZL!Y~Kejte`#jB-(SA z%b7$)#YdC((j1(W)Q$=^O9W(ua;!8lL#$8386VBSwGFs&7>dvpoiGIIfG%XPJ6Uf}~(ScY3hWo(9e1XQ^Hi+F8q*0#sLQ~JH`iiy(lcO#^=c}jH}Dp^X= zVe63q>B5n+hARUnec%k0Oc$;|3+nkjKE5!n<Z~Bt#FBsB{9HD7{uc zKA_rfltIe+(j!*a2&j-B#V1DDQG_g9kO8?stERw$an7M>N{<)s|3aW(!W)?}PC~Ra z1!j!%g$G&Bu(2*ADv|Rt4l8ih!XE6ywH9XNz#+<%nt&d$fY|u+VSw!T#Z!ToV^996 z)TsZoI4B?kMWKse7#Z0sQF50hJ*ehfr({XlccsI2L1n5do(;g1O;c-M7k!_rK$kA~ zl3$y5H!yhj&*8>LUi#Ti;3gCQbC82-$qohP9}f1w<0H7GGd?PoxSZD!%~zF-E&&cf zI)uO+jB*HOf7ufI>y9Y^rUqNLSKzE?4w}IPra4GbhJv{>4R}%hHRaz*>2B}_?HY25 zz*_48mtdspB1 zQnC_BBVy8-JCoN9^)M?5%DW||_aR6y1DhrM8>O|$pC_&lu}&88=BupaS=L`Owsiq) zK|Yr@o9k-OMH~tf>VnNvqb?EXA|)?o!XBN$M}xnKi--RljqH{&(&0bJkxHc`8Y=zB zx(w>2M5GM9Bo?ric@^fb^+HTo-XmOgz|DDo&Dg$0Q2~#n_al z)w;bWq5egx`(h++4SbZFbY-sV1YoMXUL@)7os^HISa2#0y7VMHh)jEr-49bF51-JF zr0`rpW`LjuV5rY*7TGI6AE#oDka{j^@Fo2{0w$%zNN-|lz=c^eWjM%&awIe~P}4as zb>3f}q^Lfhz2j}#kfSLZs(PsQ#XajZq9Ufcij3|9Vo(DwkG?TWMPC9R<8g}smge+P3R<#2~zlhK! zB$Bj|mO#ypo8M$e9T+h(K7{ogeDAY?;NsG#(D?BFQWmz9*Pv#qo!n{aYYw)E0z_Oc z>>^_Ys_Pz^Dy7sY7m9_iOYwVUqzh6-8!3hf;c#~VGZYL)Sy}*ZYiZxC&^C#?WNK-+$Tl6bY{EgC~23OEzXq;6_m+Ky^N8tk67Iy{PCNFdvm~>Yry)* zvu?r22E9Q}8yRIH4x%c8$R>*kL7rLZfzI5Whb;vF4%q!*uVJM&od(4oIGytP1xr!3nr5$5hj_WuwZyt z5QZ!;StQ*1oxpZ+f|cI@3)e&4aFUN|U6LIQe)b-kcRm5AdAy*D@$D$oO@vQ3>G#A& z$2wBE>PFMdlHH;@q+FW{`k%R=;)eTK%Zcu*$|l^!`s zE>!rmDD&bf;fE>j8oBUmDScZ?R!Ig}5|G1{uM0}=6=qhO66&y4l8+0@V{s9WN}cy# zn&(z=;kS`Svk@8(Nts& zzDNR40@6T{eo!0i39?!}@I>R>W^^Qv|H<#1pZX8#z(tpe}(ZF0oa7@F$50_lKkr zN3hoVjc@e8phvK|U`rVbEM3#w8bqlggb@lxr=^@pf>I^~i4!&FBX!NGCAbMCy_}Xi zXj9w_K8Q*$ia?7^fKg(_*cLJwdzMRkz{Muh-269j;W}gXAdII^1g47zX%4m)u)npSOxC54Fy8-U6-#Sd7>tezASHrO zMFXKqMk#z-^nE}lttm1=nwdSEfA#=(-n#%hp=_cn$V`m@gv8k6{2iz@#`q16V}bG9 zk05n&poTrGjtC~qIT8}o!~u?z(1qKR(6P#{(WTq0=Y0W8tJIe`HaO^nm{ zb|~d}Y9$niisRNM_kodP2zz`EGqeVl0~oiJffO5~q;0;>mC@0q32&4lS#|xY>rX|q zXSkizT1G{u)>DgsbK8WqS%XPqu-k;|hK>J>k|m0n@r5c)Q%R(Wy@@VyF#6}hQ^|)0 zaN6VKb(eY=#3+DO4c8t8V`}FzpZ*2>6eI4e5yD;}Q^EH3$K2^|u<4MTM{KG{? z9|OFw16JPz20MbS7w9wUUkwg?q&`X$IxZ&Y;(0x7_U3hJ~R0}>XU zv{V$Lll(+ffh?dxUZd%P@9et z5JCrhLXlq70Y;{RFH@0=?&EqSMnz|;4@BvuBvY>e@-(m|-k1ole&*HGFTs(4k(Yy%E#vA9=e5FEP@zz}>{I5|S9vF4dCDRBlI z?jt}9d^s8X87TWS2!bgkd>ph$j#VX)_u4qz2RR4GtoM2t41N9GL|vu{-T|I1K+4Yn z9ngx7r+IwcfEP(Vnib%p*ael@ZBgJtfiHdc)z7V%i0NlnCedXn0F*#$zmveWjCL}_ z?BYbpM$uug_`=jG5T*;tBxZ=SIq}F^|6kh%ZIS4v4@moyE~N z{{UhJfNeYT8UlDiNv0_Yn3l@e+(iaLU{37ZS;EoYY?4ChIbQ=io44mNx5SuT-tA3d zLJzwo{f($J6jrH5WupTs?a1NmlecjHlT{q-jPh#=DuBQh(j$bl7Up1dZ^CD{8T6pw zy%A%0BU{Q&TsDVS2Dk0R`TtshYXkFT;sVeU3VNpCt>R!B1{;EDN@hXw!U{hZrnwXV z>A!Y_fvq=nW%emo99TC|Zk7O-@V-kHktBoN$SM+*Y~)!zu85P4 z=DLuou@nDO2KPiEDJn#8-!tFDga$Y(Kk?v*E!kqR11sTLNd{pFe2Mg%Y{Hv>KY_o- zwD(=;qvr+SblzWG0PR$$|KPDOe zb1>HROqk4uVKOk>1VF}vFsAssPdVSmDc5MWns@PL(VNEbI;Bm_i&8n<9pq|pN@^s@cR+iGfSBK;91DR ztOr*#yF@jb9(b!CV+`z5Yp_?(CotT6av!{V0KT;e-r7T*RO9AGa4T~sd%cJGxa?UV zgB`)fD?mH@c#@4o2*cq7FFpSW&aUplTCNl>)cc&3rG2a{?Wg-L(>h*$;o}5qTk9#((rJ@ZBxU{Oeyo zmU^NwDscxDb^lnVfgHzi(Sx(J1uGdQ`B{0xuKicM=R{6)kpf`Ro&f?W7%d5)0cBmg z_KJ~mBU(_mAN(b~P>3l&Tc<{oeYWyEs!>Asezjg)%+N+<)rMEN8JS7yuE|g3ZA{X+MmKi zrRR{Z8x+$88kot^>7+WqP8+|de;kJhW{+Rfa^q7TxMsTn(Owg@h%(K z7LuU|x=Bm}%0PF{#lbDC;@~@f6~kZt8=xHr!}Cxiu>lzamH{LnfMkqkw=ADSd*K|TeTbAMK6eFD=sIC;Ym|NL_vkv=PBh@PEu6wap;^z+!)JotCC$+4gHxqI@hyLMORU0;mAn2C%7hNn&IJ;1U@{9h2QCtroRD=w=Pu zB(Y+qz|`?fMmS&}XE5YvuwdWH%#?Nxm@L8B78u-ACbl-qi=qci7-v!dF%o>AtOuq- zx+94;I+lWYm`$bqc@KHpFcZP04Z_78;KNnM2dj*oq4VcbvAA;TPu0a#;75`gDF7wj zXOt8vGGRD?KZKGU!vQ2Q;XRx1yI;LHgDLU5kH8G5WT_OMER>EBkDne{GhMh)T2t37Uh7i(}?1~R5M>hxzxu^B}w&n$#SC<^G8K7keM#Zm^1I~ zdp;jcVZ8Jd`xWa2wZx~2RnGDqbb*)Seg?Y6xtIoil%6gfutgOZI)x}PW2gpg91 zqpORt)E9@{1zG3>gN}}&!cY(BPyi@B%o?K44s40Hr=MIs(c@~?OFtbi121XJ7UM8X z=0*BXh&NT|L}DsO*zCpbJV%zA-6|CPuv$kD%jGNO{j5&`Q3(l{vq z6iC-Jx0WF3^rOhw$Z19{?;k|4eRlz)#XU4LV+9_$o+#xEw2+ElP5(LvA%p#I{bg^i ze)Bz;_kIPK20R#ghD$6mLs59}((hq%=3=P)+hS5l*M0PFp^%yqVxwII#l?gIH2Q)F z#s>pzTwhC{x1MhjIG|Y{Ot8BK&JHm%x0@CuSEV#{*e-5LytJA$+>}l$0E`xPFk0Nj z;qC~x-#H%)ft?2*xMCqjfCApD1r)&w%4WKXJ(~=23#mw+!y*GE2DBvrA^;b5;?Pcl znW`a}#(P$g@eGlI7hMDCDF!;ri6oHnn6qa~npcDWkp9fRw)XGe#Ns&2r!L5uQfiSa zin%Rb~{!h69U* zIj~_O;DW$&tHUGSb>a&S>mS(xf2)Xt=j($4dl!M#;-mP7z0dN@b&=)KYt%)eKRFN zp57jCP6-%)`zqX1YySI5X5n}|5}rrvn1%f@c?naTQ0-^yb}I~+L*R)Y3U;mn+s}kL zNFL?X5{82oFFk)9#>l4vT^@Y8{IQ$H;kl=8ygws#7^jE>s56bApS<8t~d9D&6o@Gp zDwXLjQ@=4>A!jO&rQ=a+wu~Md)J0N?$W;w!&@`~+5qw?xq)8pmmL7m?S|U;Xx$2vB zg4f=;@8j|lix|x`yagNuN3aHYlM#m)@eGN7v87RqM2x^eUN#)t%aHXnfrgl76#hOre+}ccr&J=6?W7~c1SCM?8=#GBGvMkvuyADX!>bH|!@}$;tZgxA zkKn|@ItLM(0GBU>MUBOqdA97&bw2M2R_*BuvVb zS0_Sxu*4v`0#jtjXbDq%KWva)ptBqawN#r=i{~#@ArHai8&9JB#uY#IV_orC6!8*{ zO9Zz(hoe9GrZC$Z!Gu%HV)RFOLskm>nMLQ;Ev7HPPJ5vESONQI^po-g@l#R$l?qS~ZW z_G;;inO4UmA#dWTH>gqKM94q)e86621yw*y1+HWuf(m0i;^|Bhzrd>qX;#b>u30L5 zvC@6uPYuqXVB~1P2!KzP05BSw4%kvB1gVzR%*Xk-S7Bc~1#qYA7H2sWtBOE^zk*91FNbNPD+=V3;LJ%TRyUlQ z+y3*NGF*x&)&-eEAq^6BpG%;LD1Zh~@&?J?SgvEZJB8U2y<^bBr~$H^DLyw1#r*ig zof(V|3}%=1z-Cf(w!2IZKa`^3YAUw$Ylu@a3RfBdi*)^CLTBF3Yat$*P4)_d1INND z7M&bAJ+2CzeSM7 z6%k-%qa@A!ESO#1#_ZBIhzWa}^Vqtzg7N+UY`9~LUr0|wqK@{1slmNelm}471qm$& z#s-s5KJx4o5wMo*aFL*wUfzX6C6 zSz>RZ>|>S?7$tsv@svwRfDed5a#jl`Ev&O}u0`uwZ*m>Jal;1e8Z<_L0K8b&29U+V z3&LD!ye;CBsRS^lWUO#tycjY`dSn6vCb3<@zfiKK+KhiKH${Lk zIQlE!gj-wok}P++V>}jo`3M;73btPKtdK9;2HQEpnbke~#lP?yy!p;0T)%k^jp>4) zB*4KXLOU-w`zyeV9}K+E#Cl`nL4)D1K7@95I1%V#SmiDrQ|IQQ@3?}nkJ;isSp-3n zBXk5|qJBK24Z%?rBVDpsQo}q^T5~s4`@u+IrW-fy)R88E0yP*^__}29y4tNC4;>^8 z2S@dHWVb*?I~N9P(lN@_vCdu(-1TT-DuI?1Pt8<;Cf(#B37`m*-(+3aL@7bb=UzI+5HGj1GMX#eq5> zyTu&+kV1So*d?$djz2Jm;+7!HVCTGMS^VQY*vVjVaN#(@Hj!5RxRwy>d*nCdiQdiL zY}dmOL;YAtHq%%8W!u zOjij=c`mOWSAaGVFl9{cEP~i!c6l4k@Thmu5jj~0rgS7J7pTGr*tzVX62^6kSyr3Y z)YaEAI1z{#-1*=<#)rdT{HunWmar;-JI=QrfV7@XVg0}22zNd_i1yV}J z4oVOrZ5*er00QHjmDbHFi71YlIDe+Ag|h*Ssac84>4X!R*yU0m zUbC!oH%ydNF0pnbKTpE-MvN#j>}MoPKE||LWWF$)46-DdPrT0qG#uqf)TG~;{C&hG zty#<&#L?2F&V5vw`mzDyF@;Y-moGZl0$}ouD`;PNvXff#x!zg__rwYg{_YQ8KE8+H z&))a3#a~C}iwGv)yoUB0mwn+lX-~)Q3Bi}qIxzS-u>P`Oyh<= zUdJe;Kmx#k9Ns=!!k_M+$5;#)0&|Q8DiSbWe&G|GJF|^ny?!nE!c;Gc@rsulo%@-9 z?Fm2>0^F6eu(!9++*(gwlP3dR3_qY$?gv=oU?t>^nW(dq02I!fTZ!pJ z8iYaAUdKH&r8wNY@yweY2W9M-7Hm@9Fh0FNR4YzYCl7_08}%{~sN+eZr8?<^-Lb$Ns<7Z%|}aQ^HZ z&Y#VoRvlek02Yrpxt|zt>HRS>F&wU4UdI3OAOAr?`92A|<+pMBlRx_aAKl!-Klq!k zV0Px=^WU|}ZYeYJ*Gfz<@+`CPo1*rYekp+kt9sYo4n~T!Ezd{+$a&_Avds6o324np&YAciIl)z177NAHha$N~h!EVSNS}sU|Jo|=%uL^b8GN~SI0p1Kejt>i|@oc0H%tUrA~*CxnCbgnX;7X{4K3=wrcQsPYX!Ll$z zi%TzknEWX0q`}_iBA5t!n{yZ+G>N4V6MB+|Nr;?w3PAR0Y7Cfgy|yu4I@(cD@-TE& z(ogh=(I(GX78Z(hL+QH}@c@rs;!mzo$%hW!2yZ)s%}Hz%Bx7k1d__^!Ay6 zEe`EVPh#@&lYwUT#iRky#KK)Vi=&l!4FBwH@cr$t7wbhF#^1gM`_h%q&!^=}4!oE{ z;Owt}yTAK*Om?R=#>Qgs&Cxpk!u%cl;rwk3*!pHn_1M3*coY94dJ|3vKiXTv|7HCJ z?79I4$Gow&H8^)>7k}~9H}L1bdIo#@Gab1RSzxjVtbYeseGM>2z_B=r6UbNGtl~qXF=6c1D>r;N3MROIvU72hArwp# zGg76469TctYw;!Pv?&29VdEpdZzX|Ulfjm_xp#2U%v6rYqqN*5$%sV#wU+lNZaD>( zir$n0(O9&Kd#+NE$_QxADxNNZBwEAiuf>&5ek2^jh>Wg5{j3lq^v?=HH? zq){$99uK4`1&t73t$Sdn=y4n7#)4-5V1m)8LDK_h{*_m+9sB(8*kWtv5GzX~3dn7WQQkKbU7J2Rkj_QLkB>>lTK)nxUw`8dS%r(vuE$2iV_U#$aZG#d90pp(qv8de%USOfJz$ zbqxT3m<0Oxu^CJco%2SViU~!ka4by7nG=Y^MA*5%jE$RTa*C2pfVm%*Hc2B&5h>7y~7dP70Y?Hqdn?=%U}FWM&qTpI1fs%J{S-Wj@c|yC#0N zWU`+kv!kaAc?lMK`DL^PVeU#(61WGoS0LqJtQt;UqU6#75%(KH`dC4Fm6$tJ03t|$ zVwU8TM)oNqIei^-6X4lW>@rIO;Jy(Gx+Ab=z)K01K; ztfHJjlnroMA1ebf8eGYMOnqMsxR}g<3BQv%rXho&FlHt}vXuOtGDvrN`vQV31WaDO zg7&2=xrrrT@Lh&;kkJrFfAlRhzx)7$w{AR=55<=kIH1$(>C*x)N5JxL1nb{<{3p^1 zVV+z3uP*)+SBATAfjr@+L<%{z5WPBo55Ko?2S46h!~c2xMeN#UD)YrT!l1GE*2^E@ z*KaEB^BDZ*22R@ZZJNgPg9j&QbkqP06g^k} zy)FmKl%o8cGB(;5iJI1$8~Oqv#h4)}JFB7ijVIMb(?O|yT_`6V#qPZRI~c5uK;?K~ ziU>HG2;TX42N%wcu(mqN#)B%=r(m9h^QJvrIt-PL1O5pNc9A7Vs1t^2aHxn<4l!oV zDJj%R*CiDhS;=3DeJui8iMoK+1A&(l4(zUnOFz)^H~|+C!TQa)Rh&<*C-~so?Ej)E>ckl(QJWOAiDyPDdVPHI!5u_j^S=kytI-K6>J$*{N~gh zDwF8ceetn}dj^O5=P($JF}JjXW;hOGg5&=~oC7h#I-8PRD5P%r1TMySe~9rR0hnNJ z`N+pTM{q$+TH3F~7eicj$3vmEeRl=B8}n6>9hgF*&EQMaB>|67V&uHpt7GxrChV=M ztpMYF12bR@X0q|A1O$r&1q&uiMqFUKyB=9m8ON)cq?}knVVwwxVV;rZQXF-a2QnKI7ArjI$67lV?z8i^*C1{G-@!g=)+vg6pv@c%9=WD;lmEjJYJRH5x zUy6($%-_Yb8RLI_=i5nk)PE`aDC^4?*YVE#BUsl(JA{C}%fQS!Fx)=D_#uLQ<^uT6 z7R>tYi3VIsFM7~znu)O}az)z;{@u?$!P@E^zV-Y$?>JwXm`dSt-<2n2B?O_HdmDG` zxl2-CS#g^ZY06WS73p#4@xLe^B&pj~Sl>wh#XU11yzev1(n|sW#C6y&0C2c7z~RmrhzOeD1oNw#Xl5oJEKGAK zhiK=>o(OA~2u6z&%q&D{4uc(KqmQ0BT?(K)11};CZoG8~?NO7{XyUm`Nj0uaXi9UA z%LeE~5JR4g8B)c(`KLb*vvU&+=JvqNA=*~b_p2Kj5mX^k@-Lt?*-idD4%)a_o1gn6 zvQVUlv?hNIxg@hHd|8nFGKd*ue8jX*G4i_wpG1@sty02W0Q|kLi+_9q72!!-KqDSfD7GLeua9Km>365!&$ZwV|G zaEwF`K%WWMrwig$Ev=S(&Lzn9Vv12p?coTPasq{7gfxZ6t?e^54;Xex*lm0~wQ~Y$ z%4A8;;^hwb541Um-h~wVSsq&>==An!7Sk5()eD&X;Q7zT9QU)pUY>aZ=JqD| z{?^w(!$ugqeGBg58OXxuGml>W$^$RAfrE3vcmu`aI0~ z&dETReovROIDPMMCVZInW-y+mWKFG(?6)dv(pk68~Pa8TWT_XH_=;`RjKIaY-lxDa}GOAves`uFY8ICFZ6H6wAPvuTj^xT2A^dZSC zjbMfvB{1nRm;$r_$*ZKhYmwv~MEY^ZH84J>JxyyJ{@qVL#L~hDzw^q)6M;F}R2Lw$ z*5cid*0H=WgKJk-QfkpODi-OwlCmjeuNE|9;Z%K+_ zlh;N99|I%Ce?FI9Rcs5i6Hs8gIPtNchy{U&|J_#rs7yV8ud%m_Q*t6mnIe-x6K%Nb zl9Wi_2j!`OD#F(FFk@6uP{&*}fj6PUkD_?3SdOkVUeyM$qU4(6g9b+j=U|M(;@Ucf zBX2hAg6pbh4h8^&IIs+yG9C3De9=yb5cqaW>%hOc^*$|9)|{sulIvLhCiEzydam(8EGxk<2#?@=oyA&AS{9PVy$O9Ip_EK5vX*wl>F6u zhzO|U_mjFLEJI0JYTBfQyr)^PLz z3u8Z|7YVU9CUzDq1`X)A+ZQZf;f0#!5v#xyXbSuh613}DFM{2pO(64o!n0Wb={QFw1;D2-20 zly!hm0C|JtIpBhl<1yZC)Hj2j=<^NLLCsTZ2q?9FT5T^EVNq-A-g@{wB za$4FD-cL)o|FK`6%)nx_xQn^vT_0f{{92-S%l_5^CWnn;;kW`k&cBDQU^~F>`a)@x z9*16Jl{jREOJq2t0y`Ahit*^>Hvo(;s$HDxIRZ44&y}?xvccR`l5b3!J;VR#`M)0Z z(leK5)@JF^r1_swikdHX2{F9kcgy(XH9ZY^Vgx#p}a~nww*4prm+cirzyUAE_`5ceTDJK5@COs_hE7Gnj@CGek>-)guLNy zPAO`F0q?vuSUzfCh_QM^Xb|O2tTsxd7*eGfFF1p!CJQ_$s+Po)5ZU4UD_4f{9NM1s~b?%Z9* z)hF*xspUf*L=JBpuHgN{B|JT|Gu6lCWcZrJpKM>kpX^@v?E@~>!alVIdt)8ule-UO zkToWBr)=2##@~-er$}wK1%`9+i^{~3GQ}ko=SA_{G4{-{ib8&qwYNV81elv`RE#r~ z_((Km6V;s~9hF-HFRBQw0G;$Xkl$GD{-8I0w=Q{6u$rj^I?@k$VJ|}mx&RB5S#Ft5 zR6iG`M2M!%t5Y3;JL~Rr;3dn2y1h)bg}?ghHT<{!_@#%s4)3n-VQc#k&t5(IsrDDvI_&O` zF*iHtHRjdD_WITV1_Sod)6$PwPKP48_a#>t(wG?)0EtqtB^f{jRpMBP-$nEgabmr_KfniqiC1%9h5#UN%kYk=(Yk`oQfWHmGN$` z|4aUReJrQ`7WT9W>`0(V?fFs^w60)6YL-Eq>-9Bk4;kabC2Zea${zfy9KIPi$x+Q z>7D;s0+T7WtGpCTDt3h~_PBUYIq}7_6&QrWoe}PSa7mrhI-0x$&`OqqQ!D_<>zVV+ zqnyqbeM)>`>zwyq^J!_EEPsj(uNElE|khVqvY z-dh0gG`oee+z7#6B>^*FJhjcZy34q^Z1DbB|5(R)@!>!_VK&LY)-zu?Fk4KL3k}G? zputnyjHL-DW)U$IuybU8rmU{Q2d(+u+-q;OzsLn;Yu$d=6lY0Dy%I zhZz6v3vibMv!(rPz?Nv_Ep*J*<&@&|889{Yw{lKN0B3-`i-0uh(wP8rw>)400P-cY z)DiZe%hJ1ojaQC|kQT!2yDL~(*~OXVJ=iH9)^dt zV}aA66~UCLte4|VU-X!uV}Y07``%?d^VAB?ti_2 z8-M4IUc?{#;3_mbrH~vEu(f-HxtRf$=0}-v^icDLJUUR3E+^%jObWO}tyTACzR3f? zsZ}d}HfM|E6)Gk+nSv1V*E>EsfYL?!i%=&KreLKwW%enhL9TvI;Ys28K$z)2WX zzoZ#0s?cNRQX)~@m(OGLu5mgwD}i19`*6{@Ib4+-=6^5$k+g2HQ1ZTD_Tw!^B}c$Y zIIq!N&m7JE%-~6iSyt;Hg|X+)Q)FYs6h{~QJCyg8iUAkoaZQwyx-=Ljfu*Iv$T+?- z3o3&!K#Ya778DYh zI7^x0hD;QoLX^|Zk_nO8$dQ&8g&>G1Y17Q+0(=3`URzTbu)wV@z+PK>d|ms2@$`78 ziPcppXOM?~J=X&cIe|O72zPcddAlL7VCZ0i=G|MM@dW0R`z5Qj-td0vb<%G*CNDjS z_JxbUFtB(YC$mNJeszBha06iP5@6>%i%qz{_r*uR!Y6{!9bmZYdrqgfPldRkdG{vl zg=M%4tDjALwD|97^I2f;$zV2H70sJ3dfa@lD_DKq0~lYn?^cWlj}FfY4leWqFGPaF zqal9%##MaxTkm0U{t(vn11|#-{HxtdIFtteleJ&Rw#>tQyJYcicQ4{US$`1^;*1ap zc6MfQG#+-+i#{FNMh_Di&E1bUMMfk&ej6HTDGgDh(VFsONupIz&&eBQ(tSmhj?gqd zx-xD~3eON7hpSRAP6%;7WI+kk3M87AVXO>msV60<222W|rT0s$r9WLymKt%-6bcAsRtE7kMt_pHdNV{3CCTiZvt^1>26xW0)i7ndat-!*EO(kK2+-roK^E4RK+kmz^LaW!%wS|Z+tOad%o1i#uT}cjx&y|#SGLq=sHgW zF#7cq@KXrM^kWrsQTu5)73u4|=SX_rE*j02AWs4&5WxYb7zI-JZvdW^AR=JLa10n7 zF|64gtQZ(6i6+Zo66jQUj74vnXngD#U{dkVO5W#-NXfDXlq?jcay2R9qKnAiP}G93 zb9Wi*H_oc>Fnim?v7)_$th2@5fe5hGTpK|sZ+{czQ!$cQecvt^=%SRH6%7!|pngta z@`k?A3x$(^NhrP~$f<%P#CynCa9{?x#L9A=Brb=pH%n*LBkCkLRyIP#W2bKFl`*d^ ze1ih-BADqKLtrc5hSRv^qj?PZJluTAY-w!^=PaC9Sl7adA72UB)9*`=7${rDV0WPb z5%9^9!OQpOaCw_BH`bp)3Q&WP&2yqTGisJg{2S~0lnHMDGZ=(3M;z|s4$x9QmqCV8 z@|eWeRR6-SGUJ;8 z?Aj7!G(h`}E0D!mU}6*_?Bmssyz~S2T%{7r= z(i;5vYfs}_-}n$qiw9F#EJJem(f%6#2Os?b{(EQM!e3mt4UywHD}H)(7(2%Q>E0{& zliiD$<@Q*niPnC^^&}NP#WuMhK>edpbGwzus!w;Ciu~xe}dor)+H=1JQ_GNX)V?_ z4{&dNA7{_ZVRdPQcRpN)VZyUl&w`oo_6PTIZ(|>?Jhz6~(IELP9E~krf9Eb{1`U>% zX21+I%vf5O!N4%?Z|>vX`aTZFEiRp3#P!=dSYDjLGgnsOMDXT&_prS?#w*XC!_M9j ze)#iGaP9I6UVQc(Hg?9ib8in@`4O&NS;fxIK7Re?hd4U4C&o78#-E`Qlo0$6M5gaI zPiorp6-_X5O14w5S|od=)KZ9IZgf%^?$#!}Jzg%Z^oN;d!kZ0#yRp<-j^b*Mm%{fY zkCP0JXf{GQXGFG6Do|aPQAIC~#PCr?tUf2C<|XYF0`Y~qPvG(3fd`}rjs$F~_n5lc zvEV|A0gfp?3ukw+d|{)KC3s*pMqkIz$Ob4GlH}PaOvSp9&2v$7cN9m&7lEMwBxQn{ zyZEe%?`~XpC&9{PHjGW@G&4__y=gZaO3~NZqA5qbh^xW694nrIIOU0=KA%57A<9}9 z)=79>Z?w#gV0{R^|GvU8Tzs5W-gK^fkErB!>4c^=QAwu~n+KWM)Bv#l`_~f7G` z@na$Ujky6Bc;lSGduJI>>>K>fEzJ~BiFE~_$KfGdc)S!~3FS!XJ`-Nl@}z0Tye2bf zB*>0pqEcd}uufSj?~5Rde;@w25`h{I zkIW4G@3S+QeE%7L4owEJuzv*JIh@YgW`?ZHc_vTvii;QAm1a_bD$u4df z7yxlTd&HL^3yhb6-7CP-`v4vnE8^=mw8EM-{Ij=l^w+Wg#Vf_`snKw|Yn7`PKJq8v(^qbAi7YWlWRG0;A+u*e~uHxkvKgOAr-KmTh1Ho7r z|A%`oL4 z02k*NZ@hH{_tzKu0hdsUnj_EVd8qN#@QJ^`hAT6#1Q%5D1ezjOC?bF%rJN|KJR&#Ggwm<8R$|V(`H`*J`V(6`qT~&@P4Uh z!bhtE>9{x0d8qCqRQhgudJS?4V$wJm_}&-X8wb|Kc@_Cl-I>uRM>JpIgKJ z!34j4`wqVM%0(>95An0tZsJ?dpU1&bi(kBP3*Ua}3B2^oIgBS3KYQ&4UU=pljA85_ zOz_tG_wmga&SPm|2KP7i0T9Nm#r0d;SeP5)&3EtNrRUaQt;1_?-@zZg`ZRv^)@|Il zyMxP5Ea8>s&tq?YjNiO}57#cQ;_BsPJb7^$?|!rn=Ya3MauGjy?K&>4E#lG>%WzKc zv)69oiE|71!MD%ir?1_>g|$Vz_whQOyts_3msjwUUtPy@*Un;Y)ZoV5T|7;|&dxsU z#Nt?2t7)jI@58Hn5UYh{~e4_IT;W*B1A=Y=B$bmjD;2cxy$H;Vs zuNj*`V7eq(6jctkNJW)4J&iS5GXMqy2j@J15;MJ=keApHfsHABU6>N1k~o`*rWsyD zNw4x+$SO520uGvyNeXOXX59VYJodNdigmQ#9V(~IXwTKiKFNm2oF0>nShoV}+0Rn;zUN9s8SVC%409l;mbw{x;^VpO^TIWH|ynpejYNg4(2YwhZ zE_hjaW)Mq|7{t#CD3uH41g4O}6wi~Z7&27!CbF46YQG@KjSNBX^+^%p;sF>q54HrE zk+l=gR3e0EWaGy=1LQNMeTrN-#)N?zOTfKl#?@_uC%1rwN%lCY!543=o1>z2ymSIv zD6?OPH3P<|`!w5y3$K)9%!^8@#HJ^WIa!upq}FgIOl1bB1Zu^7C5w2Ig6oXM9w7zQrMha#h8 z_5`N6L;`}~jkho3-u)#Qkx5K;aP z#S+k9O*EM!9JMVtNDqo)osN+KQP-d4*qLw2#GGIgDRUe|Y0I@oKzvM+pKHM7I2KHS zdTTEds5nO{{ZyuSjr2){9#lsb-%DlAsLuhk{0abEPHRYDL)wrbQR+nm+dC5ofaS$u zueq=`G<`6OB#$wYGRLR@gOaxzq4s~t(l#nQU+TDN(hM5Ko|z^$(m$8x!H>s~btahH z9*$d#h9(t;XO`zMJ2Sv|Y;iPh@&5HqEG^F9#b?gqH#@-4F!m-EvoizV!42K|H{ZR7Pi}2tI5f$t!8*@$noJxvw-4~qsKJvL zmT_ifE}e(*xW#D3zxUBhgQKGs3$sHk%=%b~C(bS4$G^Ca*-?X6o<9%QTHIgXhIKA8 z6i&3Sk^J?a-X3aCTC*F(m23p`7=WTM&sBhPWy%W#c~0%^q8KF!D5<4IDGdo7c7&_q zr3;V-rKCulj+1ufTwTnsl4Pnb73!`4n?xC!cK(g1jFtigd7XHhlw^faBoqaviFC}> zDx+7*J}h? zcHHc%ZsV0^4uMI{)8Yk>_Q zE*Ry8_sbEuVDubEj48JJs}Xx_hr_Qgw&HOWZW`|qs0?M-Ik zaAHA5JFEPCzC`<7X@I4V0Jgx^^Eg&&)LMf-{mF}X?wK37_T*hy`{2ofvxf%^9_=Dy zcKGmgkRZ{~G%KI06Y&`M>DRtMY#-ykGiRFXi_^ zg&`n`M`+XcR=vl*P5eoiFAut{EYIQ}{fFP}->`^aes+kbF0SD9ckY0h@XGV&0RZb; z2iV;oV{v|%KKJ6n5KD_Q_*Xyr02j_K;Oy!wj43z6I$1%RFh^kP-o`!#jltU4IShx4 z!=o{N{nj14^xPWOH}~=9zrKmf7nU$TH^86%{1z^rU&M>gp2MI0;yRoaTzX;=FI+o| zt)0W-nmst2VA5LLS>MO%@>yKGa0WZO2bfISj%-9y6l+=R)8h_k_!@yO9q$wUJFDw(*fh?nnCl8?PLa(jxkj7lcB=$! zPJ5C?CmIh+Vy#434V_?Njq)B7!4IA38#^z7i4x5>Ie<0XFgQ@*9XX#2=p>~2F<_8l zv?qr{Y~ET`G3+Y!j)0}}TNun9DN}ptNU^ksizIK5(%Z!ae-$qc^51o=XRY<0hdDC~ zB{WT3*o`t(2~epX=EUyEroz$SR0_#g8GVi-nJQ0h(IdvEEI9#){QxLI*S^}v#(TR6 z5ghyPH2Dd|Bqa53^zam*7w8dNrCtSpn{MnmN{}pqV}^XuriW?a8JZs_VN96-tXS)P zUAU0~;K}|tnIXdleoQfgi6P`*$b|1&JQG9&hMFLC$qgh@`EnW5YkUNAh+<|oArv5w zn2*f+}0hL!m)l>DejEmF*y&ly;d0HO#32Nyi6gRGa) z9IjEfliv#FZz%vmfZ031;J_b?tpaJkjP<(pMz|X<0tXi<`GtL{Zp<)m-+;Nj@$~~- zbkY0z$FLWcAxrZoO5r;3-Yb~Q&fOMlJ|7HqkHZQmUvFR9{U!kmANzW8>&4?gZ_`-3 z_rXPca^oysc=iU?&h8{n!N+>72Bpm5c!0Owy@ZX8#bk=7@t@_Smj)A>Uwwq; z-X`QBt|!{s+U;ybJDXFHU?S z1x``nrRVQb8bwNe4XEGI1HkkGJ-tS+J)SpdGmIQ-NTq3E)cHqm9o8m`q#`Y2Dg||) zOUiFRQ^WQ9NSoavzB)wshI9ndo-xV@IO@!u)257-wQrT!L{p4@_3u=f3-`Up8t5QE z8O~ARebY&bsy49o`_@Gq9s3^pe*bg;%%?A|AHa+XRjMwoye9+&HkTxShZI3S0>D8X^@VyO~zw@>tH82VmBuyMK2Ie>;;ir%;$MqsyVoO-Ij79oe&h$WE7)8&EZk@;aM*f z(swe$fI|#18+{*TZJ_~XU8CNo%NlF(2fn-@c=}E;rt{eDoqXt*t~Tnj0eJGY%o4F0dxqSB9g~c zhsjjLe3z_6R-Pq5JXhtg_K7{gK(-#cE~jRt=wQW4V%E|v&dEN-ec3<7C_k0NE|I+M z)y%Eh*QI8_hynu(f1;i_o77q*h^bVH{iD|WxC3!LomzcPIk2YOXcK$$Z(wWom$1<^ zx5q%&{~qRMxCHLG7?2$HAj~;_nb`yYrtv@{n-J05_`jJ3OJjo80k zGYLp(WFJH9De#3$kfz6Qw>Hqt;7YX~1i(ehg0wNO_JOHWlZXw-l-@BEq)F+0YEVZV zhYAUksk~>@anyZ1pbPz_|L}kFSlSQM8W}>s!Fg{0>xRJY6#|U+D)}@;p=Q3214efQ zqYZ!m=pN7<;0w)=p#ZGxUIw|6!5pQ96<&j_?E zFYe)`7e2wH@eV_($e)Bz9Drdk^#7QjjQb1E#L z0hmnlWd%C)0xb%3=&&9LT`;DOl7<3{in^Zak6A=v7vKx^9OnVxOS$>%zOQM(OXqy2 zq=0_VB_FmQWa?f+$9;y!55m-}n!D?J_)q>HKg0I!5&q%d`xah#{yf@fGzT??(FY>N z^bJWr=VTxRvqZ_s7zyNb%IH)QFcK30g{|Lqk)$?`Zob3Ruz=fyils=x}GTEC}Tn@+~L8NR?to??8KpM zbEIyRO|qdBgBvA0Q3|VBj8p+_L@4ISxEAQot>2e(+8s5{<0wEDEt82wzAoq~8tf9O zIVKpXhGIH0JSZ?)oD=BhV`Yh|vjo>N+LmzlgD21)nF44jJy$dnq*Ngl@y?uqqKM1r zq^Tl(DzKn5dny{q#_z@_LS>WU0$^d93c9fV-h#v^Cl>Yl%Cr-g=a?Qpq7L{}&GGem z;g|WUQNs0Jp^{})60I1q9n-MZ&;ASS&wLQ(?cm#zOmv+x)AeABi*tQq`R0p=1Ir^a zXZ(L2e2L5#!x?aiUN8g9;^N&u1W#rG5F89FjnZc{)WTpK084+JFUdz(Zr`Zpc@O&Z z8Sa*TFw@hFKoo!!uA-|=`5dkcc`4sVwUKXN%G9r`!5CDaPCQ2EzG{{FgTMC>pi8*E z4$pdKM%434<2&zm=>H!7)u7046HpNLuW1ei3!eZp_kh7(D0)8UWtm!^KD6~BVKT4m z0zQu=-vA3A3Rd2P2Ynt9aA{uu1jE-qgy7UG$e&mXdu0vd?>&>_!atMO=>aXjqEb9^ z-t>9nrRnCn(*T&Ju~<8|g(ucFv9h!mn*7rz0%pIau5T`2GHG!0_A0h_=Fqn0SP7Ay zfA~mn=GS;QIS~LEHW>W;Jq+Hujz@`*qwSqNDfaUs)4>eSC0z3r}5K z#M+s;%qmfg5)HVNg`#?_)1Ztfj{r#oA&Wim{kFt_m2f<9KW4m{iwE0%V+I(8aj`!sKf& zUSqNAocH?mj7Ffr40tdAnE_xz z=aISCL>Dw};L8iTe9FcDdl7UgfD;`P-33`n=|(9pO6e$SPL1r7&hsRLFezFZ<#D5Q zvwkgW9bD^+*!Z6fzuQTO^)-ZMXwVFNQI?XS6*yiS>81!}1$gJ-LLHM-kl0J%Pw)mp`+JT5YQG8pJG(?xp~sTI2Pi=i?dDtV+RP=+W0R0U8I0lk7DRwi?` zV~chyFar+nU3$!`qYTa!`U(xYB-Wxzw@Pa{Wgvy91gGlXnIkBX$CaNB3A+ogV`K4$ z9iSyfNBd}RNvUy>+niNVs&OIFcPRW9*cwbm$&S1XY1BS}`TdtL+I^;AEorqCDVCBS zr+K`ZhR`&?vV4dI`49u_6&@+I;VuI31FrmFsu*hOWxFU7UapLJb)2;^35>~)H@$$1 z2Y6U{&Y0}=65oe05jE{=+R)Sg`~O%Tr2zUe$#aE0u+i)SbGHPe`^d4azl|a_6vs!a zz{WQS?cC=t`w#}q0dVdY;sL2gIS0(3``eiL;ai}?@u^9k1}7PqeD@i&&zyg3k>OwH zTa+^b%6#lG-yG1+0r!3fa5MDK5;bVy-b)B%D}ZyNh+qCSv7g94d#LB%F2ZP@!1P<02sFpJG)~n%ndObnV>_@)D|Yfcw+I> z*KcEQe~iEM{VSNC9c0<$R2Iy1@P(*mz;w?s67wa)CmmMHG|5p7K0N?@i4o5K{J(x5 z|NdWk7SCNfo5pC(j(O<%UezXm^h(;aWG^$bGT@T0A;m_B*JB^!OI#0d8PaE51~olM zlEE44a!1rlK{BW!;!?35nJxJ_J~cykuS*tkn^06sKnfO3Wv=U# z1j^bBwAj}FZrcdDATeFoPysqjJB5@CE6X{BxGY|Qu6GBZ3SyuDZA$h*cfOGxNr*0< zQ5DM(pmEkgEOIPxV7}!0JR{7t8K4x!bTK9}TYSOY#GeB@h}jpl#DEzH)~?+GHHN4WK#9k9ioTK|7aOK08n4?luWv8(^|R(~W{ZhtJPrVC`q00&pP$T8rV2 z-iEokaSFKfo+H8dTUXJ(cm>qjujXeQG~ny^J@96a05I&zB4pUWKK%sj6U)Ht(8sht zj(uo2#Kt#({mb-N)4Vr3bf$VeHFg}8qE%28pg0`Ff-$M zkOzlHxP50Glh!5^M;F>j8FcZ#TPHA$!L!#cVqtz38{0=%J2Qt5Ke>&~ja@u_?E+?o z4XhP>^vNCExOu-a_pF%%Q=&16%Cr!aNj_OP%Ic5CLRP1$WYAmS&qaM~$@XKR25A=1IW3^OH1BjUJkJRUVCia5GEV1I>nBGO4M=bzlw$C1VRipO=7f2qFqyA4&2qm5xT+TU-aGOr(fi#7iq|V zvo=pHQ+23}C8_}Mg8k^!wJTjPzVy#34a#+qsm*+y^I$?`b~u~CaAHC;08B%W0VUuh zzNT%ZGA;G;oWk_FkXfoZF&c}9*Fg$7p~45LgkrN9I*7{iq;t8HS#G>yv#*Pf3XX=a z8f0Y`9#3fZV^>{i>p|m zQkIN3iZUJB%?ag89_A15)qYjWC8xJYk+r{|i=vV3uaG8P$ZbsDv)EyMSNH@L57sqc|i_A@aDvl zz!h=Mf6>k-3^G#)*P`^gY{GTGoMc}dSeb)%73a49DmIsX49oivcCg|SxE4K;T#AA2 z$EhRO5`hZlmSZD?e(=dz^5DZ$03@cBA za4gsvJP9{g!kYbQ5z}1Aev+4qPCyDKyv9_1FfpOXvrUp&uHkIVTS$_W6sclcPBZ2$ zB~GT-==bzijWw6S4>u%?hroCl*uLhklfjOcBrSX*&_3N}9Ogd*9Gvk*-_dFSShVSO zA3*;FsJVp!o_LRm`P<%C=aE@H1kj`f?;M;CsHrEMF#N>_z`z3#uH>APs& zxd9ME$ZOPiYu{flceW5|Klc0*?6vc-*Vg=bkVhYP0C47YV02%w@e&{n{no)uF#uU_ zjyroB81DFM>7f7@_Q2)f&)!4x!EME?{}glE&d$E(s;J^GZxCi@hiDpu*WbR2^JnMr z#JPpefj+#xi9us<>4`-h#{+9!Vs8}f{P6S9(FDYV;b0JVCa@0p&3pIp%u}nlyS|5m z!wH^wY88#~J0#m$wAP|&Oz2E8+P1~P!5B@`V0LzxKFh||A>R9V1K<6|1s`1epXWF=-_aSciz2;`|De{_T&Xz zx^xD^VS}S_i%DxS92g86p9s*l7DSAu@f)GGb+~ix|F?Cgzk<-!sM4fUF- zm&_Iv-R9C1x(jYjGn4Mh@08RBrH_jSSQ6{SWyV-3HFDYfGcsO8F=L9yXW3Eokr4;L z7?{yq_H*fBxeyaXcOVt}>q{dodPKm5I){;x>2e&CWs0PzkRNF&hbR-?VIf3BAiDf8S`6!4-XA{4z$GRpvpfe@CC;+&L>0hN}+Dz;cNSD1=9w>DQ# zaoUA}Z=Gycv0p02LMa6a{v+x=q-#7#i#!-5Nq(ixroCZu1_L~^0U>sp3RX~Lw=h#; z;ly=%?WwyME$k&0sHE%Oh2$!i8zmZWi02q64BvCwOO#sWcwl=p!p5z$m>kR`Grjm( z{Q4|~pG*9E@~5&{uG0kt>h({Od?>C5Udf?Ne1k`iVa2wQ&h-JEoTSEcN0x{3`bhFk zS0^c=TCYge-=*wKvsG&Uo9qds@8gI=B+)qYp6VO~rC@Dg;4FbSO4p zIHvT(Jx5^Xh7_YwdlBc>|GM{NnmA0t_1%vBf40pGHnA=-uuQ{fhJoQSFlYvhWY&!Bc@?j0F+!#M%bt=Z@f}q>T^>?yoOlV{0Db7)0(fUuNsK zLQ*Y~UnYrF1I%6*oc;AEz+m#7r(vHy|9E6b&L^O4K2MNgKma}q0EPg^9$cBfE||UJL0EZ| z9xMTvI1GOA0h$kQKUQG8>AsTh+ugdqk9!+?xVW}}xw#<-gu|m20>UrexP`kL`?z*# z8Mp86;pOMnaDQ_j#t;_ghj{JnJ6K+v!RGc6p1QP*yX$-S_{J7~?|V;TbNdi)zIzuh zKYt##?(O2~%PTm4ZUG;BvVl)-ZG(vL%JXZud3Oh^DDc(c;egw?rj|4 z`DBY3eD@m{@Y-8%9eD=gy~<6 zNYPMK{3>-}GTojNgpP4HWjX&UnzG~L5~CN-{OkaK?~k7g#=w3fo4poAF^TdEQ0J3% zH{DVvW%R^Aclq5?v0h{fvZ8eE#bNSuYEZ_6jj^@C5L6|u92`urzdsHDU(-w9uRSX= zi%hXwoD}!hKuhk5OGkp2z!aC|3K3Arpo=S+E|Jkv|2@cuieo!hNQ$)2NMW4qy!*Im zhKX_=soXJ66VY_EhPa5TQSt@fb3Nojb{x<$z0Fn1FQ|u|qFEHsatQr41KS{77r|W9 zNle9(3U-uALJ=aEwYg{n4+7BAwz?y3eeZ=S7i0rYz+wa@lgVx^?TCdeTwu23w4-P| z4wA58S29D%5%-yxrM)~#AEeq(CKeuv*%w#}x=^--Tq#_u!T3~?v2Gad;z1MvV8CGV z#VV12MIfe>RS}g&vEI8RN>?SBAVbf|1l;{-6^rK#7SFDSxg)b4L`ja4=USRmw8=1m zB}-4h035@?GdF$CG@}_E;ruhVAngDfH_u^za|V+`i}8`g{PNI$=V44mbKxXAazGOd zZe>dQHv&PLS(?BGqQq>{=SqVa3A{^~LjZ>K+^XglQS3eMWmU6*qVaEOT&D1|=hD4a{?QVM;-HvORde40`oG~D3luW2fHmahgBOnqbMx`W4 zrz2^D+)^Iov)xT$=!@j}qKtWUl(c^C!vQXz@e&llJcqS&n-~r(E?rp1(a`|wn+v#n zaUFxk`q*^{G%0$U6)+!Cz5?tN@N zHQ+)7Scm4_Tj1S;Qzq3(&X)*=fBr7U1P{DSzQn)_Gx)|jhCh85bksiF_fG_B9fm)7 z2lDgxG5Oxpp7|o5BISvFeEi%kKj%;8f&B~K82aEmCG+fLSbc)6txyJT2HS#}t>6cB zCltkTy?m6RZy2<>hvARj0dMU-_UotVz8>NB{eApD|I0V<{`D=q`mIa&kN(ap7z_q! z^ENvg;JK@3aP{&s_6{eoPOvyXgPDQB-oXU-HxDpq44iW~I%+XDJHWSJx`6X%=W%d2 z!PO^M@Z8lin6ws0lNQ!G+`PMsk8f_{%*rg9#$ah-21^SwI2v16C%AQY2N%{B@Z8n2 z7!9{@=l(8+gC@L>73}UGVbWT#VSIdJ8#iw6U~V)h7K!s`=kcxQ&to{#;9~$6&Mn}R zn_GDA!wnb$=4Xfa@cJgsEYD%wT1;At*-?Y%pFW2duARl!&LMvB=51^Zj&SMxBKG$W zF*`ehTX%P{vN*yE*UsYl?E%)e4nPFF^4uCOUs%HXA8%kdFj!d{VPXX{LxbCQHn6d= z17kd^hMgaAPW;Bn6;YF66G{L}09rIyKqw6bi8?YBKd%t_eNZ_`>E}pM z?pCi8-;Xj3j2qhFz@);VK1u{A1P%;Vn`$jJAoVFKbHV^s5rrd(&y)8bPsyvqQ`hsy z7IkVB0Hf}UXN`^bvayPmD5}_OnDC=t+`ygtd-!Yr-qRQjo8)5z0GFOv^z1N{RCN8l zlp$KBln6yS(KL1o`qREdI!QFzx5d@IE}?LCk+G1ZLs>>tA3yz9$(R6F%2A?>&orQ> z0h6&%Zk1TTXmV@*xyxL^FC^qT%*GN*G zvUK+aWGc2PgGZv*eQmIgg3S}8pu!H(+s1pKN0_y-OEij)uSAmpHq<7rw%T8*!oj`$8 z^x9aSXn%PF|LSfof)=RTFjCZainJJ2fv=5=L8qdZ{p$;8*oC{ z-kHUlZ(qUw!3+$`X9B={85ee8-<4l}+ZU0Kh2gSufZ>nd1+VX%0xl2reHaXX{vO=B zw=sV8dC2O*my7ihnmx_yA7Sw3^`36|!vRs`9ELx68}jGxWAZ!Cz&^ExUMl`c=b|ta z2M56N`+mJzeZ%h+?ZCg)b_DD`)n%}yV-T=#-LqN921y`SkAFnNX|yf))+PpT-Uvpy z{Fz)oO}%1 zB#i+Au(NxFw?A0N%g?Xj%$fIDcji*Ox|k z=BZVjTb%;{T)(xQb{_L{1N_DBKZQ5mxr5i=NR1jrAh4jPq#jF6B!VgBYEUDbQ$6r}_uB2#6Ds{J+(c{vFPgG(D zD%MN!YVp142grk&F6aP1<>!v)gFyI`Kl>1`y?qz|(cgR-YiH-Psctytq!oPsn-{~i zBxu8cjbkIq%KADqg^Xy5^snd`R;(A%k{u{x)nuNF#ZSc{T#9J% z2OQ)v>~X2%ck=0uMJz#5NFXqX{ak1o%}}6@!~vBLR5lxx!Zeo@TcCdJx?1U3sCQ;r}krf!$cjpKU?_cB+py22B=+j{u0y%*r-_`fBJ`cQWhJ~Kn z>uX9}Z89v%;!4uFI^3B7WD&DVdmwH**HC8&X-R8s;;w;jrs>z77z}1w%q|_^V0#`! z3`bd7CXUp8!8alh!LqP}%Z&-Oc&KE%BGFI9a~Ek;ChrM|GRQ8-0M@kR!f2GA{F37N zrMw2D^)NOI05BAq!DS*~0TR))aXV#_c)(-pyN#X4((ZS#vj1IdulxvyGdKPEKyB}} z9^Y4D6j26Uj4?0_NW%eCCm49z7BRuJ4mKEI*HP!%NY{J2gtRR~iSd?8W5Un z;#>eO+#fAn04$~a2iglJ`nD9Y)Lo{EW@OgJyy!951wUM6-Px%K^~R}+5Qf7^0hnC6 zu#ScKLpVohjKgR&P6;9LW*vWqOP#+8mKP83`@j2E*i)au+wWb3vwWg>*RSGDj9~r~ zVEG+@?erq^;XCyEnEAJ_gAOOBlA=f2m@s(f0Hc5QbGW5>O#Z?PaA)Sd$?O;M{f36Y z=02K_@1l9@hH3&mp7TN0Vff>>(XQ`e@~x-*9QHW&fs{eU7%@HA16JR7nCs}%A|M7B zw;25N9WNuwG}zDXE2}+SiVj{V6laDFW=AuyP67?uPySv46T5i8(YW>ACeg#Q~;#=0HC!F#xN$~{qG-6;GAdlm}FK5Oj?J-qX`Cs2BV?D?%pBB z;}&OD7vLPQe=x?(OoKtg1=#cYJ9jWU8shxfdA#}VT`Vt+@XVDJ{PMN;aOd6@28~IZ zQ*TC>H-{W4yvp;1Rs3oGnL1uBrSFMKQ$j9W^sbHQ_>J3fkFPydibqb1b*>8L-uGH1 z6tUV&*Pb<<^rB8uQTbj9JJyOq-Hpob-?^HwVYF7sC;B$QC+!sV%8R5RF6G~)V2a=v z?-mWZIMHUgrJ=6VK#E8wCORAG#>cqi0pdEQx(I-c%RUV%ZaT9RJa>zRGiYW;;Nc9o z8D#K9nd)Ype#y%(Q;LpBE&9Acmq!3xdVvlFI_d%Q-N7WMy;LbeQl0k*C}gh|?U~{f zKvq51=0usuxX`arGeoqvOMHzue&D=0wOHj<;wsM~=^i)vd?@Bg97m}jjPndr;j5y( zGW_q#Ln|~G^y@jR(x6;vlv*<*VqqV>GjwdRjwEKTqK)JG;WF|!vM+K}vQB|2SvaMc zt1FDTOGDjKYU({hJOiW|2rj<(F-$W~GEfb`Mt>I(RGuy>*@jiZ4QFNnC2u!_?b~N@ zxH|{in)JOCk=?E~4KJ?)ol2EopEB~V()~a=wmZsoCr1|hI};r3w^%wm!f?)bFSmH! zf)RL}+e%ND?ie_krwa$AeUxlpBLq@~TpZ(G>FmA!?yJ+6M4ZgPxIvRiW-?<26 zc8H_D^bN@J+?O|IJM0t8ySFj;#RnkQK63o?BYk}jDgX(<_^8GBsLkmhDkjm({iR4v z&@|hfZ3ju3Y@22or;;X;R$ry+38pdL0J8N)zLBlNg=%+e~wHP5eb|R$q7VK z^&_LnOQe!Z^e~{Fbet-=N&zb6CYO4rWA{vy8VMAnKVhRMJ|T%j z3MNkd`X%#4%Y&$MuKa6JZ)#BLq;^;XD$U3WtgS9+c~HOV!5u9W(d7yjjYUbi=A@Gz zlcg6SH3%7KiJk*GYCXn2r-YK;#G)E_sQ{Yz_u4N;nX5XH!qY$}Em1RoiKe-x0U9qa zBIcATNxR2vQsHmBfBX!E24)Elu5Gwt~GON zFk>)Bz|35O;m89n8lZP7YA*tD2;hb|7uZUX!4k%C^qWaPhbEN+z!H{p3SK1@vn5LF zA_$c<+eNCdvSiNTNG1??Z5 z0xpl6`LgZVLx6*jfxWl_`^*K%$~8QtB_xEw*&Msbg_AF*cjiTsJW3kY&dSNXR{*S95u zHBOo8s_V)squnY7I?IMCfJR&ixb!3;rEWPl;L!+XI06p?@Ddm^M8cH1ZVbsfHPZv zxk`aT$qKSLg1unT#8e!k7%gd@_lZSGR*~2(VR)O0b)yoWl8=%GTogM<6rgFXO8im4 zP(9a1wvA>@cuyH%`TRCkFWpn;RZ0LS0f73t%L!29gIV1B@VxK7w+!c~Fd@%|!#O%S zGxSi&qbgq&&FoC+R5kk}pYIOK$WT_F_Q=NKxfUha)MEisrGZIi#AxYc=XXf2lC?8V zD|Qx&y+D5&7U`d%ST5*3uJ5@;l2;hN>ACD6%@|CC-G$dN8LTVjYDl@E0S4o6@xne*TE|MW!>YUqmPuw%g_GmK5@nJb3X(#0G)00` zdbjjQlM+*=G|f%y8D;jK%zF7#`M1zN`q6*?D@_3*@*wrke{~JpJM&=v3P_HEbYie6 zIP+^@u>UEdpC8n*fBPnezxps2k*Bxc;yz9wvm@AxE0CE1+UG8KIlPDmV@?XRI>`*0 zz{23&Lzp|8puI!2q4^@DZh8P?@{P-AUw-oOBpiKKolEw5ZQ9ty@W*e5_;mVQ&tv1) z15c~93Ow=g$x`@9lz@vAn=xGkMk6*2u0R)!%5y?@vLe4hR2RH3XOzlVRC!xS4^u(V zuf>+W-=`VnL3;N|Q;&me%t`ep z7g0r}NDaKGLKIR-4qO5YT?N2&5{7~w3o78n^*pwFUyn3t%4=yuQkVujGXf80K!X9u z3_^D?Zdgr5qKSF|mjb5vqRNUM=SJ%R3tSrBI+U!CUR2jt&t8q#Cl+as6sBNA9THQZ zJee{#EgLpb@Cx$au%Ev?Yrww`W)5?Z9}mRvrn25m+&=~c7iPWK2#6_Ho{>Ps+EBWv ziSqYQ@*>J(i8+JT4Muq3-v2C*PewA}6(9jMk$IDfQc+`50RY--CP^YmNks~O6C@)% zEsfNPPx<#8nOu>Uax`%f-<{`(d@kZT;muAd_=F+IwaF2-?=0hBdmc+`JD6YH0ynPk zW9u86h6uYG3)sECfP?M13`#)9Th|7+0Z`ylLX{dILWTLbUQ;q?=2?);1eh@I3xyFG zjo1Z@oPLKOX^CvnxK1R-jPa(((B~|rCxwJPp_FWtSS^ukn$~qro?B3c@Cm3=2J^9@ zQZ!CjgG_4d5Q_M5J+2GD1{#d2yk+!Wo=PArzX$J~0yhgLU}g7r{a)4_Vm!L-IKH!xC39}3A)*`*g$uOXV`MEd+NDWqdnSs=;OFKPwCCRYPGQUVXCm>+#9I_Z5- z4HQt{Y3-?Xd%zfFjF}1!RDLfCaEU)7QquLNEj>4Po}~g{vJZfy@56upQheXF)TcDs zd@y*@%UF2e#-o&IY4h9y&{Y5Sv9??VZnzE`ObW&dqWP_KnJH|38S4DTz}^xCWj`mrF2AmA83*oJ?y~IWVIJCk`Apj zd7vnNoCKlAX~P9omtw8BJi!7j6?>huCUB6_1zAv(7DXSS=xHY*Q7W=GgfjDm0tn`% zbzIEzni0urBbbyfoaI7g1hz`%QY;u!-Y&KJvZ%+>xYUVG@qI+V0tM>@6$s?_6AUA> zm^-}YSwoX&^6L)(X@Dj$hBQN{mg#BZo#T_vr^lN!bXXP=K?P|4 zgmQE5ae?e>;v{;!L=Tww{2dB+8QOf*WDgAR279wN7GXZcJ4nfTz z%ZOC!12HLmex(!1P(v!Lze+5ZT$4;s4a(OI6@W>OOAm7eNt(R!d6MLK6oCP2%W+Nt zREZ3a#9E;UluIf;9Z3RDnElZsYsD9*q2P5M2$JZ3qJi7A4utsR_!)&@A}|w~YmxPV z?pmQ`M=`N07L2+;<=XEB`Te_SG#iU{$}9&_eo~sXkjzCneBU^ly z2n=Z!LzIe20V?-J1pA*I0@wwDSl5yBD0DkSJnP~=7WfQj3Af(9jM2gv^JjLjaAvny z1P*rQuz7n42Rkzm8~mZ1|2G3KNOKe+15%C!Y&_#8dTaT|BF`%hg+Xu$XnF7`d{jTr z1#T2k7;52^I`)iFFAY=1y*0qDzbEo74H$p}n8FJ9N;W-_VI(=?8UncZ;;gS%I(~Yh z98^#?6`+_blE)BNX1pD#5R}<23g>vD2vR9e81*{(wFx?DNs8#`V#Xpb1tJyE?$n-6 z`*~3%8;$_1Hk&pqn3dZYVh0Qhm?rzHP!1r7Z@y%)u#%usGS^LOOL%-dUh;uao-N!l z+*NWW*2zcO`{nfZWdc=1d8|Z0r8)HDbn&Ag4+78}md(nV!6N3fd4FgOaOlC7!N+$X zWKO}B)7uvYd@;8+VQy{!L>Rw(1@`49Lk9F?lnSPfM3{HC_rNzdF?joCkYGu^CcePe zMw5y;Cza;gm#Mbuq$`{yEwh<*l8Zr|vZ4($brGrmof$S*SeOM7VS8sE`v*sUvy+(X zrJfv>%&BIE6a}+B&XjaumY#wwG9xBpa_bU&d!uNCU|Xz6T3)&1I^g{j8_CT(i7 zPfVYW%ZZ{oPxyCTm>qY27jUVVF38tG?8IwUS?$@<$80HnM(MSZm@YuCe5hv6XmBMZ z6rt=+JLMUY{79MxW;B;1MW$)I%*Zr=$qbihh^Q)sg8d{_qQ;ko@p3}8OAWjf3>Wq%AXEhg7PL7EZ4(?|UhyZrtvR8|g>xlPwV{a~MNWDj8d+$2Tt%i(ur4ozg9A6*ieT# z;uDUP8M_AL0!u43ZUVDKAX6`UBE0}p!73@`LKzIJ*)CC{rPoU)N`8yUH;%H8PXgkg z02=f#T}sd1666I{DPfw)9Sm_vVC2B3fnWejGyaQJzH~ca7L1JNyS4)X3Htq@}&V;s1=w4V6Y1; zT=%k|!LE7?_s2NPZ}TfQA&UJsH!%3s2O#l9rI0!O4o`1i%zZ6@;p?9Ozy1(1Gs5J1 z*Wk`ALFQ%vYafo5&gA`ZCLyWmom-%tebC+!sADAjIGw3KW6-5eof!-p%nS!O8c%#2 zu3_x%9-wWtfu1DOyId?vr?8a5BcotKr;e->!DwcHr>?Bw-sT|=#x0({dJ*q`coRFj z2c;e#s*B#!?d?NB`XoU*(IzEwbN~q?&?5sNfkmNYIy7}&pB{}|?5cYUt*}Xp44mNU zl7OJ_p1ATt@m34Dhh3*1Ymh3jI^uiHwkuOgzlXRX>z09$130?CKy4RoI=L|OE;8Ai(zT`CTQUyr;V=fhpz8H)JITQQqAVlU$G)ND{dHgqekBE4%(vnj$pum<1QVItz z6>@<=!{k{62*6rOZy{ggMwU#xFBy*}PYfh5*&#Do65ElKthB)0DFKlXA0XhY2Qlo# zCF5IX{S(-PWE3G7@!BW@K!Q()X+pvZJhE4$k!>Q+ciEC|=z-2OrGU!FYvOz^iEX|FFm~+?B$N>Zg%YXD-PK>A=v33sH}C_cU!#eEUT&ny+FIOxoHp&r9sBAy~$I=y`%*Ux}am_uN6 zS1@-Q7;betf$~MbGMIp|1>fJs;OFmw_YVFrAdz!=bYg5jUOofbQ{wv6`b z8r-=>$glxM!*U@!82fagJ6kX}H$eMi@YW6r)L$L{%X(`T7v{PZvH;g_?c&VJEY7aZ zVRdD(cN0TIXj_ZTtzC>K6D%&xVQF!`uC-54g!*G`Y#(B0_Xt;>Si&>cF7`gwIfoBF zx{bT{w|aawbgV8tw607WP{uA5s02VdtQVPbAe3oFd7~`72{(B|<~RBg1VEHHCF7YS z9GGGfOyIy&_>a&1Y9I*d$QEdl4sA@dX~y*cOH1vW?-ai`ZQ-m_JBB*uI&iK zfe{huC`J|5D4n^xb5mvkc(ZDsF63H)Z9@W4o3G6{JWLZ4WW1d)5kQVpA!`C|7JYA= zikbGnQH&@S^_esH5)*@JIZF1^P%@Tq!fi;UDZDz=Y2c8k=Qx_a6R7c~$|izJsvytl zO_|MMCCJl=DnN#cxM}5QS^yGIiA>s+-L?+x#3|{MBpH+LUa;|!Cu1o{p8(@LYGj&F zlqc^S&ytOEET=h}^bk}RFcqFI$wx+MTFX>FNk9T8Bm?PZs?2dg-Q=S(He1P#ralhI zU|NGFsM3@YBbqb7mQ8+38Iph?Jj6afjRpsp!6t^-PH_NPsx548j%nwfB<9^)leG!pWSzVb~am}hS;>C*> z@7?Ry-Oum*7T0`f=YB`gDvcDSDa(cGhM@&tN-THJsWrX*xfUn)EUHk)9%fazP zgD-Wj#aC`&dHLoZMPZlH^c0T&;Ripvh(lWoT)ui2zw`BHaqZ>5S@+rLY!3~@_c?e&8yMsNuD-Vfi$=Ei`dhc@u; zg`4=DuRn|L|M&v#-CyAkzWov|UA>Fzx9;QonIm}Ptt$YXKw`i6OW%3{$B%3R0LC%m zm+xM~^XHG^;^jM7je@Vfeg^-=AHRt&ymS&@`{Fa$Tn?qX?@b;jz)KUotMjqEvzMIO z=Xn6dvtIT!*f1^FcX8PACbgQoz-lQBUP?t1r&qV(_eQ)^O;uw)DmojXyf1J?ce!;s z6XZRMOKRm%{&AYfv|0egOO3>L*Feq(ftt8#ngeD!uaG|enq~_5{R&#<&V}}1VK+|A z;I^iC)$=bR?rSZc6>~{OdSpKXD|KXVxX#)n&ai02DUUnMg@oaxyyT2D3E}m zj;d+*YGPhgu*wXA4P>kUCKcd^GUKs4$Jl-1+4YNO z##+O!LS?9QAdOEzs@L4HWtfT#sd}xnUOLoCuDF02y`M}gwHMmL13H8qein!10|e}} zO^)(8*~zV_f*Y5y zEeP{zIZQu6po;=HadZ=7RQ&8$S1?Awt1q6!uiv?bBZrnCBE0+IEie(zoIHek_g6S| zd<)M#a}+TO-o0=WuRMPO%jE*M?rh`ct!;e$+t1+8<`UO#-p6|vZs6FF4ZQloNt`&g ziEB6SV-Xlk!11G-SS|uqen+yE#=NED3-U{c>9L86_a266r z{Kb#nMvUST13c~ANsqMZ-J9g0HHnuEbEGrVO~s2A;H3d32zvrJWz)3ZfmZhOMbA{b z``-0`!nmmKNsGB|=_NHEx-pRTU<&PC;prSw1m`)@fnT$~yH?oVzJUhp@ZgB|alw?` z!qPKgXzB|CYP)sR`R}-{Bekx&?RBL6SH>Px(H?+l(!SbpJBfu}^SyL&%%XFNM3n_2 zDo%Ek|CRwN+DA`oeJ}3y;mvbV<7&-Rf)^VI8=K%^C<#Tx0W^f7p-*W=7X8h$vCwlY zkEcRX)WimVd{>%Mo;taZS_(@-#%fv^SD=Kb`bco_;7KwvsZ5pZ>k^QYXta2#7-K>l zLnal_)p*oDFZs4q5W)N~%>Tlkn+(3)n6g}BRcNR_98@$?sVIxA;Gj^cUN3NkBR8oi zDAEzisVODRM>62e&e*)HGqhH^S}>5VAXWvUne=ih*qM>F`+^161fdFC)c55RkeD6t zo|#2~lYdJ24Iq<0 zOlSN|eFBm<*L6Ub|7_%dHoLY;g!_w^FklA@+{OZTP|a+q0F7<)gbGli1(>n-#syq4 zfQCBOBsmm_9BZb?je5yYFC#iQ9_bNSaP|5Ty!-xHFn@yekAdUAP#k*)kfA>InSv|^ z41RPI;r*)!?_CA$tl$l&pQydc!EtaL9G@I?dG~`Gc;Vbpym0;~{_B7CD?D@NFwUGf zgg1VD1rimny>J5m#UH3XAG17*CtXrENb zS%05he$_g8CTTL}ia{qS`nmNYsfj>78OWkfjpjWMy!6E@?FO*;ji-OVn3H#Tsm$)L z*v3oGTNB&k4MT-=)+ASosc!XCm>BN%CcLN{)v~qkSOXQ5(ft?q9kZow{Cxy$1uWK& z?Kz+Y*<(e!=lB$%9xy?dZZt11YCKyUkW#^&_I(rpM)H|jER%OjPA1}ENURnPpfF@3 z!=zPKzrl6-P1_*%2}Ms0;Ii(0e**Buccqn*gu-4sd9+mEjVbw=R8wX&DMdz4umqt3 zvXK3<{VdHbTy0OX*)tW~7*wr4H2>W+#;A=J&mJ2oayUyse3~6){1B-VG*w(-~ps$8r37x2DbTh>jmaz5gFMwFbV($ zFk&`q6&COivZ-r6IGxYpD`K7^p?a<$<0{2p1e8sY6I&!P+Q|9Nc&3atAhLmToHbv> zJs4=l?b@zYVk{E0o;{ppvRNk8<=@r&nN#7+dGZ#~1W4s^!DSwzCZ)-eZ{Q7Lonf)} zWzl>-Es{I|G6}d#^>-+&PbLC|3Pvzj;Jr$6sQJ4I)0Env(V94B$$%E~&NI>G9;EX? zT|X^UHl}+&(AGnS6-60P?jv2=87-c=t*MS?Gy0{5&`gj)UV#dLAdNa!jOs43r2U>XFOO*+qmC|Ie^|^7 zkvBO`H%;A!h1W1TDyZNS38<0J(8RBV)}kTnBERREF73wLgDzG2G+$eKFCglihwJ`} zniPe`Y}ut4Rnx^xm8MSrjy?^kl`&zDb4303d4K)Rg70$qEuxg9;B|td1XShXm~2< zH{(Y*|KJ}&V+6;$AlXUpL7kC25tJ8@a5#-%4!E`aDz0ySy8*%MJj7948jpcX?Y&!# zdA0RD2}v3i0=098v>+&)k4rTHo?n~FCuf%+YfGgI~qml$^iQv$~pcz{9fphJx6 zy6gR0;C)-DrWcX-ZEKBm4TSNYFWN9_9*ebv{)6xR&lFGT5m<2T#u5DRr!Pa5XPRz% zEQ?$zZ{4ja1f@G8 zr8sWA8l){Av!32|Krw?M*5&cw$g!h`aPFCtc=nm2`1!A{;ElJg;?(gi{Qfszz|PJJ z?_ao#`}cRsMo?4{$5<9jk+c!_g?#fbIzXi#X+KAn9527X#HH?)RX3KhZ4JHXk<=z+u@NyG0EWwKbyvSe+hZ+OT zIqs9Wp^&?_YXw`h1zYxob3V-*9ojFmF3lHeY?sV9(Ja~VQXgZuB(R{$iBz?i;TE43 z$ws;=nGKiZLxHFOGz!zz?Up#kvuON z5WyoO1V9&>ir|4UEJK-6#A{8k7cdrb1D0(1&>bEq>1=W2S&T)!`KxN1o$ zvTIV;J7imRKiPWI)*4x-nv#7ApoSK>^6QncZ6Yhe;F=Q#d>Bi_z?TK%qf>tmw>REI zj4OylM2W7+z+eivcjiCA@tv>Y=)JFDYy0K0$AGPm9a*N4-%Lz_O-9C9!e$9P3JxKS z-N8kTTP@|7V#q*&fk-?U2vgZcWsUYg7iuCRxl^xhKj3|E>YYL@pfn?QE#QY|1I~ai z)U!LemmhVWE9h7;?AAyhLrv60pp$z)Ef`aorc-0y-uI>Pp2_RO$VVWo@M;_MLk;dgKs( z?;Ga;06RM)-hSr-?%mrib7tM}x$dfaFSarD)bUnsfj0f3V+|B3hqN2G1_;?Df_mRI z(nCP*-ayy0LCB>yc$fcTvJ0n(qN*9Ujo6f~Ih7w(MT748{`}5#j@2Tra#5WFS}-sF z!c=-QJ(-U0K;A2-Zc0U{Gu5R@#HQb%a@QfPNiS3X7wddikf+@+&#li!l}88Y%>h(( zytn5`y-&&>pi5yUG^s)cuE-?$s4yR9QjpNZKUbj4`?kPjM8g8ST!0oEiPbU;NlFw# zje)kW&7XzqCK#?8*|1yaA#cHh&2l{rC2b}f;!=%m_P|R4Q~ptR0><6%1|gtMC4Meq6n3ADbpv-2xRCx#UnI?WRQ}71Of6OgQ7X^$7h;$elj$qJxAdKa6c-fI(KWd^9IWQ%ioAh*U zjdu^$j?ZkZ8e_o4k51&h=tFL{^DsL877(@{apZGm@rSoAA$)WzFFBPq< znDn`lOoW4zrIC|*s1`2|9g~bC3J_OPB{7rOumiYv4qd`WXaC>WS#3i# zLS)1kcd#0_v5Gqo6)-UtvVp~*U}8{YFb}xD{16w;{onEI)xU#bJkq2Ap~$e>1yf^+ z&-MUA0V#@HMll3#z~;$$C(kZQKMT&-*o=DXI+)IN0{yJ>(Op4h~d7^|YzKuMIfT$Z97>ygkt3e@|zaGi~};c^-4~Gxljo6KPTX-8m)<5fJ%M zVjp1yuxeN@-sCnhTby*L^LKgL*Nk+HG&g<{Fvu*W(e@~#nLpW)-p}njTN!?RNNEuR zN8VO!UU>w7i%S=xn|HDNS8sxE-$f%8I!F~dI1Y}3*vOY4N0vE!K=blR4~m4|N_LU2+jTL#C4urQ1^* z8PQza^Zb3A|Kk8!rs(J7)e=C9^e=PBU<(0ZaET8YY$0|u`PRFo2mb7_1Hk2D?YL7> zV`L<)2D$1$mYgCDC>4-}nDXycKMLX`?F6Tysmvua2DwDjL^;)LTB_CSD=C@G2-^x= zSB&LYUMmm=B!*EyZZ&(y>bA9K(TFAma$g z2pM;v;|Pr-G{&3=6F^~ssDglH8rP8_7B!o4*`ZNDEMVQiix2)DZf<@Hcb6|?MTZOM z<0y?q{=>x+rY;1=MDpvEc%y5P3ciTl-=4bs;U|t4d_JeT_2bYw;dQV}ToaSMq1E8$heS^7u>J!!iGEXLuu4_RH0Ql(g3EbaaBrhCNT)ln_H*XyV zks!tZRYC|6s)W<0ZsE(XU%)WPBj3}0jHL>{diy-?+}-;4QPGd+(uOxa#PVnF1J2Um z0A%?b9J;TaCR()n;5axw5$Mu)8i_{x zIz6kx$&JvlGPF;N*&S%{i`tc2E8M#u@xn8kd)$(==APbNiqdZy?Gb{{9j&@{A}2@k z9ZaM3o7Sl7d{mHO-qU66e1ti$rI*Fb`0EHJpbNUxoj$z>4M4F5bg^j4G7mb_;a)OC zE=hr?W5U$mHEB}gqcCTr>rMRjS@-u{W&mwkkz-@6Pc6a(a4gZ!S?W-q*ZH%c_iNFK zA+85FTc9P=yqC)gv{(YsVgPeWA)*k9A+Gmq(Gu6$W}kXPXFUL09`Od<$sBUGlLLy; zv35Q!1VAXUUpTWH0y89W2D*4>2eNBUl(hsTF@r2B%$Ew(w=$Th28=K$N=gn21Sn^- z+yEj0Ga(M_7%5Vv0XY@N0GMHsB8m-&@#epcv919y7J0l%rmAMHYAl&BBq>60_ZRv5 z*zQ$QfTg53ktl>U)dDl#R+R6r6XQ>Dg5JXY#dEm2`R#(WG=;fxF*&wmuozv$yORP{ z=9-x#w=!Kn*Y@*MYIxZBazIOA165W{DU>r4iUZfUdGm5p0xQyIRUm``3tEDR5jbFs z3+N!p9|#2IfFTSBVS#}cSPV;S>^y^0SN`or_Si6F(V8)%Pom4wT0~~buLTq!PF-?K z0&kH1{BC8cf)@q&Eesrb z`eL2`^6emsvf=Q7?T(g6m{h|H71JZWu7ENNbXU%gl@hjTREO#B4*?YPq zDP8huYUO!d>d>5ghy!Q{2#Y0XvCQ54q5jJuM{b6)Bc__IT3IfARH6f|8j;+7jdBkb zxV=vgC+k#IAY}QE8hb^M02NV$fb7$fq(jMPMO}BDQ_)NWp=6t4V^eIt5v``V*-J*c z80a(?SJq3NM;JiNg#n7mDKWqy8RL5Si;eB#L*dM2o0OcK>=V%%DOvhWwSxC1>g>vk@cLSXv^i_!xGEb1tne z{ohOfQi@n*qF8E_2VX2{Or)|wG)g(&KGDehTzdIRBQ!OJWRX)=k2W)gW%h=!G~ExB z$mb069C`319J%=wY}|XXB(jOkVNIG*`}Zn1 zt}S>#+4SBR7a5siCTM1^h?l-0fsEi}N=yMoo|gd4c5OF&!^?=$%*V6L7FC_B=@S~r-jNkg|+c{1imv4Z!R|lZo!Lc{!GAX9v!Ht=MSartJrFJpribR=Z!n8)AvL-#n7l;#? ziek#P*>Ci-XH@7ch-9(3$5_v#IuP zgmxP;Zfvz6%r0ypI2n)!DDC{p^m&raFXm0AF`q;PrwwEVEtlYsl7~2C`H(SN0vCUl ze$QxBn^rE zMcLnoI3ys39cak`${V<{`IqrvcrF1~GT&w^Kucr(isHFa9(TZus1$=@k@dxeq?E{$I^yiKpe748Cq6YxU$vQU!W z5$8zsX2NfQDs_Ork~Z(9uCcUh_okofILm*ufH`ms7M}4lYyV~fHMqVub)GKkyj*C; zaJMscHsHpa>z3ufo9mjnH}z|CYgi1dG4Sn7ckd22;}eV?F577u&78LmR+_Tw+mQ?2Gs~VE@~W z1yewqw%`_-lRcnGBU)F;W8y*6F>X2uQNwuI16*0NFKT~RY5r-np8fKv&ok!7KI0El7a)5V&85~?Z&8#ig%ZP3meNn#HLfRKFeGMkr5%Z@3&C|o5t8G~w=NH$FzyZ<#DTfL6e=4HevSniw! zk6ZO~sC_1>>>e`!cM_^5#=0|{2dp4hNX&+}CMn8(LTM;#HvX+j%7jT~KO87%;AGmY zlw-B)Iq<-hI>w1lA*`T5XNcQKT@74m*AmZiY1o@6v0M#+Qc{n&2WHS1?t1gw3YzR5 zFI~Z!Ii?D&_hzyG!n|)xT|%ZTnetemX=;;!f9pCP2gm-_3RYbF=p-(FbP~sp-orCz zZ{Y0dTUac{--zKZ)5kZJQN|RV?1PkeCYxd)R}c2VL6Ycm{xJ(uvxi8`#k@U8(0EW8XpRiiy%yQlLfeF`d zuW;$=HeP%FFgBN=0u4<7Wvl7l_ad_nP3k~`dX3k_K0D*$G8PLZJXp+TPl**%W~571ugp1_NULXSA^@cEVP?BYj(`$pJO{p{ z)Ep|ni;pCyEY(Plnam}kA5-l#foD52T$ADU6G8ogMNH_8-Vqwf}QNo=PIFnbWj*~V96 zW&;j5@mRP>tJ1B&epz?7hczbyQ}#2;tRG6_tG~zksfeg<7AU(}doaO_k=0}s4uFZq z!h-iL;kIeh04!7h7Ih#{59aiYkqWR;iPAQJsQKD^v$)56wDfNA((EIoooTL5zCxGE zMa|EsVX`#8+xgWT9H0ESdHWD<+&Y9`{PKAy2+y3pfiJ%HAr^~qPZ{;c0ekM;*~FW_ ze)eMnF2~0DFjd~- zj9-5d;r(mi_b+4k;MxKE<={x5%UpqN#ck7t^DfU_ytHjvn}V|{!5dRv-?h| zgmsasuTOiJHzn52w9w0@tYhdnSW-z!gqjNFPbpck=DcGX(2MrQ3flAM8A0M$Ts7j^ zK64Zwm9C{Q7L|?>CeCnrO}z7B1GLO+7Lz&*11K<IslP#uQ7QHamggq~ua9jKBEOM6Vr2TI!8MwJ|EDw`m)741FvlBnpEk<2pwln}H9 z(N(!HEDA%xzE@+Y2m;l(YcVrgm!4xFg9k_o!$Vs@!UO%{eL(W_V<*)y6J04uK2pFN zn{N_`5R+7jDaCH*f>cB?@_-LE{yT}~k^NY+2m5SrmJXc*x zkxw3KSTIp%z!yv;M#Ng;k2zl}W2uC}PokYEJhf|5l^$UNxD=yga`XB`YK$6L9b4v( zPf@C@82daGU@Hc=IlYUWhmZNOFr_hJK1M2z&FGktMP6k0&>S6@XtI`8;K7@lQc2m- z2_r;{6e^m@wHX$dHJ!SIpl;r6e9Ig_gEmgu0~gJ81T|?!JYk@4`}(~kiCgAQ>j6Vk zfR3m!HEx(T+?w#(`>vmz4*-`>4X`&>R!Ts+{HG_t9P#YA>o|MnCQcr^SN4%2pX354 ze)Z0IY_Apw{4rCD9_95{1vVBKUq27Neg|}K`(S__9G`ql0f^6^LVWQwRy!k>fBGwg z53k~20{fhUF1yvv^ht}NUFJ(|5^=oB#C5&A`KYG8zY4YN8SmlZqp3aM(t$1e^^hP@ zRQr}(WcUf6D5nIw;ynMne!fIuhVB!1@swb4@sBk3G-nk15P-mb>Q&WUU2fLCcT#e) zs>%#%pcMl!vM)sWsZs$tJjH(5;{>i&W-IuDrn;%LKA476@Sgh5+PfXK+YHsmwqq zu@E3IC~$=pxeh$a42On8Ppw>IGPY(D6?7i}+9LpDb{ptV@q$;9iE=zN%=p$AEd?OX z^OQ5g6}uU~s!3N)s@wdha3NP!SEMdjwZB}GC*)BU1(GRXIf+Sdm9jOxr_ zJwpQpY@N)b)~MrlPH%c2@CLY4{Z7i~Lnk|`9#9o5;ijFynL&sw-DF?nXD_DGbZ`ZA z!(3=mX>!DHs1nz8I|4K9Eo?)0@V&B~kO9K-nQ~Jih3h1_0IQ9^3M!Tqt+Kb^wF_|d zjhSBs$$O`HLtA*mb_ci!N|d{;MK!UfF6A|`sD90y)&K(^#KuJ)n_e9m_xa6~af? z0EC0$_=!dl)BMfX?m$i)`Rv|@C@=)<{K1z2QPA}}*!bQrL3i&SjIqx*=<*OVm~Ajz zVZIwPp)aHw@=S3A(WZ;%6D0&)hp+Rykco+|P71tfH1_T{D$q%ZEHid7~LB(00xdFLw#1q8n8f6p+)cEf(o8^|DlGh zBAOX3`8m>oEn2(Q=JNvP1h6bOT#Cv78nVX(g$lBm2SrI$sk`rV4%jhQ{LZ`sCD#Be zo?+D2Rl9;P53%?V(Z}C&^@I5-TJ(}9hZ*To?&??Yg>9Y|P0}8_=StB>6>#yA7OFBL zl01)Rc~L1+bHupK(-z%K8GP_81&Kb9$1yb`TGolovmSagS(NBwG*QuIjCm;!wK5xW zI@9tL&+M4P#J$v`1H~J^k61mJ#Lk;&!xrrcgx+r@LMEoB+A&T0q(A%2p7m*uiI1P6 z3QE%?|Bl)s-T88q)r>Il<*4SmIc6 zgf*WZRbczUhzIvZj5~s@qYG>v8r<9_4MU@0bT(6}0WRbK7fVe-VYEcapTR{V$EcN& z?$&vhmVTbw0W?2Sr|w*MX%Zah)1(ej2U2Aq!^d5-IU1550 zFl4Z0vlw<3Pl@a+VKO1&kWV(d0mhv?XpaHkZ+mq;XgmMBhXF&{Z#;vhumjdatv(ct z{1mZa3Ju@A=^NHufIVuWif3V)hB9p&1ebfH&cs)AKAENSvX}rcdlrA%fEZ=( zte(kJe~>nM24qyqb@41IlA$ps|6UU?4ZWT({0jCa+J$#_c3Vi^D+ls(HaTMjFGZ2U#vwud%kGzz*)keFCK&TE890y4Uc)-;>?9SGnJr=xiyH6Dj`2cH zPE=BfI6dE_LO^=0!b&hkqNA%-sa!RK7ANg7!xd3&yh&6w0WL*SR2eVxY!~PIQR0$O zJ-_UJf|=t=mDezpf}eyyB6*(5ek~c8@{)((Vyd}BCbxxX0e?J@lz|wCyZ=Qxri(NF zB?ggznG;Z--)sGQd2Z$8UQz)UATT4U)Oc+nu#?RA*!CK|ZE_$jQP8FEH6SP#`<0=2h0=M&Dc4uQK;@et+5gS)+ggK+()(ldPDsRL#zT0WL-Mq}oVUd?FLuXLIZc zcHn>+K&Lra3YtQk&ZVj%#?FA)b2uG%<4tp8W18#OHYyd=6imPu$&DH2DvQczBAG}- zQu0^oE;YbN6CK_HGOgh*+<5i|y(nNJ zd1j1_Ewr9A2ghR!z=Sk!-n?}fKfHM)kA-%neI#H@w_(scPkd^JP0p(ky17Jr?HuCk z=YfGix9+Ei;A?k4A_q)`$96Lm5Z=9vC7ZA@K$Hw>G1l_rR z0OozJL6;f)rG1PV6F>u4)Kf4}izFqTEo5g0qqcxco1!!=T5A%Lc1FP3#uLv-p}gr` zwdHWSXI1B&;_9;A`LF@1e5|q7#2r;k9B;KR?DvPo?CYj}7#Wk3`0NI}l=8}%BUVov zZQvL0b7IUF8w*vcg~kZD>i8f2BsBWYxtV4Bth*NL&Qk}p^dMlvW`R%TsL!>O zBG33z$$kZ!ON5P0uthyD9N5wr<5Dp}RPta8&~f1R4WRUo*GsEwPN`0SR^7)u<1eNa zaB0j?`Fl#!Yw0`K+Oebh)RvFMgn5!SR_38#-EvD{%Y|ACzEs&!`o(Iv>w#>$|5LQI zLL{dL!8}kfWt?~~BFFfMIi*OW7IsY|C(6J}%m7REf2m+f%!aY(ykEqp8A;26Yzk*a zWBMxMyhD1XT!~4hVn9m_guu<$>cAcuoxyEp>Y&`;)A!aeT{wc6ASA8qB4qHJDMwyQ zGF;EsEJbx|jrq>MZ}PAP{BUz+F*da%B6bnI>NfjEiAK!2XSlWgLIYx{JTd*c3dKxWFYonwOjwi6jrBA=0B>`4Pfjch( z$KOog%WtkwR$vvOTT5*JwXdf!fB6RJ_Jbs6`Sm5x-EGhqQS#Cb#`0%9C^39^75cq5 zvHI?ps-ybjazufiIE)AX&hLV+-vM8^hQ+Tg0z2`5<@Yp$F4`3s>I)RtQJ(YRsPdDp z#F{~BJY!-vFVYeRSy7j1YLV-nihGXw$R5{2BC61;{nMu%ECU#{d=}ht8aaGit>Q(KFk~W}FDdwp%G^o22N;(fdgns+BzWmuw7RsQ3;^&jfR~#H8=J+mrO1gm0D(bdpi3HzN*@DgSp%$~ z@wm{=oLVOl^OKXT`#;Z<+;zD4X|ns!TPd4CEVbyN18LxxE>l|PMVy&K z^aih7xwM4+0&x`ZEe3>S+XR+Acu z_k(dP8C7VMvYrsy^q3N7T!0jAn0kF2FJ*QK2Wr6(Mlr`O#=P45(P$gxTzs2s5tRZ& zhmVB-9D8O)5pOB}oR zbr5Z4FedL4U5Zcwxhi<(C1o|Lx?MXe+ro@x)t%?$f@>_J#J~zr5l~1Q=0KtB2hjMd z&?HsId(Bu;ugDB6C*N$w@9do3-}+jmRhfMR^~%i}4UPPBF~1`x@ez?~Vw_F;O^FKu zB(q-BJa{sAQX;S^B{eZ|x_2R9<{gDA>$uK=9bV(X(oDH>&iNtxFgL*HQ){u=v5-pa-ibuW|D=pi7+$LmdsK#m`RoH~N|+$k)- z_a^xEy#waU(*?R{lZfyT`}m3%xPqBFJi!*`#)&ke;c8R~bh4!`ImclxWuBA9$Hg@A z;(($7v=~6c0-XIVkT;V6%BCX~6q!ye0#(VKQ-Q_^)rh!S0WoF}#&xk2h*V`VO*#X+ zsNxK}a1&90EKILJje!IPRG8dFwaSsyI&9i8Me-jnzh8itHr=8~Y9=g>)XjSR#iO-2 z^93*I9*~AMo+y|BV9=xjRk>ABS*ZiGT*3EAWl{SBT&9v3yQa}V4+5@S-$4|`Gp9CY zB}Emy^fIF=H)>2heUv)T#owxnVFzefAZ%=b7fbMBSwWXDB#W1efNU68t=tt<>H(yBpj9NW}5=#+_A_oMbaaxuDDb#w6H% z4iChLI`AOB2Sx!}%JpMHpagJ$7@UoHImcHkB?gX&rlOqv^{HMiHWv%6Km=So@t@<) z#+%8!8^&Z|1RgMi0Yg~g#<72iMOfhYgKy!)&F^;aU)s;o121L@j@CQGKAXu&gj}q+ zZ#bBwiU=w>f;^C8UbU|cID=Qm&|soGjvdI|v9rp!6>a+pz1N#Da~!}+sx7m_B@xvG zqRcEo@{Ey)ErG%-&WCP4B$#95|R02;@#F_1Fkw=3DIJ~L)C|I3>88x*oMP*PHr zfv<#meDzKTYZ7TDIEiEgbmxE-YgJU0s2dxyR zehzG2#(V(TV^BEzJwkl`G~!EV0TB#8d642puyfAD>bFFk|tcV2}q z7bq_GkINASdi)T!|GU2fx^f%K@BI>d=Ky?pNif9I5Qg>7(Vvq=l5jsXlTtUVa z5XTBQbsH=KNHM0Eja40tg>qkvi{U=eyB z83M+Y;QFl{oH?=CM3nl2XT3c|*v zi&{La(1GFxa(P)snZs1N&S16KZvL5!qk2!3NObL(Io^m?Tfn2pnPLS7ib-nV1WE)+ zDNZ7}sLyPk?7^axJUy5*Q^7n#sLF8C`!ir$%KH`VC5Ad->4*R_iUX}OVf;KoOwz#1WBVCT^*0UUtHbkIsDhkY`F1mW(mIkeMxLBf~ua z(}0KKrO-54HHf+tC8_U=*#kz^A4al4Z}q#gXlpH=RGb-TD5kiS+=I0yAgS1O&I@a1 z!-PPEL2AsS^jLbHN{W;Z!HqY+E}37JlOm}S5S!e|>hWiw7SMPEndx(%K2)w{F>y|) z4x5CIy#$P&sA=`!_>{4X0oc5%IQ1id$Hx?K*`Q49m)?5WMQHSn&N$o=i6aP=cWTac${3Z}Wx-8pCt z2&VonQ?}0Ru%mg3IA;7=>xLV6{>)}#i9%60R5Amu%zSNNPVqJXIvJ5K#B3~UCt)Jc zVwuNu0$V6#z$F8S32@;iPK(xYwCBc~W3;F%d@Hp~-DCB>fEiBO*DCer$$+LUqV0Rp zjuJLMu+rG28Znv~JVXrjUkA?Z{&X(X3_^>OsI<;R`m9?+wuctGjShIe$a|36_LSSGE zS8;m#Utwc)A&u>rfcneB@8Le5$4ZyDhco%TQ2E#1pGi;Efix(7SAONFiA(l*Y2Et^ zRMrL+$-o5_0*ykk6Ru%<>s{PmegGX)Qz6QTC@ZYS1i%c#5*QNr662Ua7#ScEp-?C1 zb#kegr-D(k|5Wy^k<4@{G9$?>BhIXx1fmF2`d!BavUkma5CTJ(5E2TOu7v?GKBC*p zef*=^HfZ2YoxNOcVsehzG1VmY6f;@{7s)S|_YTn{6%+G+$)7n&k+zu`u1E#m$P99k z{RiCnqC94d!D1dvi6x`?F)Att=1M6ozf0uKjh`Dco2rbx`9_78-Sz%Jgd}0|Y@=%6 z>kW?`cxh}Tk_5yQSsj%GrUNF-=kHJg!VYlu&lJmBSx)q%4uf2*?EKL;FuZXAi@*5w zq!u|iesj$y0HEy=iyyy>#gE>CZf-!%9>e&`Imnr#z;Xaa`D~4MRe{5s*#0YD#^yi% zQEBKO98W6fvTh^Wc~MNZy&a2%XvXe9ciS${RJ_os+otA?8oG{oFK6J8iqqu=I4r=6 z0c1=UGZrnbiEgvt)i*gk$G1`?gD!xkWQ!OR%Vn{IEJw&VLdF&1&V%$bOBWz-v{$=c zN|lyO7V}8RCWxqoeeM*MMpkxyCs5kFp(-h0Y#Mc)CAfqoR2p|mDk1#r0GB{$zpY!i zeQ(6Kzj890Kce`j?B;{A-#w2n9GZ)4v>+#Q*cE(fezdy-v(6$tXbpaKEoL)$ObZZ! z7Fh8~TQkPHDm{qd$Q`P)vC$}<@!Z8EN|K`GMgm@jMT&LW(xoq_w(lpGUB z-FUB^(+Z>%(8Y3oHD(rA`nlaB2DT)BhnNA&{B_K{b?5Pc*>{Fw?r3sAWAYeVjW~cq z$T8Sl{?qK)WHGsE)6a=nMhs=|09jkn1j_duHPNzdVNWg4yxRi#us6%&u>Wv?XmHY> zDBZ0=YxXX)-b*hgATv| zFb9ZiWTs0%2m?Y02>E_v4hh6D$(Q+|WPqi{eoHY&F5Wt-P0F1H$wjsI^ihl}aqOSO zND7ibq%hKrEGWl@hY3_yfU9X0k!9XMn)5U8;|f7U`Own?0GWu(-HJK->6= zl7N%ZS@vB37eDrc87V8U@QAzl|r0w)3=tFafkZBD{YM;k~O!+(E^7@;Fw%`x^Av zRsvz7wi2@67+@y{*XU^gUDg(#pE|_2_WY%0pbkXSCmP>Z!vpqg9% zyq=Oep9*CGs{k5u#HoNn1atw7BQOTgFo4Gt-y2suh^uYrIL<&#F2QKVKLlD$cR6o` zB%A4#%}voU`Rb=;Bf-pROCEE2-GYxv282}crI(ME?Usm>9_<3W&>r#3#qVY<@rfKH zqiy7L@v_PL#JtIr+NN#HEq4QiW(}QzS#WRyHew!7nMj7*OHVvo-1A%e6LmE1&X1@u z8%=-Do%xoE)S#ID`aJ0^Y)VU{9cL_X`Mmw{l?1|*Ef(=wrk>qJ)AWQyQv(J%^ zE2v5E;)v4f_JuQfzz6Mno?Hm)EW`%%s@FZUScc?jlbAm_y(whFY&&0+9up@oROZC^ zVwdccT`NhQPYfz;-sf>y@%U6SUkqfh8kKw!i<3(_&{ti-WimluglUe=Erk^kB8ht} znRZ4<{oedYIL!%+TA*q!)S{)jXiA1b-~@I->cPYq!vaG#khk;0Au&XUu)q)&2)w}2?Jwcb z&P(0g=Vq8}kYdbgo4^G*^@i3qZ@W|;?PJ;hX<5B%a(e1H3DMI_3 zgE$+DaxP3mN^zm&d4a&m3&P1TsPT0`*D;b@61Cr~9q#}N|8>}?ctu~iuiMFQm9h{+|F>@NkJiln0$pi<)DYffmvY9|4m zrBN|B@O1$i7{o&cW2PQBq`rDhZ%~;l+s*uOP>Vvf#~%iGnIe`?z@`H({Y|H-B87#b z<=+b0%ssy|h0Xd2>Z0cp2x11D_IL%6Qzu-C7OUM2+?3Y964ZDz`{R+unsY?q2c8<@LT3|I`yY?Qk|3@a=oLR3nk zlz}lsjDZI*FR-939DVQ=Y;3=Pm?c8m&!dghxMx|yc`#{Xa9hH(0+q<&!sf`ID+C4) zTn&cV>=2S?PmI;5xTIP+mQ4dHqMj%1d~ZtBxG5(Mh{>Q#;~B$Ll8C7IucWmdl8j>2 zd{~q+lST8-s>fILI->%{kg8*>IFO^9l*(lFQc1YqD?W9AlS`ubG9@{fHeN_|snE6S zrcY?>6R^C2vG;HxCj&F!6%7N%jrBmFv4WtK8Brkw2rD!g*;5kmasa;kM%M*hvy_px zy;NoFTLwXrUU%b$;?N~v>mz_xd7u2$+MXmoqxk%3@U43XW9zX8Ve-m;=K&VKyokk{ z9|A+b`1~ovm(D_-J&`rH`l;P}2eP8433ORortVQpJS1kLO)^pKxHtM~)I}3ubDjOVb;yFakJrnu^ITN04xmSmfQg#+bV5oM_l_93ZQ0 z$ZC~0YiV;4tqUa84@b#G+vY;R_FKeSXvH8PB5z6okaTgTr5I9I{7{LFY+{`$Q?v^U z!6iTdCDQrfYsD%Dn2d`C6RK>N229C2(C42y1Y?C4kmaF(7o7$3{Er*JrDv^lV-X$r z(v0PG2}Qspigc2=1#ckA;AN5&@gmEKhM{9?G1yDx8llEIf0^bDmw0rGMYo7_WMHKL zE@Onq2puCd8%WD)1>@#ddOeqPAxrZpp}RCSLwp!&xT+Rfequg^`nk9}hY}%iMBI6h zq)0;rV9NOn2Et_Ug+lSgAr2*4T1|SSG%Gvu!0^62U!FMDi_WlBToI*!vL=aS{+C$u zyad(bA(?Xts3AJ})=3D0i-V;oui8nFP88GIa9iRm@2pfQ1w1xCp1D;*XHizPPY9ei2; zWBlsye}HWqbACE#fZs_(wPUnYnT7YfKw~glj7o#e>Rjfh@~JBE>&U-#Fm zXCamUILU#cCN|BOK$etZg(fk|zZ`pJlauhMt%s`4h#AF@xup8#sn-A(CT~^MgpHSV zfC~8K*resUQ#IZ1;RZ?9Vp^QQZz}At3dEuT z+>9YqOpyr)T<=9cCWr}PAV`b}=nC2AN0KiN2Tjs5#@Zl&gX0s77Xp^I6^mQI@)odl z3G-?g%?7vmkm2D#7m9gJx8Hf%fiwjW81eiG3_t$>BzjO(KWRWr6b$cP!SK#y06;u@ z9IM~^0`$lR8g2F`J)%I*p1|sBFM&V00X@2v_NRBZ5k9DEJUPKHiF$%GzE=Z14bnmf5Mk*DGz6UjGXUxtm73owT1D!U1 zRE&VBW4t_yTG2;}&;NXC#@w@=rXy@`7E5Djy9?l=Z3K}y2F;Jb-2fSFJz!L)Kd)oo znL&$r5-kxHHKE92p*`S2g?%xFy{Y|xEpS-838XQ#O7!%F3nu<;3WTHyhONF3W`lC4}Hy2wO zJT^H{0beA&PKv0_5P@=Gz(}5HIRnp>Q)85Jni8i(mK2e!h@uG)w_z{U$h?tDKuesu zmk@zkRtYn(rI!)(LGdUmk~_PX3d?1LtX7~*(@FPkil@;iN%AE3@udgnGS5t|#C{1uZA^iP6MLc^FtM7aPdSo+!FOTB-u11Vseh&E3bM^I@fpNs*&)>rE?qwWId`}4I zlA6_=3$nB+j$?|_w4y1hPO@U!&BiYAirPwsv||cruS4>_Dwt0bz`CtYV{t)kLIq*I z@aqdeXAa^mRMhdFsYKQalv77fCFacp0~{e{^cjX^w7VJ|McK@DQ6xjfWY-E+7eg)O zb7dWQ5pG*dutiwrjZEf&`p1<}iYErQzN@9a?Fy4ebQ3qpFv!N3y2fOg@X*oF+M_yJ zpV@o1da$JVJzd9Mse@Ov1vG4wHUOe_uit|$Xp@X644K`sOkOS-5MUlk++0hor0WA}HInXd(%HF(Bx>`drYp){B z$8z`QUtMR`k~rWCi3r(=ke%&xeius&%Z>vYaAsrb(sFS6Q9Kq|n}LB^TzL{h3OEPH9cyP}A7}M$BMzPRy<2 ziY)Ru73q1ZO~W@c7)3O*5sls8z+9K&;ug*bZ+6+?Fro|k`$>v{v1m)|LgG1Cdttp{9vGa9)O)5K`kfR_|=ZQcL$ z`A_Zq1vc(pgxp>sDkt`eqz-i$W04Dr#GHVn1!y|C{V#Ar6^eizI*#`@{w7v@B()4o z8s_{|%qU*P(>+|QFzWj!^6V3?=D?s5aZc{J#&97Q(+$e;iJn!Sr8%aT$@1YDr zdG8x!DU~+;GVK~7)%co>ISc2@spXR1ks+ zK_w+H1_e|YVaWGQX$~A59~%b+Rpw)Q5dU@PIm%xnoFWtsJ|NaN~ z&TpN^tIr=x%>5-pqT*lt`3C@i-~Z-$Fmv9_?swoQCeLmV7H!Jt{k-zJz?qVc&=tj` zYbblP9(Y;zhs{v3uwIBWGp1$G5K~S}0kjx*5+ZLySF57?x7QVNNlM8zvhjN%^$AD> z$>|1#lu~r~RAQvf3&Ddgh4u|c8+Ozl+u(Y3i=xVm*0EluNiS}5OVw`iBt)h85bXD+DPf{FbY)DB%N;G$18GPcrkBePqUrT92XSY+f-P*Zqq(>MHC=dSngv^$ z;(@v`LRbsrk@J9_fNY+MUw{^>hQ*@g-XuF0k^zux9-V0QJBZ^7vf4>N*RTW@14xo# zF@^z|c9COPt;o)WrTIL0v)zvMvZvhW36dHa;3k|q+Ui&eAdm{oli02et7bM!k~WqC z%k~LTYs!uR_RjA`tme%LZuT#TK+#gZQXxPwC*X)C?-r0VQT4{w6&Um5u@u-|YGm>U z0D-y4(7*y31b~2aQRX=YK|=sSid8P>&e&;#CFu>t_ltOi#V}&A2=zVM_$`ri+yR{C zX;UQ{jhU`bd!a1zU||S8A@IJ+ekuy;;92)81!I;;mwN(zq|-Nbrj>v$@@hQZzLM%^JZS}~Y&O63P^4__>FMwuau|4pD%m`u59bhi!BE5RZJ|v~Z10D@$ULQG5`r#FOknVN#(!>CtzOi?>TTOIpB?%0i(%*=l|F zZ7LO_#^1&Jw)i4jXMmSEyv2{IsVr#5M@IJsTWq|M2Uk4U(!F*s6Pg8M+?Z~@wkL%E z9+n6TGksm87-aJtVFuAq3a_NW=$+|0RLaYh3h*K&iAXi45XF={BrzwjWJ6k6Z5L*X zF}Z9Aurp0;*jPTfqR`E|$7Vp6{a_B0)S`yzLhk(5F;(Us1p?LLo0RIjA_;sM#}#Zh(S-S*i)Qv0jL>IUr5a%dNO+0I;W^<50{(6)mg9#`GjfNQ+kqp?Xmi z@R-p^D?RkiP4$@OOU)6%38>KoP)quos+x>7Ex}Q#DIC$?gEP3hFL-HENHZ8?0!wr- zXA}sK3UOu#2dE4QtcbCC(%7|Um#D?r(7B}S1q{p3MW|EVumMftiy4n{p7h)JXeY@i z&x<%F@8HBQ+O9djI;btLBzPe z{3bqH{u_u`I6RyhaNnmxp*J!1UOO&gI7x@hNHwu@nYDVgsXzl~=`3g9$NS|t5X2k2 z8Z#z)(o|wgW>6J2lDihoe28h{RFl>-1s_V2gy2kRD<{;hvzO*f4QT6Q{`Rr=V`)ys z-$twSs(RL-Wxb#UUna)*ZqD;;N1}O&rBCDX&#fS#R+dXd0aa35cw)0ijL;!n&rs$K zNmOkmj36VMAq-pqsg`|oa6EK97uFl+9vqM8h>Cdr1j2hqa*ENx34gl4mpmt5yN%`5 zTV=-+pE&{DTqFkKsiTlrpD9chU4;FOgCT(5zJ!f`{p%d?axiutd(g%2^9mQ#wK&A* z8m<9a_C#{gQ4Y{~x;P&VUq?gdr6)R($n_pFy^n<@1gJw>W-7crJQ>tAlFBBMG@ET& z0!mB?Gv)0DFn|avRVCkLhniz% zJX#tYORFTqGhx;m_U`zeEw&M?-!L2uTE?}WHo+9(0ivwF4kfok=VQ=IhXgmA1WX~b46{zpBlZ&V( zU=s66j@d$uuM2hm?k9TOo@eK_7CP#@hRQ90_SPqDi+M**OXn>ojVKhdvr`h8bh$)O z1r|#vYm$s0SPh&&FA;#bNpDy9uCg}%HBSfIg)-wHjr|0~WKR*Km}UbbEbg9i=Cp;f zv75sP$$T}HO;wVU{22iYLF&iE$f-+Q+u`ZM`sw9vl@2ZT?n=Z$|~)d;mm*Cd+UK2=tdkggUB~ zfi2>m)UZ_0;CSt8citie_v@rd#0)GJ2*Cj^KF&A<({mIV5s@n@x|+RD^h#f5lTRQ6 zF0uS8(ab(aNK8pYva_9BD50=hUOQ19i?%Z>JG5ulY$wbzi! zMWF)9P$Tmyr%ALFatSx#%8H3&HkXtfR;IupAS}?Zh*%TrMKiq6lZ-H9u)Evmd_sU1 zVk+mD3*Q3;JSLllP@~fcgi!pYH2GIKwn{>wGj&}uOD`wQnYpQ@9jQxoOV=~RnXn@Wvo!;YV|A@ zcqR?i`LRlm&@z>%CT2ArH|#uMy5FtpV680HSOWmJDhW;~FDI6gf=)y@37nH#nYtDY=?bs(B)t!3Icxp>1OM6omx%HTsTnzcbh(k3J7Uc3=41!F5A z@N%NgNplTaqawvXk;Hsa1f<;3Y3%t#B^97I&uzZm>rN@NbLGJhF~AlNX;ICbHv}PV z)H#4yz#+#?Hy{@(&|;C#)Eae?Y5~WTw2=vszed_>!$0{dLi+$*+Tz+5$_?pZrJGt{072f!G>nx12_n9Rc9T0Liuk%a4&&EMVvIT_jB2Eu+h})Gr#XZ0leG*^Cnm#Br`#R2-y5j z^7tY3pQBW#1wh>%p20^Of0#c%Ludiv4M4P!?eztDd4Jr_yAx&w6PCDvQ{#_7a<9$> zIi*Z9Tcsv2jSct$sbGt-Ul1eU7%&FRKqTFdIZ7#kE}T-=RDd9b-IO!1aAfsM9FezE zs^4%NA8r02?u8c`)7y0GNh3#O)&gpnVQ?4{0K%e>porP;LnV2Dz%w=!^Q=$D=pg25 zY|iA?6Y91fnLH0l zO?EO_QM%O9%8tzAMN#6mp}vveWWUq`ehHMFo@;fWy9bS!IRPvo8Dg_VK;!S$Vel=a=WA8jI#SgH361ee2ARf+p>Imo}{mUaT+*2HWAK17K zgq=^B>7xKP7LZei5iZ?4C{91mhj}@A<{A^Qy+XKn1L0Q}5w6}$K63|v%M&!`2;{_3 z3_kKu)prA`&qXqHwV!KS2$42pqf;l<&dY90g&7cKzYiNwq1M4GhM~Fpp_1RXK$RU6 zr@HV@porPX$lcz6W>lQIXxYjeF7)8MlVVEI(#oM4oT@i=Y$1~Qrnq~?zVH-k;yY;K zp@23?n|xQ1+?+tu9W2&iRoWyv)X(Akfnc%Ud80*DzwiBn3YfGOg4xBpr8CJb&y^Nz zX`kyi=QC+U=>1^oyHE!fCMHYrZs8$I3@BvT0i)rU)ASQj`NLHG9|$h3$fp!JDS#!A zj1h<{#26u~ZOCc`jH{}%cV>s&3|kMtkV}cCj_HDSBMxVN>BpHHC$kJIzgtITa20cB z=Lw;t9j0Ln2g>(;+N4{PmUFDEwXxVq37I(;9Flx(iaV2e4K?s?GC4*9UQp=ls9-L+ znAg3eMo)^&Nd0JZ2G~pmm=Z|&+GzelwQLG5;YM=8kH!q@aV-FelR2gp<0dySCWA53 ziUdMkQdKt6ED}cD`*b$|G69F=A_lpWeY7Hm01$5^uw__enN5-uJ-`Xvr*j3ovyS`< zhjBZ+UQK_^4{dD6yJB>Jrq1}ZBu^VMkC)Exgk6EY#4T)%7ZBurwLS7eyK;^+ua)^R z#}qBVa%QyjG9*ZqCzT9lOK%Fc2~55-N|Mw4>byiG5N6z>m#`fVVT>{Vt$IyezoD)- z*+iIVOtHb{2NIH;$ozzgL`Et=PLqPQ`T(&arBbP8ke2ItFw^Xr^}fm_9nFr=NNtG8 z$(h&zN1ZPVw{jud(}*M{nE3gn8M8V8TG)*p%B-+tgRkEO?ZgAM$mj7O#^NXMVEENVUU`TM7dc4TBwE)ocl83-L?d7MkoM$~ zmhrOdTcEW_P_8A4IiI?l$+}Ob!&ahw7hJS=vvx8^(_Bophs>xzFQquH4Iyf2+`uFf zbKU#uJv)41T;s*PpNp}jj7{Z=l27Ew-7;L7B5X}OG`eW?xxe3nF>OKaSvQ&i7le>$ z<6JfP?7*@7ysl84|5zv{ysBXvVnp#Q;2H zqi@ab7$g<)3rZ3dc3Y^Ck|mcWfK5pI3~IQ0|7 zp-Tyvd89`a=(!V!ub#v3#)U^iOg}iDNZ^IGSHSkFd;9=sd2%OYK|FmD@#V87FQU%; z)QXr2pon*o6%^B1QeR9{7ZFUQsCK!7GuyL1sivdqH^19%2#F|nIik@P3a#1}?p#e( zzZ$^Fr0QEslB)f5o^|bP&5ml@pL8w%W%+_hK-K|E9S}t1{deZPHLBF3Z2myg#Dv+R zni>`ZJ9E_Xx!{ZH7Q8`khU<3m+E_0-{6Ou!NC9W+NYEO;E7~x0+OB&YFKrH#A5H4K zm3J}9op`s*Clg@~a&yw6;zQ$nP(U3cLNwEUwYa=0bGA;3P!dP8pxL5G4dp8dMX|74 zBqx%jDCkuNT~;N+m#TKi`LT5AM2@vl!4;oW!4r>`%8=<&VH)(0_K8ch(aUuNy7AQZ#jB{j6>8B+>rsuz zuox(;fYSMP%#xTGgw_9{`m9(N9j0^>=dWQ#o~Q*bQDzEqnx>6Clj3?)^sj0vv{aD+ zmkf}3zb40msh6d?U>zCX!Vqs1`Q2i?0@78H--!BqNg8H|UE_sbz_|ziIW8>!I-(vb z1+7Uk8n2AJs2Honn~W-|XNfOh+vsOw2XF$Ggp$ui;LKtpV5sfpZ9W59j5sWBW}0`740+-NCGrSiEXFAAWD8U?2^8SDwB`$ z>)sol#k(8-USeB}NfK<}RT&$_1FL$~*m;l;5ds$(l3iN{ilHhiCZ0duXWw0B)C78R zen9S??7^#MLJF+5fa~8#3>IUwJnUqQl-FFgysa1DI>9%|m`!EtaL98WNk1}qXvJ6Pe}JJef;#Oujz!j(pnqSe#D zb-fd1UmDeffjBk&q;4XpaEh%dO4)$1t-45h178$SMzX=7<|xTzsGF081Uc!#F)AiS z7%<64?7TmwVgW4^vTADtqE<|+i}7{(dWn^$UQ8TOV|r;OrWcrtpLA@MiP@sRCap26 zFObV~$Zs5}yGAJKHH}P(rht(LCLCkBu%`;xR?JVm`+f!V%8oj3s_Ft*r6;5<+=ABX zWMZ`2d#^N!3!NgN-|*@_?yZW;WgsL{vih@)Uq~H1Rn9;QXJ!l6!l+|G>2wEG0hbvw-RY^DmyeMzjPlNh z@&NH>(0038v2F4qb+PN^elKZd&JYsS2v%i;taczAlIgB+DmF;~vDqmVoCekvh=>T2 z!BpniCuNuJia;x*O4^B~2&bP%GtZPN@hH!;@9p{88R2RLZEAW7N`!AMpqxynOr>5@ z)B!Ep8eW5dVRa3g;A1SH1B zW2W~fvIy-Wl_3R7PH|ymHh|>xs0>Pbb96HkCBhCip?VqvUB-g0gD6%r=VI`h*TxKl zX!c`CamgXGLK9Pn2ZD~tSUQ13p`0u7Yb24AN^n#zHa8bu5Wc3|$3EocvTtOUfH%vuqAjmu~Y8%j3+(h*0T;xJ&B{m~)a*0rMt! zi%-{U8yJn3iJxz|O>k4Ktdjz~M5$mADp=&x4a?sO?K&Sq1zvJ4WdRKn7+4u;(E}^_ z?|Cq095av@>%CgilmcaNM4@2=Z=CvHr)#;A%2LxRa|$`?+1B+TgH%z>TswQQaGG;S zxB#tXRuv@A9>)SQ;H5TBXv%EOa|4AZw|L#@bUX}TAo;|vJ4VK-lXvj7FTabQzVRYr z4Es+&5@0+;_~U{M@@;}HW+s=zQH zK7Shg^ZN(2>cMevJPijk;_{KTh_G`}$y z)9bx8q!h#kycDmEm`n*}+<}g(9H~f?E;)!@!(61kJd70Y2z7170mMho%5cm{!2Om zb;w7GN6A30Ktlv{%uE-~%ov|jO`ZP^W;}ZK*lax}Y?lIpnBPMOj8tI3Nspvu#mHR3 zP|QG%+T$omDpnwhmnvC->|UoDc6O2M(#5zt0Np^GxLP5OtDMAB0m=fpn1_kW9~Yau z8;__5IJ5JQFmC*t*r69PI{?Ki!@vV${7e8P-*m`8XNt;|{Fal)P%?{^Br&SmxC9S| z>}wPi16f=)5OEmW;oD$(fD`&dZ0JY%9B^T+5Qk*+jw%yo02)1;F|%rjpxNwQJqw6X zz(zCi1tk!fbCMC5fsj*;!T?aHz90E~sVL%@!I%86og)q@8rZx&h%_(hheU*{cMw4sOm5QnB*2o3YXOr~Fc~nh#8d@@ zsjwJ0)0qXnUewBPDfEA;Nfr5V)Att;KwT;d9P7iyYT6=eUuzs8ExtLH80V6h zBPbpf#q_b(a?6pYtf5C5(%ijStU0$Mg<7b>30~?xjqj8lBqlA1? ziIU|^#Saa;NoS*?)iGTRY)P@OD9I%59$^pYRTdR{gJ(CsnA**Km9n)3S;K6Z@oMP- zm)*b?qse>2MmWI4gD*Ynr2sEzfn)XAsn7}x=R(turpB#L&aB z+Grwwr0IBjLiYMr=u|HfX@HQz;Bb#waj33iU*!qa)YRB7aq?Vsj2FxRD_YnJBCP?o zN*V*wNC9i2oKGG5h`)^^^h=!B`GEsj44lmOQ?%+cr4msAbli2%$1^+sC6>cCaB28% zE=;8q(H?ve$NXthu8J2&1Phmf8IZ(cfF@R4mRZ<+Dpbuv!J5F44jG8pz~$jPSn>@V zTD^_K`ZgrE=L9XoRK~WmK|~NCkmNZ@1QH}SFP!8G{@zZYO9)&fN(pF55z=>;U&Oue zQU*0-0&$mnyg|~bo0%PeUe*M4@y#gryhV#^PBN?4kn4D2FXQ1xUfRq9vzfA;p){!b zSL?j#JfEtp3U$297}^?;Sqy%iJkv}+Lr!ucCMd@QI!Q7X)rqt_P#f08AItk8>7nY2|>;N zNYP4(8V2T**d*;XrY|q=;N|5VFcklbXMTc@b`Imey8S%i9yhUgNGeAZ#>wM% z@xpUg@XmYBAcTiU6YNhuc!u!7dEn5+(m31#vM`&^y*$sYo~>J!(7L9Y4j>u zx%?@&i|!ZYvvdZwn-r1(B=YRsDKW z%NjtYO39owiKr%8IZu`n)9sC;otd=J_t^sj4RBMOUmNyCu0Ej{yH0AA(9Eyu&bgO# zLc=2TKug`Jdj=I|t}PKwuPe2b`2Bc4@A>o2NcYP12UtbLxzn3dZ0upu&t`!&eTe7I z{H{gHsv=vZR?uy3@6}y4qV`=p&Jv>vph%S+WUpB-Gw{Gmksi3X*=R-MsO33Ha-a?1 zG68cOtEFYKARF3xP{u!xnshPqOX?*?swv4!#xc#&IfcjMMx<5xX)Hxc!;{`2G=F_; z^{+ATMZB~8+YR8N=8-W-7*fS#S#tC;3NsXlU^VGjl2MTb z{}?OS8Z=olXtGjO0S^ov1*GZRr{uQ^PM3WKR|DWM7|^4L(V4wx-!F^A4nqPKL!cy4 z%Gb^Odd%C1O(saz;I7|5OoMP)DaNDWhlkQe}u&neLN_WycxtKFnIzM*Y+w! zqiw8Lt8DU_%rwogu#twaCZ7h%(XX|#pCa?>B4CSOK#A{2kH-krm^!7BSuJCP#1(Wk zBJONM<0@|ws4=SbT5nzpwopqgcHi@i_lwDmcr9=<|8;N1Tlds7TQtwY0z_CYJ?7wJ zx~WkA*<=P?esnFR2c0{W9*-(T`sNugp6#NO&+fHEXxUF*TIAl0Ph8Uy$z7#_&8aVD z*ws5=Py21h%6t44gev9H>g}A2aYf2-tbmJjjF##L5u=t)er0+%kBBA(smhef>i~IP zt&*mif~FlNrk!6$WyAPXFuUFE$T=u~1;_9Ic}e(6zFRR#jfyvtR;iIo2J7NvKtx#3 zhj@1U2e>%=A$G9UFm%+(MC`L0$ep}LD!a@W7arTUIS77jrgltO6uS3}nH~c^T>cT3 zat$o^v5=cMvHfExbBTl|4j47!&65ES5FwKOi-@?gK^Te3{UF}oEEnxT31_wg22Bzp z`!9q6i+cgQZP$=XC_9;9swi}DvF^a6z~{i=ki2F>pi-P02$Kw3xw1Her5I5oA?i(Y z3$QL;%91~uVo$KQusv*T@G@Ow?;)TXQpd`CDh#m#v6+!PNGg0A)oCCO>l0+&*=Q)3pfs{tVI~MDT{t+2bWg zese(j4EbwjfCp}#&-wMs_j$i#Ku$@wqCQ0mjX8CazdgOwgoH&0d~@pt{&z3@3;g)r zY5Yf5zlxi2xi9d=0x!Pw+J`u_xr4XfIS+YAsnO)V5W@X)z<3xq@pHw-t^fikq*eG_8kzjR+ilTN}mOBVUV$klAB`12f%&i&Jr)95qx$JH~_-QbGk>kfWx1P$3)4O3wyqO;@Rjq*Z8KL3UDw6*8B? zmwZL@&(;y;!aAAFzyuntu~i%COGz?>OjU=M5{;__wq)-XF9~A*d3b%2Q2CmvO(N=8 zEvZOmmpnvMcFdlj%RJE1dwKXyUJtzVz7~y-i<9aUle`SR^t$=h;-Zh_C09>prjuQJ zH~_}HJkWw6i4BsA^@+WYd%#J~=A2%1PWsb<3vFzx12{mlzlYhgiZuxq?Yo}P@M)S7 zM6;kty{^3(E;aW~8!6s^akGF6rhrS95&h!Vw;%$1{q++q1BeLEoZe_&uqJ1r0a&{E zY}R{WH)hG6tP@2?EUGe-bsQwx<@?8W!|o(SHNLlcvp{O{iGd{cJTHr=5z11f65V4y z;m4##a4Y~Te8u@%cv<4y^eir&%)o$F1*&Bo8uc(Br*JIMP%6kG2EfE71+21Oq)1dS zxfi!_ly2cD{TT0V{B7Li*AS($Sqf_a3Z@)q-X-%iYl8cac8l1q%Fm5Y)yRaii#$NWh2AOX4IY?RnovHCjbRX z5J|K~4T^6{N^NwBf112hlq;izAcz1$_Q}a@kNhzS6cuWXv5pl~<>E+^Ax4SB2DOIK z>YmG43YCDd%yJpX0WefPTVcY4&P z)|JN~>4<=%Zvh)u71zH8jE5i2TvrJQJD)CVm7-w$t(Oq4-3DL1b-;ExI1Y}dJiuW&E#{CC7O`)H>D9ISF#nXj}Ae?}nRG|UF zS_{4cFjGmrOooS4jej%n61P*qpekS$&>&zLfDmeg0f)qNsrk!mj67=+QHl61|HYJc zGG+tQaRu4ghOBlf*c8~sHKPGXOoMLEWv-nvroDldA|IOZXW3h>)J8>9)1@QVxkFdL zuQ!^7lL{3%j@GE(!bzZ-K2m*z=KdovTSRUBLoB)Aau&!0K&bcC@bOphYOy)>|>s(ODyUm%sZ3Z znepL)n81uLym+hye`emRH^QwOp2}?TY?p`C@9ayigbsgm$zOY2gC}Ks-=+)c#5A`Q zg3+a%6u_m*j?_tMD(C{|ZPI#I)M#ZXAWQulQqz-MI!TRwZSOBXF2!})?G`dghyBJq zoW{Gu-^BTye}E8gRRi5Pwg$U7;i!P>{lw(v?^K&Jo|S)qjpgs)qv0Kbb=Rqd z;I|&tTZM@bbJK~PK|Ax*hYjA#B!hY=<5J7OO9@ASP?7`1sGyi$L)fK-1$3b2^y9OO z#P+P0#@mvM)u&l;$8xeU;Q>1Tw~0PKCLHNLVtj4$ zI{x6$Mf}%yUci##zSbmF!Vm<1>DzDMmv5cN+wY$H#K4ON!qwjfj=ZZl{>#T;fn;EL z2RQ#Pf$d|88($~v97)os-MTbNz{#H~Hf{hie9D~=B8)Gd!ScpkWEB6PV*QQZ0H{D$ zzeEBZ1|SgPxs#A*jsc?kzJ|lEE`c8GfL8I~d>$MLbb0r~Tex)P4xTx67%xA60@rUn zz?*Mf!S8#OIn!6nSN7V^+$vs?iftuFh%(94^~)WAty63JdA zw%K9M`gRAF=(x&prb(Ai+3ePU7vdo&G1RDDVxF4&nF*gbmP_u8mT2BMB4(3Z#1Y2$ zX}}Gx#VOA*S7!WFnoSmFo>!uLX?I{{H>S%PkfmisOp|MxLc7`U*UnPegiQ+Z>UC16 zPdb_LoSS|%buR4&g7Z?LiFJ&u{wd4pYV2D!1|-BAlK-Re|dpq}yKWAFPH z)Q{hiV*jS5NhP434YbF#cq}(fIab?s|4X`zq?0cqIgV9JWOD*s3}o?NJ1{0nks8_e zB2H>k*ex=NT-L@XMk{zy?iXzmV|?13_Hog0?8a=IKI#!%AHIR3qy%-~C6 zyht?GOY8IEm~HselAmSh4SC1wz22QiKqWrZ=WATs84HG61Kz>t9! zV>iTnofbsdkT~Mj)=#j#^#P7;e-)c|Uc(Rgl5EQ-lL4Wmi_J}+ZBim! zbTyj!zhPJsI$(s0JjpX!s^qA$nCvkFW0Ew<*gI9SR9_2uJRti4eLic(B`N-=XWqaF z#y`6A95!hG#ossvy#C51oIZ6MfBwVQX7_s!wbBT1=jAl^Py8Z9IDh8nD1$HO{zRb! z+&=@{Kc75lOxa_K!^0O8$KTA&zTr2qG!x{^Q7AJg3J#7>doWbSUp##j@x`-LrVlEoH(|Hx8J{k<3~5~(zD00Tm&3Dyu@4YUB~rX_i^&*Cbl*g zxOVL(c6L@^PF={-9g*r8AqJ{&?qCZ;NwP0X%zh4x2mwPg!^O-?Q<{Ty^C+hkKvLAE zA|gJx2N_3jTp|n$=n#{`ei&11uiKS~Z4gvj;3Y?8RtkEK=5?t=h~ii*+;pOB6Vw~s zwt&le84z2y%BZ|>UO1gOF6RD*18wTh(J^PH@{v})HOHW6_xW?*tIm051P=R%S#(Wt7BI)4>sf~&P_*a9k_e3EQHftlB9xG*KP zryq;Ewzk%T7-&Hcw>56H@MukSJ@dtWql__ExlR0EFirF*uQ22BvJQYL*THAiJ5%M7 zRs?V5Qmb!$2qWIcNk?6AVP=k?8BmS7cn=&<-~lLQqxP>zAl z;7Sju#IZiFP4&^@ZJ|YOgvLCyH}3WCcaq!g=QDTSwefT@V7A_0SMXIV=mLUX2gxb{ zE@rNq!E}`h#AwaPb|cQ1C=8Jtl?=sVyoP7wk8v*iGrYg~H*st6B`6Kfkh`0QbAedo z5MDOJ)%VLhZ(7Nf&NfQx9IZ30XDxI7$?Ja=!`2yGIrJyBVPVF(`Fsf^GmiwLM8vp) zNW>5pDLz;OL?W01ge4gQqxzuPb&+rncaQuOhvIVxt7QiD&_sUs>x-?S2EG{Ur}~6s zUl9fluWsY`y_?m?hmfPT+<7U;obM{vzbVAHeB@a~9wy*jDTa_3I&md={G*Z584GCw z)FhwtWbB*GY||*>3& z!8$*-dUhmxZxwEV7S#@vaexpN1LO>v7$7rn0Z)4N5(fesDC50-LOutBlb#t%=5t@) z5dQs>zrruJkK@DDp@%ZqjgfKe$OHVfzx-4D#ZO+rjhjcn{0Ueu5xD&_;oh^riJvJp zui&w;EHST{t*c1_MK-^N^fMmwmW+ObX-p!}(?>9V<3%k0{8vx}92}48g4<3{Acqel zzIYn()n}lGHnUz+E2Bj|0pMklSPa-+jW}{>1Ixt%1mMWwE!??#A3Hl^69=uN#Z8}bvW`gpI{!?HPFjlxjHNrX z8_y;+Vy+vMit}Hg zKbOL@_hvzxD3m{2-B6-2z_lWGLMO&PeOl1|{l;i_51^$JRPl>3LrU!=Dn&lj_47W(m33Xfj;^7$ z=q{8Oec1QB4)B(Z=vo zT>?w=QMmnMV;irmiY7YOcictM$ebolQBAaLWrLvc@jyu*>aX2ZvTDkEdC6)7hl5V<#*lq_c6KJ zc~DUCtN@u|ZcXEHp6-?9)k$Uw(W~=uG9a@^mGX5Z_r3_p=PZE%1V%sziOI51AW(oJ zncOoE$;X8QLI|bdUhv<}OwkE~XRf_hSUdeZacg-T*EUWej)FL9{x^M{#&I=} zHfmBi9}YybbRZIoeOAPfWX~en`WYFk${3$TidJKzlM!vp01BLv8;uoHKBEU;w38PW zzZ+*>-E~!}9NDv2+&(6>pWF6iMA`so?ASWoNsh{U3{_^-oA3rRR}P$?Q_lhAIZRN^ ze?O0hDB*Be;eU1Z$N1k|{yHwK4k0{*L9Qi9e&Z|e;-_!CfNR%}eKO!BGexfcHsSEQ ziW6@>W{rssSRwfg4S*HWkv6|cQ`vOIX|_*V0z<41CeNEH0F@4W0#@WdE-?wO-d zQT*i1OZe7T&g1N-fo=m+|#4p2aW>*xnvd`pr&e)Urydl*GqMTer@VkvOLp znY1M4&6t>DKh+J7PhSEAx{4Tga;$U+;9&u9NZ%Wq1hu=B7%eeNiel0H1DK6f=3vET z+UyY8c;?jPs&4v?%qa1GbNxnp$3_>A33RL(^U2|KlBn9C&c{LfqPj0O`}JtI*do_S z&4AG_-?;%I;Faf(&HR!X^iW};2xUHoI;&$PF{1=3`8sDqW`<0%f66c;7vb#V zr>&4z-E{*%bC1w|p0^*sg}PJY00!OV_w2;c3=p$+UoizedPYiL^t6DA?|8O=OJ&KR z17B#(DO-24Jzc8DGp4q+C7#}aGJPP`o;b^{C>6EE{#>ee|KQ`go~p5BwWhL_`pWzr zw0gUk-(~@5)D>yy;%;41kxOMM(j&)|G0zu!Tt!;|Mk@=(o0*$Pwaib>m^Lug^r`IW zRqk@fda>g&eG|7gpT)WR{|KA%0idfI-;_IEMP}sKFQ61@%Lo8+{E8+i7CTUsRI!X# zaTb4yGx{T3+WNO}e|Qm*H@kuq4HF=(K~khQs?mLh*4Vy023Z4&Q{zLE&YP6^{?P5O zVDaD?Ts!(F(C{HN11zP;Ck6{6P=JJ(JU@^OO$m&^AtmbYfFUdpctD^FYY$K+IeiL zPh-Lw@W*x$91(+HTnXYzFpiRd!~(#yGC6x$V}uxRFf7u)-~@h1j%OB81b1)Nd5wx+ zOBpXz;UKr19+`;c1x`O}L%~ufc za2^w?gvDaS3(sD~t=oqXBY)yrks@&K1;X7IfTM3Ij=%k>_qz^`&n4I*(B%R<-+mqP z(%IyXV<5};8F;OXG0B#gu>4nVJUNLAj}>@^rU~#wfi8FNJ#d}Cx+9kyS5zW7ee9uW z+bM0Dhrl>_;s}2GtLO2-#ap<3>j6$4+rld^oWPZ4z02d8O@XYD|BvCE-EG6~@)dT|l1JWw~qGc2l|e z9;K5)(Bbj$@vWR1(?a-FacE@7&+thvTx+=vDk!H zNl}e~b|4Ez?1Y<$G(sqQesF|D#jrX9)sU4oRFaKEtZ78W1h)b&DCtFJxNFP+A1fWB zMNeY_#uSs^&hN-N>*kdunQ>UXY78g${w~_!d3SII50?KPULXH27--vRB2eaR%?4z> zsj?c2!^aMl^^G#FoYx6m;kljvA7VTL4I9{5oX1C7f0Smu%+3TVuvKHrZO)ViJTlf` zGj?Zn=UNJ1qjgXQtE{;Z;whY2{dIhF_U}T&br3P4j2UnlG3ZddTvWxa8`(_PQj9nx z(1iztFks*XhWxc98zmo@0jtGD+*<<2?*3L~qIh$jd<_oo+{MucH=wEramQS*jh5~-@SvkZr^I?y{>mv z7ksDrO{S?-i$}+9L8f1;MK3ejB%Ay~n!ElCpM+g0vz(26tHvJ<*fc4uJJw0RaiKm2 z+DAMavxT{fe@69b=^~`}G{bFVL!Dl`7^HT;+W|7bdXwDA&-aNaQjZ)Eb(^&LFx{#y z@{$4V+*4~Zm1*Kt;Xs*m{gt&yhRo2{y5pLSd(|Nrx)&(%kU+(rb@p0zMYrkqV2aY@ zz3L>XWSZzQ_uRd4fO+o~FR7t5fXc)J#)B+0O*kUj-@9tlM4Ztv)nu#k8T<2VH;HI5 z=eF@xBVToL52*iRjjw^DpzdeTJkA{qQV3!KR45|y4g?V+MhGQC)fh*_oK|Bds}T_o zHhvA-IfNj`KzgWQ6lgZatwy*$4p*};N{W*%pig1DREbheLP8TaZ89TUv~1i3N!@Ve zJl8YTx;q;IL)1yndOai{w8YOh|3e%fe~uG7Kg1Dzv+n-Qw|BT z{+9<(0OH~*?jHIRoWJ@N4C4~R_yEhD``L~~N&+FW3`s=N9533)Z1o~e+t zo~dT<#)xEU*X81wBh|Q!oRK)evl6v6R3-%pmA;ehHN>-w%&U&=Gju+3)cO-uV5RqS z@!=$WIKiFPet?wmW(F4$4PAKk?8 z&Six6FWchsn1L?p3$(J6%k@UrZFgOv^3!gUx3jZqX{!iu&|Drp>^MBJO`Hl8iySS@gDmP(T^n^~R# zQr4voO*~p=x>0lBN)steGflodkcHk_M0dv>yp@Y*IN9G)A4=L3*p{S%3aDrWUo1k{ zGi1~Q7rlSVegK!rM_(tCnf?y#QIpRiB|X^SL6!b(>-x{NwtuU;;T<%8-TSdW0bZyB zROXDB+wa%Ei59IeV5tvh@sZ*U8;>XzWb9;SV)8QwK>9+ejFsX*kvr(Inu=-~m6Qwd z1OQbq7*4{0^*HWhu(kq!s6L^l zu@<7l-nd3z#*MA7;_$}%c8e1g5g+h_85(iKiK;(cJ3ed0t zA#1a;W`9k3;dvM3@{~@3sIIF5hIw~C=3Ys=L0Vg!U6*?aCGM=Uis)*sN4he zUIFkVYwhiGx4@p;i%69gp)(pT2GI>_+a(K`;dXbwYHdn3Qp;m^uVHv_AMYQ2p&LJT z9;Eo?P)JpOk_{#|lR zA;}hhPZI9JY1MhSdOgo)Q5kP-AHjcoAzZr+y1V`P1B6weiv`A4pMku1 z26Fmnl7G3ieXr}?mJI|scLF=-PXd4C%b+W_vHbq8a$?lu0lo~jDYF8tQyGz3rXkwFBN(ovVbSwY@dRWq#=#WYh2W!cQ#{N{T%pk)eB z)JWyrnK7C!M$hQ*d(~P zRGE(DVqH6n`u0|k-UPCMNB$a7&dkiXe*?-0nsH$XSCeAh$x|j-(7SxNb&<()K*jp! zt)DOIV{`YIuKC&}LqWUv*m}0t0|1J3G@U+Hw)b_JMuWDI;!}U1b+1e7X9v4S^M+e9 zm}Y4#B2~jLc|%?R7*2F(b6qAR`I#ce&1Wz-rJvc`@T?ar-UK?1z%V45eoQ(xm23*h zm91y-uX`zuK1(L4s$h&`0#7o7CCZpUm<*^G=n^GD9N^*~iy4d>^Uoh_{s0uVpfP~Q zEo|IK&?cxn$WG8aD&z{LsY`#7rRhJnQzFL3Vi ze;=#mWyo+py<~{EdGt>qVLP)9xv)10T>M>3c4S{~;3SSd_;O}6Fb=N>$L|X?Zl?`% zM&;DfBaEpeRYnBIWKmUUOp(o+o%K~}a*{e3T?v+V0FI4=Nn@b{teVkFz*6qx{GAVR zY4a>%Ah2?|4giB$Ap>Qze=TOQX7)NP7-5ln~KZx*g%`il;bByX7sP6w<0f8Q z-o=+UZ|vF1`StcO{L8y%@el7jhX)dnn04|<0G9;9efldHkHGdB!sXvnocal{y!AO` zy@(*ZcNG-l0p_w#z-4^x99F;mO54?atgo>`4{u`i^_Q{y-Y-5s;F>BB7(3s59r26L z0x_nw?ooN{r~;!xPaMYfzw^7`Uthw;pZ?;pNQ@fP35I>w%+q$gHr{^b4d{HD0(NEI z&qOGC6Wy*3GvKArPi+I)EW89_aZHJ%^JX(rEV}5KsLi?Rw*w+tdTo{J@Wg|qW4;u5 zku%YC-Yn@c?qooYmg^-$9kYcy1Kl1(nJ^OECTk*zq3(08DTW_vDriz;(422i+4k%s z@AFcwWkyj-m)eS}{G8CR8<3KU0GCS9cL{ZmF-g0W%JX0g(f$CI83&wQK$sp_X?NQ_ zFxq=uG_Qk?SLM&LQr0kA=EmZBrb`QC?mc&QAXImaOIn%hj+gWel1kO*#F0vmb6)Ri zq7B0~^e);SiFqJ#1dS2k5rLA#gb-6PmMVel>0vSl^}u^Al-+07-3Gv?R1K(V0!tuO zE|l3WQKMtDq<4#)Qq^Z_>FM*x6rK7&YG`8p@Rm&+Uf2JVFy>iokFY&Q@pGB}Ubz*HJA z64SdXfQw@QL0f;Cy6#Frk~LGhigZ?MK~3%^q+G>P1}!OrP^G};+`w@6t*BzyJ`37G z0T2#vzuq<$Ld31(e+C_Pz{*&zPU6_zZxEcI>_0Jh?#W<$IagS4o{`d_#+zEUy^pR(50op$emg zt1QPFTuezGXiYFno#Zr52z3rM`A-_($#c)b4g4O?zE)C%?A->(T(P)xVl=Vw#UNKu zea$lMSrjErGBIK_zpk!Hs(d_;Kf8Ape|GOIq7ue^Jz`7lu&pr$@8( zv1gV59m~a0+Zzv;hHCA;XLRzR-I9qq(4~)m#`@HuwH_^dFc+{UrD&3vxyu6Cq(1eX zHlUbFrp9u8&Rh~r{S5ABTFs5s@H!>e)htcx%KC8Ban*Io{oR2Q>X|;&j-|CA%r37x zFH@{YmAXnmoAjbN)(cGycxOJZ>VANhxz9ptnO_aK=l`8!wh-+Tpz?D-oeQ^j7gD9retgxFGbqf_$lHdrh@9w z01?5_o4<|W{xhXmFRkoc@N)(XIOK~Htka&@02a&ai$KbZfwTtr^dn4?kSvP2_=#E6 zt!CLoehojqE-n55yvbmU2yz#yijfXOG_-4pBvxjfV>L6YYI+K>Kr;{lt!ta5tQ0BM z1cY&H7cZHT8eKL?qk?vg3@;a{U;v6pw2yfik$6@N(4=0WtP_nfRGE}?jmL{RQ)L~c z>;;~=_AVq05Ds`SY~jM8=PJnOl7QgAso;!Y{k}>aP?H!tGL^(BTwJ(1^WnM0Sj%3e zr1ZJ#o$fs?dlFGCz?iXIJoqA+u_GDqHfE`XB#Ndnq+GpLBm-f|n}wVlD!mS;6ok|~ zGb3zC;3sQkq#C0q$&EPOXXf9cH3hTo0n#SHZbh)x^+dhA@X4uU1L;Gj4n3-a2#Aq! z_ud9n8T1>JDMQyO32%?S&;Y>EwF)!*aYVw&& zDczWfQfm}S-YD10d^!+?JBbl-*<`h#3+BHDtu^so2fVBWS=Pk%`p-NMuF$@qiE=vK z0!^Kyr(a1lYpuOZs82UCuNU&y6jrEcVZPMy<_dJ{N`g92gZ4QJXRx?6Y#^FFN%O#r z&iJ?ZFDG6tJqW6;XUkNMq%&a792kRL0gygbXx%t#$KiC`O`h8Ue0xS~tBccilzLxa zs`}1wVo+69OQq{47J#+*Q-LWNh4E}uRc;;=QRr%g=n^|@Bn1U@u#J5H<&L`&BM01j z+h`ZTr0W?k{=z+?#n*gk6fq~zNCr&O*9O2OutXq;4Vy)zGF;SyEpg1hm;GV-$K3BH z>)wd_NB<$@NCb_Cuyyy9l=32iVf!qW_nuGZDx~w53c?ya9lD~kCc?GSLNrnmlxQmz zaq-gz+*6h585q;}MpXtt#DGzc6(B?$L!lYdjj?E!T5y(`Sm2m}8fpw3Du9t^xl|t$ z6v-7tJ6|hpyw}!)s_Gg9)fdf}N5(jSt#O$mBA{YcPY#qSsWGa6YBZmNC?&QyPH8ZZn!*&!uBY_S-o)_5fSbntK2K z0`If zehwHI%RhhXQ)#?C2B>PdG6U!13gR)9ktxS~qdkS=cfrBA}nL?m}9H8Wk1H-1!NL#Zp^ z&}JNWZ>wQ>xWaKF>**LNye4(XO!Ov97@q)O1w2px&RU?w&O=ws&M^;~qPP2O<+aEs zBs^pnNLwde^_|rc>6<&N#o#yrC)M9H8=!WDf)+ivR@Rb}9a&G$12AOox z(UuHUq2AfiNsWrX$vzk_743c$+mbA|5vazTLKBO(i)xY_rGN8({ns9tF+fEHA|u9Z z!dqA_5;4m3F`tGM^&0MPT`7<2A%z@|>0GPe^wqzPt@|%0S%Rc<&br9V#yU((AqVqo zseTb`vwNSL<7AYTu51tp(xUfWJXF^vXhHj zNqZP|dQy?(xkI(DlhfsLf?#$_RtLCfaapeH7Xx34wESL+B&jn`RwQYT zIgqG>#4RV#!&si%&&wv(GaHXo+a)LodStQS$TnukDjRUGu zBsS0q+1n)pk1AR%2>-OlxZv`z>hLBu1JZrrfV5YC4w?0)nuUuvW;37 zu^fS0^B(7_;GyFXei zFn;@WAf#B~C;3{(FFuRaC|LaXZ9G*IlSafdrywt$`t;>QyUitIM11xX!n;?%x9@!> zGNWPQup`u8`fr8sC9o`u}XPSPtBCfjL4gwR5DQk zVwCEJigIMA5pdO|7L;O#=Za2hfEQ{a7JCK?&wIKQ8BmHmtO-Q(z>9$$9)R%xOY^wz zpmvO$KC;(74^dl0uLBc?f$`&CT*fd2eEF4ArK>hykxwi623zp%w`xF|lZ6{Rgl2;u2BX z`x?1nR{-a|0L_oN@hV^n1X2L18vUEt9}x=8X+~oKUlg%n#fa4CU@73sn0;cz0WOK% zQlv;Smd6aliLxs1&3;djWKgP#50CwSphw%gc5~-h406PQ)r{k}zk|htXELJ#MREuz zI8P`_1R+JR#5-~Kx0i}KKdv5}wn90^S{PT;TW#fVmRM&=(MpJ#``ZJWTwPC?H6J9u$ONpBpFt7^SB?>6VUt3y`2xV|2&t;^=)IPCc42;S5BilHr-fRS8w3@F=o491- zk8N{7jyV%*qpdKs0-^CaGEhfRWOAxhQs*9biBXcf*40Dg+4a?BB+&qK_#@t6{1E@*AjS_A`^4T zKU{$r_9;ShKnkV|7ng2iU=kBICbn}@BOm#^RyNcFFhrfC#ep>w@POO`toYg&&ZPOP zq`2(0iu)_W=wtCDvT`21=M= zV$d#(kN)TLI0mi3J*WdsXlkD8K|=pJ>Z!H^a8w)zY>p06!>g#b?w=&a(*hTZ2z>Tx4h7iET7p6pNl=sHT<3;X4 zMG!WuxL>3(8iqVRd`kz3XA7cGtkY<5#&NG#W`2tMeJWIYBeR1COET>>5GE!-E6bEba*C3Vp?2U7P~T%Ih>5TY?_?k&`~fhWav@m#Tbnd|&&Cd~yPD6!VgFQ&|W`L&7- zX$Duc&cz9E(ZsaMz(qCrt&6Tm8+BdcwH>==jy2(dT5n=&D4%(?n2$^XT+{(BD6$aJ zngYm9CQ^#lBKz#(ikqUkrmIx|-Z4+ad$@E)y3#%7*f0fDG4REI{>E@O&x;0ZKs#TQ zc}6Zdv*u>uWh#s~l6o#o`9oSIEUGEdsv0`yYZ>}r+@Obvi=N1#IxtFV-e(` zY8N8K-TNE3^wEhb!;D<^5neLH{P-2H6oI=h5SBL-hc5#9d1AXnL44sf;>%}&C|LaH z9Sm=NcmTfaQD#1|2NPDm{VMn${TMWkPscTWOk`gg0v11h2mI0X&rV*XGaK~2<2G%$ z5}rSIG(RS}Lj=f-CVKysUQMMSnkmf7=Ga_cW?na0URr)7!LV3*v!BZf!x0bk%%B$2rA$q zn?H&IgFrD9ri+&JH7Bib{xB72e)No&YQQN4l=C1;8aL8B=Km9ylw$_E#!xZPM)LE_ zBc@1~qEAIymB)&^VoK86Mw&sc^Hc6Mc5_pnLuoIoacaqY`?bw7oV@{33^n68nGI8aUJZ1$ zc`QqgqBqa2Y?|^J{m?w!_VD81gusV{^Bj{{I#z?HP=~>AHwQuFJSq@x9~*EjPhK*`sxeN!<(O}v}jVy zeMaEZFjuk7x#4T0A99tkemta+T!K(7tgB>%I<|!ws+P^Sv1F`+qs1$+I{I6IMmhl& z)&edQrb}yJyBDz1q!i8gy?C#dc}daUKnr)EOY=BOJN+T@%*JuIWVUDj?e5wWYnDM|(cL*Q2`Y zBc1eXQrW3T!z#gztA~quB?M06zv32(ND8*Z4iQK;*G>Or!_xdclcq!u%HAkhuA$r8 z(3qGWx{+8U92NkE>~W#VU>BUa!^|__7PZMndjTsC!HQ8h$*7;lsiukf=M+=*iL_LT zoS}}(%9hD|nj$kQKn>JA4>dh0R=}l?sV0A?5mL=@$hpAgDkE*?5o$d_ z%DFZVvplg8(Jm&qF42tYT3GGM+_)jl>kvCRjJv0)jj{77f!3U0;>I9*xA8?p4>jcy z6i2piBaAya<{33@$gWM}=i-0vK$Q+)X}n*eR6xan8CuM1rLcF%0ZpEyseTQ}l48ls z7UWoC4h*FTV$ORH$!6Z14TB}|om3EX1s+#5@>|@01`LRkmAR<%>;qoXt0a56q~BFX z6V}H3pE%E3me7^wwHSeM6%ogLZZa4%EE4cy^B#)tix&SO3W*_M%qZlPp|U2IW(cEd zfou)uwn0-Kqo$Ei0Kor0dw<$2NtT`mV$b^?_lUUrl6h~gm3!@b?_hVM0T3VnatM$d zQj&2vl8u>6nlJjGU!tEN*=RIoqGm{HNJ1n?G(a?ZK?B`gRb6XVRaWkM=H0glKj+nl zv%7oTCHJh#D9gHWBjQGQxS#EP&a-5IQuF;7$z$GtKaKaUHO#u4NDx7wXSXN6fZI4o z7`rMcH@;#iM(NFs0fVod#Nf>nC_cQ1^6a%e0p4G_8-K~Zc-Z-UiqS;_=gY zCYz-tH3rSaM5k2vd*3^mozv|X95lQrzQP-sex9JAw~5*FUVrbA$BJZ#u-2|0+R(UmQ=X{+VWo5 zr5?HXVh7k*=8J)b^|bKGIQF$R)y3!mXhQ==16o5m8iWp5N;kGUgIyK$MoznthOb3~ z-TD}L|Koj@s~uU4sK@96Z8A4WI~pWUjY3PDZSeAlOclw18_8r%fkERWN!kH1KK;lu zbO;P)M!^LD1L4AgSz@JOWDGQK;OgQ30du$iK1SA0TGL~uB;jg1(2;TpwFg2drVa`F zzc)^%Ca$S)HhzS8f#c;?Au>8L9XSDb(ljMQ8Ew-(uO*DJK9-!EcZ~Ha66brC1GUi{ zxb7_$B~UIG-?NVz8wA!RCu*HJESqZC+?xU*N6 zGDkV`Gomw1~hntk}VO4A`D(X34Qt?0HCOw=jJ;CK)zn5dWAF; zfZ4HVZ~%+cL78|bi-}GPg1Wy;>eNb716a}`KRChU^=0all14i=AhM98D6{dp=_xlKW-?W$5k{*e~xbwHv0vcv*+rvg5WZ;b6GO}S~~z)&m<0(HeL z=qLwb;F6BQ^`z8D78&R!xVLz6q@YR)q@)FWH$j1lqtll`FQfwQ#$M ze#hI(8+2}RofXsd&z9YM;q9+IcKsH+AGo%?K9r0(X}1pTSTd^?ezNcs{_%gSJ7#>QYl`4DvF(ZHnxOAkmP8g!k<-#so=2 z-S($B26;~kjs7QWU|ZRzNk#T#++!H~~y3NgDI9$ms?|GA4qW zESYrEAsbgH0R)hz4kfO^O-XZ&=@S3Ofde`w9T}g7q@@AKq{h5Po8V27NssC>FGyyZ z>vvSi#Vd=^)*FbdIk$a{WxbH|h$5G$L4hWfuyNAOtb{~NKs2(?03yHnP&eAmBhW)) zkuZp3tg}xU@+P;$3|0bVqNfonLQ$|aSXOraVa{bk#2LC4qQmzN1UnfrC8=~0CE=dk z;?EN|(7*d%5N8X}C$)yDZOW3tS5sc|>^5w11$|;3W?}^0pMC<`*!pr9uzuBV+CZkq z(Et7`(U@HXd~4ZVHsG%8saG2NKL_Tv)$b;>wN*0uBu6Dek&9$a-+X$ zZm5|Ri0(y{EXaxKAW+l%GkqP^m?#-YQfIt)L)}^eQH*=e-;ceYL;7B6at5008l|ix$p@g%Cc~f4RB3^-3KH!3Po@WLQcsRaKpnG zwWPJ=vEXl&`s*NN#8S(yOni(oe=JKwvR*Bgxgx{>7d8b>l+Wk}lL9k?NCh)pA`4o& zcLou#H2K#sY7G;suR%*H->^lzXB&8sB?V#95zCHG3}0sw6O^(^H7TIu+XWJ7tF5mM zn38Kt0>x|rK*gT$1QxOY9eYn0=kw%PSvJaCoC&A|&n$8Ay-KBQ9%)?vY)(tqEmjhR z#Qe7wnay#;q=czcQ%lvPNaDsg4(%cObvTxU_mY9+PW`C?uJ_V0rWuKy#6**SeVS_I z*&1GElzGP_Nl2;uC|iXj{z}Xaw4h*aOp0AXnUmmnlWY$n_&DOggrYG1?*^bwO?4x< z=#LvoRCw+OdlVOu|%Q3SeWuP4gMnn8*Nn1Xw-Vev(YF&0OzIkDtUF0lk|7 zwe<{hYAw)b#6W7oIe*#q|+=UbIzR&a%G#n>^7~sx5Evj`oz~DR&MDeUe^&dsrcd-$q9wL zO>xndQq%^#3_OT&FyQlO;)%p~W)?Gko73U9u2ASu#XfB?5xeCgCa zyl`?Bol@DIBD%+wO0BMI-HmTVFQ&WRku6Y{D}~exmu%!&E>e@PB%XKhooqN%C3dITC9!a<=Yj>e zdtZ^@HtGs76Z)T360l{-xW|m)P-xpoWk3c4Xo=g`41iR^;!#NvYmnp;a|Sx5E&E;< znKdiz##jVrOi5B_0oEjsK`ui1yOIS;j4+58EuMw4oN%& z#~krVJ_aPVjl%i+1SBBHWj({n%>lBz-3!Xh=8*wmA;HfXSOp0tCsO1@VicJ#O?=k- z@pwi{dhPu00@>Z%N)d>Am}p4c18#&B*d-T1Nd)5&4Z-bqQc&(Q6&GMuC@_K}H~)7~ z{qYd-9D$dbIcb&_(_%=9Xd)_(wINAC%}&-6(u=e+f7LEQNE>hC0RkLzz>+4icI((G z8gVx(rFc=oLNUgs>4y@DzjTcZVZc^-mgpqd5rbkaek2Dm#<5+le7j$}Pm{FIW! zDhJ6`;Qf98!!{MkwgbwOtq=iS%GgU3V$hq{pCT~m{!Un9W#U5^+QL@n z1~$8w9q8y-X2ej+_B*9YObkw;W2Vu;1V;NOhRz{eGjg_)TF(6EJi{vka@uxY?z2E8 zOaIw(!roJ}{@e?d8k1s!XmWv3aQ()`2-n3xUHULy1wZtN+B|GGaMMK8eY@vGZU`rcFB8gu^ z{C?IXPK0&TiGxv7!%%)IC_C3OqZ~>OBchaQ?=U} zIdy;~Tci&0M%dvbHLBa8o)U?dOZZNiY=pKe-D~BR0}&EzC6$&?T_={BDeo0vXp;ri zJX(mF?PafERsAT^_{u!7Hl`B=W8v(nSfGaUT{8leU3RZ~23qQ8JB{T`ftEC~)2D^` z@6`glNUJgPaPJS1`Z>$5Ng5pOC}C@E>Z8(( z`xeg3lDXMFOl27_zOeG(j`uGiO>XSx;Azx|OHZT0hqb*OBt`_vB#Nor$4YY;CgGG@ zaM=P#{%;5hEaW7BgweGZ!CTWXmB46$t_-vmXe|zOu#XuBK={Xuv9I?9u|^-)_Wvsk zXvrEDa|MkpDAo>elni+C;4?cv9L35pUKmUTN;6uE;6-i@YLEdg;l4;rl@XJe%i3#8 zVr)?=7B~?h7}IRO0W@`KO~EIGa?cLb{KZ5BW)KZbB?j}^LYKYg1^}uou{9 zGqz_6-at~nnK+lB2BhQ?qWC)}3>lw@;}dRz97$;q3`X=F%y0b!Vl<`+SlM?PYjX#2 zVCzTrL=3#*@2-`(lmu)Y2V^P&C%Xh>Q*fqjrjc}B1Jw+mO$NY-ab7IOeVy%aa_~>aADEfx-@mAxDY>k=yB~02W4uQ$B}f z%p{6Fa`Bp>med6R8k-}RadY3l4`$XP0&MyBv~leP7f?!};0~0kVANR@We26|V0Ges z>|6OwbYwCZ4o90{|;)6R2np3a4AoMAZdWjsg8yg6ROH9}o!RV(v$-3T8fe#%{T%#hW&$&KyGZ{2{1Muc7n) z1%%xAFXeZB2DUuA?Gku;kN~6rfUzk}GvmNudo$}|M-Xe9O6;LE@uAz}d1Ne6vozcu zgxSu=g&H6WGP7J~K-j`=$>d1LSuHsbgT`yKg#hBQX zpj*RmH}hPP%y&c*5GUSG$H_D;gECk}?g2vBPEt0kO|+e##`&b}B|EYse37Gzb>AC7 zI~#^l-xAvWL_@p2;5FdG|9xAk5GApyZKl=opvEz|?;#{TJyeq|+LSDW0^Si4g4)Lx zqT-wyoUaC8y+w@ERIoMUWsYxcO#GclAXNpkx#@}wc4;_d>*j)7VVB4eykx`~jo%N$ zC7cUpkT6&TLMF(41eTfM0uoBVuPIG z@8ZA~Q%UqDa?+yxm;PC3K1OX~t9KOuusr#<*etKNgGi2PL(b=AWa|W`*4{#A^Pv5l z;1Lx;I!Tgh0^`MlGhzWF1eUF3_mImQCw3;+E`Z7aU~;S|I5v+;Kx$&QG2nVnO}fEs zi)wPoN_qg8$|SNUpFrc{dL2tf8OE&xe}aB_3uS+QHnxmyp2o!5>%&LQRGLxWaG)eE z8=h$ZCtE=TT2gk4d(VFFDmF&H2y@!}#$C*AZeV0nTbZ2$HAeA1M&;Kq$W3b{o6|o5 ziXK3-z~FFm{7sC&q$V@8$zypMq8R^}3BZ#H_kC=)y}n+WM9wQHP)mF&F=|p_q-%$q zxr*9jITq#sE7-s@%ObO}^um4&v0$YKLqq~GFM!2xQptP@$P=Tye-Aa}VfnT6zb}u! zhdY!11yz55O1n6B7u!xmP^7?IK&b+yDxsA@>C(m0dEoZc53z6kH!!LX2N_eExEMec z`+VRK6V#&xE$))ZI?iV0Q!Z)*c$7h`_oT$VarO!xXtuf-NVkKnA2^1~VCVF(A}zF}o)Mk8>?8W7grZ1> z7j7wIMp_C(8Tw0HSf_hdgd~O-d7{#8#*cIZ#OD}=g=F#quAAdFjC3hu%hXvhL6h%2 z01}}y*W^Q#>?9EJHidt(TeS_)(vZfq#Q^UTxNAi6CO`~HyGg4zK~0yWb>>Uc-=`gf zh^-)n+4jI~A?yIawSjR|Yj0?njc)fD!=z491FKSl>Ts5lxXj4@$$Nmbd`3GE)N*~c z3!@TgeLqQ4h0;VJijo+SdhGk&ftT$(r0#74BTZA0mPRdMJh5I66g@FbWUYwz%Lp&@q*d2RE@56X?9Nqq*y@Pc_ z+Flx0n*s!sj~K47bz{Bn-$tAnr623;b>$SmP|Kcr?8u}~~W2y5I)bxKqDLuS!nz2)0*cdMbbFx66@+6*u=4C(Z&1N}(F(CWa)_27kT>J5in6i{6 zFb7ErIPrLMJ}+$`OX`P|dgu7`K4OpbBG9|Zu^zn?QW05CA}=d5woO?!6}8TtR7*UJ zI}eUUC6p}lETDL6-=AQu`zZ#xk3rRUKet?*yRp7WtWXvm6w-+)lT2X4PNJy6Mnf5c zrSZRk9-P6{=4+^tO@c>IdcHVG)Cw|erhMmwqP#m@3VBIfdJg>BEITjRB1fK%=xCpM z^(5E5)|LyM6=3##w{EI4R|(jfwtg{f>k+De?n07miR~p)&u)9TX#?}zKJ>RvqVtQ- z@ugt9xV6#X<>yend=&SkWq)@2@?*wZ1JLT`0|oo4qx&)V))_mI?-KAU>VS(c2-7fu z;JPoVm40mal2B~x#b53XQ%f$|%M#h893>mLM~N|gq^&)r%J|B;V_}cg#d-f z(mD|1-y?lbt|t%?y0x*()I#z0&_x1lWi@NvFSjLS zB`sd4amCv~n0C)5$rp}0TamkyCG8o1f>u=#>eES0!wFP1YW)1NRX(HS;V)p5weqwaFzr4m2={#7H}aOUjHf z&I2V)4~mi%XYQ#DR6$U(5A!$v7}VVa7r^@1r&ykN2MS%xE&d+Lt$h%!LK_WIE;5Ns z5dj4AKnc6&3|w)Wq!Ix&W7u@eXG*+H>{U@Ehwm?-Jb5Oa!-7YPPrvf=5EJ(~j0Io< zc;Ge)H1%<1=6}H!-+>H_O|o%qS8)L*MxjcuR5-NqZ!ofDfij(fst!0P=@O1^{ZAlO z*niA`>Ohy1ATDsT_kG-%*ue7myP?}?-h`0d$stYoyoD%TGnIi1v`ZM$0dSFejN(?gCnWANmN??E=+7Q2(&~n}Cp7;DtHyHc1NdU~ubzQ854&F2b1>cn*?&qDwn6BZ(T~QCgDF@UBzH)I3j8^u40H-(O0uRBB(I~VW5d7u zr|&=?orOMi5Yj8{K|kp``qaJ_>MZXBFg;5qdUzlOz8rohB9Nj$b><+d*N)|L%Cp^a)_7%-yPl8`V2Be6@{#s+dWJ%Hq%VikgA}y8E zFh7S>CLkh>-Hg=NWk?`R!Y-)+CGh8;gJB|(-_3RlRH`kw(cDF<11gm6j*(p;AbWne zF>Vu7Y4>ZPq%qMjP@n}^AO;p!`Vay3&x|%=q;mja2dN1VDcTYlFh&F$TNMh$=#(nH zkK17*t^+F63MlLZq-@{EYK@^rsjQ#ZX1k$=w@n)`(_CvLv8ECWysXcVGhj@aBuOd- zA&oyq^lfOg^B7fnPsm2?n9}PkwSgo9$FNHqrw1rE+9SS@;eg>>)>K}8ms7~64B4W{ zz?3#)`vl|lo93#ScuUu{Q+1FAle#*kaH&W3>2>o4RJ8ZZcg;7 zxwk&S#IAt1GNMuxDwJSNFat*AVtM2EPr={B8agMwD3bVJI0I2{zhWe&1?kksC1t|| zc~S&u{8vE{xT< zr~)K{Lhgc8iMt2>f4Dtf>%gWB46gg^0D7Qd1_q+FU7Tp0FYO@*-8D-~vTa+SD*E zpjcTjIY|E4wObBrsFdY{8aR@!5sgU{WR3x6gS)(OHLMx6`@ZaG5gy=5ftIk&fRAZU z!7s}odKz~8d1V9q(G`>*Ubg3Gat!*peb6W7A)_6K8b2#IpWSu_!s=1MPXoZ>fm|~- z3Vm`O`uH4Vv}fln^K{9H(iE_J5xG2Le%)tb@Icz6L3MNvgRh^uCw5ga3~))e;-&GL z6j2#gSG6-}8n2Mu^IeFkQ9EWVfEul%HU2l<anMk(nXVmC$)B>KgvV@5CesDq=*cZ_zBr&Jd9@$vyA@#V>_C@wy`+N={ zg=7VG~ui{_>wcZja-u0bA+OYi!rfJG6CAL8_0ny%;ZQb z-h04s zbyjMXpG6s*XDr0nVw1wWxhIr2eU+RQ6WY1+Ffk0UPmTdK+E-yF&|QDcf;=So4mSa$ ztn;XsXZf9T=&s5EflqgB;iN$M3is3jW#!ZU^bkF=MT>E72;o-by z9KaPmPZ`F+a&^A9JGD5U{@fcT%r|&)E!Xo z=b+730o}6;P!Gz1!?_mERyFo<3&5!eU>YYKa_LV0{@r5hCBXS8p$THf)UG6+Ju{S!Kqo5(8}}L&KSU9Q*ZVQmN-J}--lwZ* zAPd5Lc-f}XfG~K)%Pa6Kx#iid{iYbSu!i#eOHXF2&+0>gbi2?;W>KA-hfMS=4V4py zmwrm(iT!3&0c;$w|N4^zGES1W+pj?YZ`sInKkWDJ0OcBn))K9!n6^LG`i3fPQ|5dn zZz3?`BdDG~1eEHY#@iy76Qz@Rl4j&5^l%@UUrU~RB*|u03cN(gQe1ou0bE2H#ay#+ zYBsSp#z;L5n34#^=&eG{$Y{jfYF|3E0xlV#6N?N=*)>Q&o*LlN2BfrsEyH9)ttmXi zY)AHh^iiYo-wuqCtS6R=aPsJM_8g_an_##>=skAkVc(P5+R0E1f`(xeyB=RDQHKz6 zIh9YS@MT#j$|#9g&R&ZKsM7Sr83xGgVIv{*pJaF58O=5ZV4wQXc#ei9itGfc-d^0q z>RKNM_m5$ut8z)ueXLKL29tFSRrG#=i$5npFxd=po)q+=7%`o(7bwOH6Enz|gz@4M ze2j6v7Oof-1rlR_#*(RNsw6o`DEDE6$HdSfl_*C2rn9buxa1t1iyOo4ZzvY)K|)~s zPe~e$*rLn$bA}-3CN!h^`=2Wq<0*g1t%sT!54cV54|hkk%k(3`p?P z=L|MG78C<&bF|b<;vJY5eaQ%BPyv;O@nDPl>D#{dcFA^5Y)q3ohsv^4m_b@O`ICzu zR{-_i1-4!URWlaYQ8volHa7*!VRAqV3)uKV--JkW01l7>pwQ|yLutIRqfil)CD{}V z>J}iyV8x(9f!#k+3hasmQWU&u*nP+ESm6{}in@7l!v-}2@QudrF#tXF4qffsOT>QHA}!VLYRHO61eHb8Ej(`Qas$A6tgWcNtnYku0cHm zV4mIVGSd;=R-jG`MkX)=s2uo+;?@Q0O6ej|xEdfjmXj1{>7wylwMTAkn>T`hU0&3I7 z#;+d)1`}w$7XzbLtyEChnre3!{YLHm)o~B=nwZHE3*H%n`^j{b=`qOuiF=lK7REXD zOXksnd^ZJd(db{|V=Yqvr4@9EP+w-Mn*uq>N!igRbytSDIjbcDJt!LJrZOO|B?M*n z)AXTGXyrSWG1@TE8K(zb16-OwOHKAd!@qoHwmJlCX-zG<7jUCi{7D^*sk1|}S~<~j zWNYgLP`dxU`)z=i7BFQOVAMUGCwC2(SGTaWSz-Ua(ZqB(M~5kq+!1-t4o?ZMA<`+E zD~aSLqE==}BT;H7&>}5>O&yq^9C$&DU>4Lt3)~af;@@F?V}PaAKIUgfV99qfdWCLcOTl9;0*^L&++rCTrm7+LEw+`5O=jmcV?h%U0Vxwk6oG)cpMcaM$kuTS@OdwuAYWn2N^vpp z!575?bPkyCZNjfhTIYpyL!?lUj&bkp!3_o}Wx=pgfeIDb8jkJ44mk|3XTm79uuck< z1A@pI=dx!@dDC20HPc)KMy1puCQUH(b(}7;phQT;a%Y?=^-r=45mE#$7)&GRRA-=Z z9UJ8pXxZf4j+C+Iid~YNLIfn0uwz!)u?RwrmrRo~@$+Ha+T`s^Ayzc`lxb&r!N0A}>xI0p0Fe#mIoF(Q+5 zUg@W^85s*+EW8429CA!sx8x!Ha6Yf?X3F-W#dLthmv>$qni5!eb^8V8>hZib5@!fs zYydP6Ok4nZOBTS%RQ>#zfEjI|pFf1H@ey=>@i}O-|JV$@iUzZ#4!B4SU;)B}mM-E& zfI(%qloWFYw&Y$e+ZTcN4(1Y8*9W+Aa~;PIk7J}))M(IX04|g{!%{x^r#ri;H%uDu zoO!t9;0}`K>lJ+4wWb!VrOt9`IPlj1mmR?tY8J-Zj*leGqnG?MVxo>@7z^dpm)h}eHWnJm>6kb&ZZdYrrmzSZ^0&phUYuN-W#OFjz?hTk7QZ2Nv@vLBbPd z58~uFk{EwV2+i=tnXva&kibZRi&Pdd;DP}yP(hBxATrRb05T|uV3=T(eT|htm@FwM zWs9&cv=j&Siz;GjjM2`JH!_|9QDtus_atEGZo>NKLdWf(r{malzQP^xNp_IV_I<+=3a(SinUDl7OJEUDr6U zR9PcRWhFyg0Ah2dBWTD9#0*x2ea=aGE>A0*J*cpuv}KJ{5{mk!yv(P6QH<{VvBCBWDkK=oMkyyhLCnH{j*qIpPaEMZkfzYq&ms80(!0yBHM; zlAz!*V?5)91JIcIjR7@}H3vG{R5Al8$g%8lkG>#}BiE1pSYVtSQWuzA_-#nB2`&wE z?=J36{n#;GC<9$s6(~qyq<CcPy0qqSmr?fs^au;Dxw3}xa<5zi3J1iD zT@mya0N%2-&qMdCF#>aN8e6~hD#~Ae4s~vyl? zKmPb4=B9i2Cx7oW_D%N^I&AVDwV0GTc!MFp!?2<;t)0e3OPo12g+et`iO>R+q`TKd zZD2>ubT^GdrhLZ~bw*4L+}QP)x1A478=BC0^z9Ovj>lkPL7!X~kGV+glp#0LrIydhckY{=NNR~k+w~>C z_|3o@zqd@tc7SqLNglH;$@X=KUJX0#Ni8eXIL1b^@w>7NZ1pv+-d@B0>5%}sw2c*Y z7EgN`l(d|y2waLJ*Ps?X?b%8(K3-zs<@^_5D9CT3V@v{6iV6M@mI{(@u+c*_8}KHv ze#f1Sal7M=t)i?%ffd7uc0Lsnyb(lfF(YEEH;SnLuW z!RFM**qr?srq~R}P-?+%oYUxSR*-_CEQb|D%9tLMc)A3?6jtD(z}0ESl__A22f<9( zc+=aqKIRRG{dpvYaWUkE*s?QxM6@y16U3Mxb&3p_7_AOwu#_MrNXfsX8A95Q7h?TV zED~sd;u@&f1Z}YgIFy(xBS|B2C&aQ^ z2#JYq0?csodUAdwih{(=gM9uNg&hdvF*^335jWOS9!#;aHb7~H_CQo>!s|dui2Yd& zlD~IpMp_xDf}zSTs3LT#aU9t?fubPv$F4%U>lUyu1Pln>&BNfqsAHcQ=sMVGq$TAJ zx#vyNAJP;vFC7YFfg!MV=>!4Kh9Y3JiW?J(Pp+c;^@X@@zPoDYvMYCN0eNr+=$5EX%t6L`kWT4! zs!!~9!a#$sEuizOFF=CgA;m1b1KzdP|OT3pwVj@fpzZ7R6 zDY2N3udTgThPt%-;?x0*lx;+mvtsH}BqGY>1~EN}BKxGq07=2u;D=cQUi^32*wk3x z8enp~3pHeCksamR%Q5`7Fh(#wTH>3p9;kU3?0Vg~yLPpg{CddHNA~hof!J~nW5GRl zA-4V@hQ*mtIto6sErbipEl|Q1NK&p?_W{ddJxE9=GAPGBAmg^Al9!G+pe3bOdThYUi+oCw1v^ZQ0TY22PJCm;&-}i<7~3CJ!7;Yk zMM3*w)u%T3{?r>Q!hKyy@NEgwBICZZcIi#Vxc2V-HX<-56xpS|?H1J}rkB5iQTZP3 z&iogwcQ0aUy~5jG_6%1Vvih`33GYg#B z{;km6Jc6R)99-0bzSdbEjM6@neGf|KhLGmv%yvE4!j`J9oEH}9*dLX#(nS#i6_WkP z$`pYhtwLd$KYjuv?N|OWsgkrn5kF;)y7yR+e^t#dhpgv#aox^mb)A`OlGKGXuVgvWr){5A(&?ESK!0K(K6E@??9 zwPd61swEosTw6^%L`qa&G}Rd{bxBdf#|8O&=3q>t#BV*u=6E!GcO?gYwh_S5aE43M z=cS1}C`H=?A=HjB`1dLl*r0E)KpT5F5rSZD0qrmIS;@q52Sb9N3%pl`#J&;|g-qgQW+XBQ1UdMafC6rgwwM&#e#1gQ0Vq-4J2u2cTSkO6 zV&-HMpzJU@J$qkQg6X?Izzh)zY~tqlCG6YyF__m}grcL86QrG^})NfFsxNr;5 z2DG+i@0$<<76BG|LfWwiq*I{(-IpNay{8s%A?LNe{5-Jo97O{2Gd9b^xf$Ejw)PRW z_Q%cW-YvoOC(a{AJ)j*)cMS($I|&$r^87W34Rqe2Q79DG?}GpOEVjP?a_$GU8_>n1 z2}89By$x*fug%kokO44ucTj?nT^r!C>j7vtbuYDn6=+a{+W?o=Dw>+dkVYaufO7r5 zYWybfQ2*XL11_{Dw4;3&P-}yi&&=Vq7w4fp(;eY>+-oPto=9)$Pw#|%o-)rMM(*SgWyvW57#m!sEyl*71VkAmiB$c$(Su%-K z#>b7eNc9@#x*--xYMzE|(wyAGC1u|<;DsT+w|-~ywdeQawHNkNIJOHsbHf!^g->;2SHKu(__P{vDM$>% zfMx-)acM*rWU&$hf_4cbcCILrG#?L$L@>si&_bdau1RDH9?d6^b7i0al#4S66?TjU zvNTnnnnXn4#KXt}9vppak{D>)b|c^tjCr;7ArX^HCX7kv8i@=_W|tI9ATog+kQ$EX z{uS}_z05=)AVZTUCr099K50pkxZqe5u#Jay5*LCu(Uq_pb#8{S++}>{3(G)Zg%BxiSuUzJU?#FB z<^DPO6S%NwiAy!|Kt^(sL4^XeGh`M8A}dl7HW5rq#(&Q=q|`{aHi%PALL68cX<_8s z4swZ6lplIPE%$oyDMnok&_|WX_$-`Y$3IF_R5O1(pJp^1=e2DoB$UBR!CV|SS;mhl z;)Ya~8per)(x*zLtY87EN?L|nv?~k6qA(>Deu?f zKqwe{A11){7BsQ_&1gFxYBG+^Vr7ojtHwUYr0jVy6rQsHvwXR{UFxkt8}Qv#=*f|1 zg`Mx`qa_AkKaK8>KHR-$np-rLpIrw&y$UnZ#o!yKVGhn@(er!X1+j6+#rqdgoWB9; zS7`8E+W-}MQo%xl!J8)`Q=`D(Df4YHHgRZUKd^q7phx1I@$81UMg-FE&!meypc5tW zoNw+YTsvT|&BPai$qRUJbZ{dWeB(5r*fL&ZcZ?UlxrC8_{nr@0cHBlt?6uwrF~}#LsP}5k2q;lUk9N_JpQd56I%Dw*eKlKXlr5?y4$jfeZGKqKe>hPfBguK92j>+uIyeuw2J{=S{{_vmr7q`8|#`EEI= zVb%2TCQY{s4VNmE!s0=4ER!WjC_Fu%ZGwo=0@i@hD(rT%l4$D55@ZatdA92MZi$G|A>l6PG7ikH> zm=Bih=~jrBf9ol-C!ayt6-oDIDmr+!1xGn`?`e@g&&c|gMWQH{%hM1vrFs| z=eZI zrM^wZ_FGXB<|S`{OT-{e&@iFU)NCbtL>5E=!S)FQ3%vToFcwF}iy&{1CMwU|vB}|I zPQ-8gLRyKCG0(bLq`QCXH?_b2=jpNYIAGG7h zHtUHZi-NA1-8R7$w16=AYkFOUmrhKFWQtvF0uKpA*|s#MAwWk9!zF?WyK+p)2SwV( z^JEVN(r$qC2T}SrK#6TKkcsZ$Km>aLYnltfUExwKAk%gL%di9Y(VN?Tu?Hq~rW$x5 z+4oP=bNqD);7a-$*rL%gS`v0k;ns zcxf@OO}pgKG0Oef3nyl9`q&f-#X%x+Kbu@_O`0T0jjY2glEtdiPqNa7(Psi%pF>=2XqNciVM zp=MGLMiNO#dD|Ws)-gMdTq^nXnCQ5uyxbGHZJRZPwDS+ZlSBb1itc#Z3D6in= z{J)0QI*|s&cIQ)t$TLjDT{p*cfs+(@4;holiXsSO0tjQ1YuL#{*x5u_FBcJK$PBjc z2SEjcwXVYX`4Y1JkI~;aiQeV~yompg8}|~{0|-Ligw_Ku5p3}c7_bGeT+Xq34Zz)x zAzLRv)szEU5ZZTG)3GF`?#R-7cASo=W~`jtPtA30q`WhNPW@cSn+B%IMizAFVt@&= zjkxY{QNUef3SDJg9ua^sB4Q*R~LpXnzyTJxEWFUwBL+8HOWt8fWa7W_hmwV##*A0 ze%3YYW(}j;>Eo3bE@O6f1zK~cSB&9+Qz{mWj`RTlr;gv;mKMZr18H@w2dx=bug~Dl z-AQcqOEAmMAdF)=FP{chPFd#5#D)9ZsWb*MJ%;M|9Lo34V^0vglS+5q`2zU$1q@z0 z2L0SV$cT$WuYH}Ojnz^IQu0DYGEKd-6e(u6Sj&(iZ^v`j0=VQJE;-=RC;@9pMU*jP zsHMQKxxQgItK~rfFndN>8s@sKVb$$59Np(+?|tnk-hO#5FznjK1z#AqfhOCrUGm2zzn8_? zryz+$KqWN+N4`@lwKY}n$EpL=h;iIL7S|hT`f5!m?tG^#m|%7F&j0S%D_;=u?e2D5_V0);BU%$Q#LI=bu6S*B)4<4HVWyl;&0hNMnftJq0a zJWG{=F)xMlk^nfF$*75u%mff=i-CEs5Jky6Wr36aU<;KV1V)MnQ#_F2fs#TMU{ZvHLg1{8NYocL=HD9AF)`%U1e~8G@V@_mV~fBGHw~2TI&eAnqGE4oO6*pqz=Z`i{BB+t2fPQ9NRr%z0JwMn#(N|I9%vC~-0i9#vT{ITwyZ6e z>SP>-*f)xeWu=J+*wAFc=rie0ZP9pW2{$@d(t7CGf4qdjel! z1m$}dP`-N}X0!`)U>eo)hpexWVk;puMz#T2qy=oLE&5wPndWPD0ld%-6-C>krxkEX z%FzV`fO$vb7z`~W)05YDI68gje-mUwl9-80Cd^ z5SntuVT-tWYSrE+S4qCVi|aw%GXinPJt@5XxiTjDeMK3B35AzQrKw&nW0F%ZxnE0W zz^Pk687+y&N@R%mop5_P1tJV#fz}l&GeD&W(7J+%fi~KLD2`2H({>b;Qcy_SdkG^Z zVL3WOP6pTj8qq6*n4rM6+d8npGhL|W2L?)vd3A0u8k657n}58V$m1nWQGt!ob66Vx zIR<(Qx~fo_$^lE2lNi}HrW}}Lj7H&PIe}>bn@U4ktOOG-h}Z$RHtjfil~4c~EC5Og zizanDi@)dK#N~aA+cPEhuM=LlY0$0mb{-`;Y2Qcxt_A}}K|e0`F2MM{#UQkhXS*Nrjbl(1hC>2kt+ zVP_W1N;yeiEjiNnQ{TS885`N3bE$dJ1g{;%;KIOE0#n$;!r)6Jh>|OR#oRG_Ig#~w zaWW(4)wJyxEZc#^DP53i<6Yu`lR;qlu3nR~}vN7wLt$DZy|GYfU{~j2MPg@a9&ytIFIWa;eME?@vt*dbtZAFzJF`hzV;kS#kg^M4QJ2a!O;VgIC^LbufKE< zqrC!(8J~V}2hSauM7OkH$@$9*C>7!DR}P{qtO4IgpWVXiFCM_;SO;Hw^$_M}$MD6a z1$4^-FPz+mvC$IeE-i%gk@S1!QlqBqC~aDv^^(-SZcMhUm%=UTZG^1^yOdPQ6WAw^ zodHi7&KPMtPI;nI0}r8uzMmEbHRg+mU{JN2PwgdzXm>1^oR!zu*O!=(BN+fuV{l|_ zmYVsv`+Fml05dUNhgAV83J?{pn2d}5Fc1+kmdo(nv-`nB>lZw`C@EAGfg?mdgJ)!T z@Pf#JERv_%r9LWR66Q)G9rE4~s3#gFNkRU;t|AcQua%FL7DYB0$eC=~&v1sYVl4P# zDrlGJLqt$gqEOx!g27^7i~%Wwe&<)%9KV8@g&$yz4?sf!#`@SWoK(aEQcSszQ3ARI z5XOU<#xYJsl4K;wW76Gs3bFIt9Lf8wAL7y0kr#ml^)pdKm?@<7%m`6K#HIZ zqe%Q%NFw8hi9=eGWfW?#a4^!1!9^5gOCW|K71E5@0VQ72#7s`Q5ewKs!MHKSxHZ$k znLEJzieR+L;{d&Jt7m_Cutm6s4KkgR zW6L;@Q0$k4C`L&F?PWh640E6388rpq~1ujbv7vQpE znJYyBmJ(JTWPubz1DnP~9Do%=+O}I}7^9(#jaMi4Q;R~S?Qt0gtdMJeMzl4x_U#c- z8p=<)_l9WbWAo4_4m{YDoiFQ+o}p6@q~KiL057dW@0)nMamoU$90yiTSi|fLWO+=- zr8Q$_dKL5gmvC@?F>GcM0qYwb+_*J`e!s-cThlN#hWvvDI+zV!JaYv{4=te53}YVu zc;;)PGpDZO__3S##XD!PzR`tJ!!H;KphpQezag0V6d1d9Z-5J!FnIeU_|I0Xne~Gh z4~PIL(AEIO=hso>jFuWTzE-Ua16X!`ba%iDcGz)hFCH*78amlzL(@Dr0bkPBv`BPv zGul+1w0Gpi7(uUF;J^C8>A(;WkzE?6@5X+%?FH02pH!8>^C$M<#gqGkLFA*G!?y8y z5y3zIqc`xquOGwO#sJ5UOkuk2x=#dSjHUKx*P0p&=FyQ7vr{7|3&!t%{|o@&#_d&9 z0}~_%S{s{ik{p*}hL%W&uCxj5MkTSXC!U+e?ZtKcfB*BxICXRy-+bc;I;GkMyr9hU zC1r*H2$Ca7oOHd6h!n84R^ea$>4&&>YYl(=yD#E}<1=;#(=E=mmMji9d^Wbx;j~~g zb%{~fS=675++6tv;+x`H(5=9 z0VA=P$(bBZ?opKB!WIgaagavI*4P30AT=aE?EV%b!@%?Od;rTpG{3a<)~2yKf?UQH z!mvf2HbGKQ4Puk&=fR4Tl$o~ri9)o~!w|E^l%fAD1MJqFB;GEwfq6Bd9DKJ?ROxm0=UX~Fh zTFf??DfVGP-7~6wZK%EiN&9+@y~V^f`kNDZBCOdcGsB1u3>&HW5!mBnCqq#niT)&t zRgg0=DG=C>lUzhl22s-W#T?`EenQ8k(|A9ZL#u>iiwU!U8LQ=KEEI2`Z@Mr88+&XL zb7OcQ0TF!m+hBpck)%XfIEGOoW0pi76(h+* zJFI~(sq~1L&>@Z4%{#a|egGA@xg#V*M9;0Xuda@Kf_`x~mqoU1&Jdxubr>TX$K!aG zN(hl*UO{HW4s0PuhBMmw{jhRioQiFp726jnNq{ziCI+#MjaLavZOmN7v5kKfJ$;y< z7$|8IRCojB0$i35RaoX3O3TJ70aHaF(*!n(hOiFFMPl52rCgjk14aQ_LzG27#b}5y zwlJ`=rj&t0UY-|0E#G!M^Tni~<&(yO5rLT;L;q{1p4!OXM+&wWLHYhg&{qHHHnM#( zPN-I1V_#y8&j4C7;)(3%@H|46To6VKfOli_dacaOJ2y=5<-T4Mrw{%`kwIVUYj>qpjD|Wk^_YwaRb^&Eixl=9Ygt9hP7KGEsXR|_( zh;VRj0_QF*;=la$7br`GTX)x?oO~vYgw_s3Iyg6u+Y6KUPd_<_nTZ~{odU0%*^jbR zxOry{Kl$ZFjE{D3XJG^1c;hf2g8%V|i%==KzT>)R)> zy57gJLz6k1g@8hFt$(G@?=J3#h+2#9w&M%0M#HIN{c z3LynnGCvDMAjL@Lh0=V?0~RJJsNHo}B~+&iD#{RtOH7cEV&d2nnZa)JwB4_?sM*~l z$9IA$t>jPy)n4nyFdcka67WQu5E*OJjAGGNRWWM-!l*eoa*q-`Fa zC1!XJiWqh4hE~^m~KDnA&&)i@kTCP}&!13vhTQQtDM>{c02xDQA4^y?kujv_-9fz<`}+23Q>H zHBY4rU{&H9V*xF4=aisGIiO1g227-tTKN}qwIc`^oI<9-Ipot=@4jkm8zP>~L6hZH>V3?>N0Sa7n8mmoWGe`AOp~6G#H@#+t1Pe-Ya&{lt;*-7eJT5$}vEX&|^2o)tYf&ZV@j% ze;Lfu09@K`n_DFY1NA_eE*|)K`;BuLAKiK)m@PY=yGr5A$?E_CSFY~g-si>G1gh1e z!1P%w2bU*|yjIjbTpFd#-fQXM&&%$?mmL9@jAYWzaEa`e1Q?+jm6@96xhbHt9m{_^ zS<-{g8X1Dl*N(ZFSkz>>kk=>g0{q|ZrWE6sA6x|y;mwy0CULp6%lD&QeO9`786WN7 z?|tud>+90Tf9E?V!~NG@n8#}`%xAA%S=++VLzDRK*N>x9=I7#H{LvfX{jg zfIt4-mmC@^_}lldVrFV2e8$h-xs2<#SF^uum&@cFk-F4~*rB(Qzm5qwa$q8W9OfZT zX3gVnOELm>6+brQo9`8+_k&3r;L>LJEvW=ZkomQUpcOKZST}(8MHRh~{um$2xq)svcsVp!?zOWH8%(IiI@)IJrohn3eO~PI6j?usnWj(q z(Fxe%lTD0v1lF{OPdjt$} z-YFK8vupx?-g2XM543pDDKKZ4Fj5@`ZD_2GeFVi7v{n#R#*`)x?2vMxNP$8XP^t_> z7$XMSrBRVEm`pJAWteS&bgD@(;Cx=9%*Yp^%EnV0X4`2oZ827yB%06BVAWr^AtgLjXD8Yq5+jM7pK3RheBSs&Y zK&ulMcMjj?ZKgcP0WKoOc|VJl(xnnei3wYq5Rgs*6*RyT|9mDp3cw6o6W`>q$cTB2 z5+ow<+6IbGu43@UagctNTJ-Gph;NT84a``U%jO(Cc7{u=mkgL?R~{+Ef`x?%EU%2V zMlav{kRYfkg%3VDhBsgP0=-TJBTv4hPK0p!_zfsBxN!LZn75Z2ZO#*_D}v54o;W|N z2)eX@EJN8S^=~120AFPIdu<26P-C|(d8Sq6LpAS~rulBG2`#mMCe@@wGz1jbO#!rH zbTkb~Eon2l-3#cmm%3~huhrV%t(Ola1zY^1JBu4I#$eyfC=_oWVKnTs?q{dS7rsih zzlUPRNUw16BEIMI!b~`EbO!HybPeY&-bGm|9Gn}+YtPT`_&%xBNLuEf6HnI}Y}p*{FngP5#YsyBZnvZktn+@rzx#|dzSE)wq*@9|>X zm-cLfXquZdh7iuFW4Cw^#z~E|W5B@eQ1}!TzKO*-4xOwy()$l^SJLYcRb z1m;WHCm1GqJ_jftWwinn7jDALPr@9WdB)_}79gN!o-Pmirj7Ly>J*Q**(+e=CNO?U zuzG?(gQx4X*}3cCtkszXn_C_HA7P!>Ei?(#tZ0BRdb z?Y@~&?3)>VAf4#Y+&B)+J)b>xXJH-x!@qeKYwLadvp;+lFP_@JO)?N#Wk#)iB}oGE z9w@uW^x4(o3@r<2*#k%;ZDt%p#tzxVXUC_8C8{;k*5blGmrR-zbV)s18c90&ePa^o zO!B)CCvOlqX+!#){R|L8b-UnB*BU?;MaFW0lNh0v+JOXsk%u~oCEh~GctH%ev+pD> zhK4l4;nyvWL>6XCNrS$4qI3We$zr^{Nw04+-dL2KadsTvDKj*s7$AemmA5gm{B~#? z1Ym9SQ>;$Dhr$?q>(Ui;H#hB$yOTnQ)(~AezXyvRS?LV|Fh;6yg_etn78RZw8C(Gw zdu>HVFf)1v#ne#@q;RKOXcIG!;fNaPqH%}YD5z=AF&fL2m#d(jue zvjRx8ou7<`Vg+$BC}DxI`m-RNiK$j5FsHPeqpZ2EfE2@$DA*%%Vev)=L1JWxz#fwXv6Wt%sY#iSDxSX(v=fxycBG|EZR6c~2BV0aaM zUWZmd!6x)*Cbn&e*aC-6CM4S5SAa1f)^^9cD55V8ThA5yyO$Rg;UBwLaBr#{O~)N$ zC>W8aDN!+oJ3gN*Oo(8ZpbNrk&)D{E(y`b1#DxB0+!$oSI#HM-I77xsovirDf-ELH zN8kY7L_o#^T#u>>AkbzX#i!TNpBcBsuX)CJX;wmv;=?OYS8hM^b9rz(J5aZmP<(L{ z)vHH=!K2mqhyte00%}9B{5(C}#nb}^MOIe3`0V__hl&9*1D||$7+MpK9=^LP$@OBIIVF1iMO(3+3+HfeTBLx$NNs6cy zya><)Cl-pyLcPu=35*!Z;SpwFFfdqN?qhyNgV2Gr9&?W1?6ngS5wsTk-~Y|8vAW*J zzxboqFgraG=1m$BcU{-v13*zjA;>N4r4gxHkFd5rAyhQukDDFCvPgdOTPF}@2syCh zO=d+NEYR{K-Dajn@JE05MGPu~lh4gGu4xXu|S&_wKvJqFwmCvGbDaF zg+dx8wfXOH2Q~#<>hbgK443fg7D-WEPL#zn1DQ!KYW^)EZDzNqfh{H!U!L8fJ-fw3 zn!0EtfJEqNE4Si0X!U=$Fg9$IJolr zxHJ2ou~A;ArT3&J!YUN;LK4h`MGTmoq$s2o+Suq}V~dZL_iQ}lzyO~P6~F<<*ho!$ z!<_0E1)Q4ivVvj*L+rd|43zWW@v^W+iciWA@;+1!5F+neQ%fI9hr<9=NNnWHf|)~i zQFI0{I`Ljfz1@8A?PO!{@y}x0qRc8(Km-l6{kvtefZO_ZkP#W9p&d|VTF&T(Es-Hko}X-7%y4%Nuc#D@U100%hrA<H|Xn}x_OB|iD=2nK^eq`HMD&vh652%pU%P7~ z;~!E@S{yjAAH9-r_OmPK_XpX6-y8a+i^7Lm9Met@CBQ{Zf|CO+dGV4N-6g;ZCCNqG zCKXW=LeWNWXnq`r=f~ZS6LLb#9@2;m&vWVmqB#|LNOC9i#bPi4aHi8@NAdVyx?{M?mmEs2jyV77Qr#zZNS^Hkto4@IX3 z>UP1ZlkDO$K+64$MS&lPLciZF;BwCst}PO^m~9p1d!)0)C^ISG>y3z8^6j31#miER{!QZYI?p}L0mBkO;noCzu`c8ooWYzHS*ss=hS z^sNI!_HQ*8I6L}(#`um=RZX=(~0h*+77jpH?m-gmfhmV0rXC^ou*# zf9oIEbSKxo*e9NeHQZ$)7-if-mtYlqt`ILYmM7oE?e5ReRpU5hzKiL>tKph=dVP$~ zZeV0;J@h%PBZEZ{H4>CR9w~cYk4sro0#>RU)phas9?ap5~hoS>x zC;%|pJ|@lt)&pH|fQ!i(W3F!s62QO#lOQM$PLKi_FDFt^N?CcByCx6=VHJUP65JkD zn3V#hG2p^Jt{nr33)^0e8%LNKQn57)ci;?_r8T<^UP(zuVh-`(Ys#CMMEj^|c+VSc*(_|CErAU~3<(UE z$dD04!(9u0*>>(<>&Mqe0=^J|*SFC7%Ma0i^%(REhf~z?D}E#Jr90r8i_buphXDAM z?_Y%3Hvuz0^;p0@VW6`D9Q?6h?Fg{=@}ptB7{e%(#`C9rN)T=9pTcagxHN|MK0E=f z)k6hb^3N6Ax;>56)e*e%;w4OsZ$7bdquqj6_Y6RYpt!c^=Iw{W{3$M7S;Wg{=J3i( z$1xaGcH&JuIF^=Hapn3Q3 z2RGVfWU@WrlCe!9%cTBUr~@xGnPZdD(k3ygMLlQ6xp@?HFc<|AHcMSvl(Jh)@F59o zmxR$`$qhP5H}Vn23fy&oOQ#bfqQed?J9D|3aqhhWF89%&yyu13dI}_DeMVqe0?bZs zVSL(;lLdHr47&t0<=U5W3@$~0FbW7N(V2aG0fr_MfO9qgbCEELa;aDVeY{C7Te%1+ z3&`k7LO_R4vGHCp!Sll>ld$!L5ivl)E^gjm2RoTt`G6#*s2sd6qBln(4+}f(zQ|(; zmsl-M;PS{niasL}Osz3SMRa5m zlbf%A6hW1OeMfGiH?d{=xX$H%l=`zE#({hDRBeo7zF6iCj5~h`_~P4-c0h{#HweIr z2V1nRYJiJpyLdK?$pEiZW|SN0Cc{I*&R}L3lSsPANr~84Zy#tdGYVDOcyafh3YPtJ zYXle>5K3Ku-JGvrJy3)zH~(A5XVDslm6PpN5Unkn$|q)KOcz8}iZj*?08GkwDeQf) z0+*#_oVkDgc`HvU0i|Hd0@o)QMhS>CpiN?e?CpBBJvYJ)`4|zy@~(6^f1)kGCzQ&L zQ~+Rnzw&G{o18>oa1intid!O9E+QtBj%Nuy%)P67%{_1Zp z;>6KuymV>~W1~GNrG|no)FNZqJtErx(C z)N-&?144Fd5Zg4zrJ&m`SOqKpSO_57scFV$Bmb@#&QLMw!si}qIwHcQYfJc#fB6~y z;0Mp+=)uWWW>kNm@gM%nr+E3y9G*Y1Z`=30cy$Rs`r8Zmz3-lSsK7_Bqwr7v;FZUK z*wPR>c$9Fp$2ISOzepX>$PkkTz!BLi?cfGn5iT_Z#_qV*qUI%9aHf);1_LHF==AAJ z$rsB3A89aJa$qR`-1PV(^z$IcJJRjIEJ_@)fp}Heb zT_-0B1p+4py6wzTODuZSfJ+#sn7~FL46qXd*n-%A|q#dn|wRV?C76{IOzbR9v>lZI4b&32hE zwfZ(j)=!}r%!FhvfuJf@ur~537AJld`lb<|o#P6B4`9NCRiXQ1OE~SZv8O|9*5BqSTCL-m4dL@#tRb^6G#ybt^OfKCO0v0 z{0=~Z-dG=`1UALmF^4U z1rW=FGG0>TnL|NtAZ!5*Bk{wHRV3rC_QGq%=rbgKBbY9fa!|fyWrT?fRDTiEcI4OHtVSg$G#5 z?7kgq?d#Ti3M*rbt-{I!p(#jy(v@CdjX8fB_RJu5OeIN}Dohrz5(}F6F`8MyXzds) z_O-(CZ@rudtN_O%5@XyoFqZj91~xeU5g6_g0R||4eF3yFz~HSDUp=`I5ugn^fA(vr z+e^=UTpsF8L)}<}J~0P37=Ee0tucgy^9wlS3~FTuu%oIJ&Rv|x($W|jYjtGnWA!+87jSCv-cP?%mUEh+I|@ z1g0q+%43w9k{twzK^?deaz%$dmp)lYvsmd7k!2((vZmh710xs@ z`|FZhrANbaFJlUTivxrlHWHXQio-;0G++uO1(NfGasNnLABiwiiv>=|d%UD$sEF+QTps;nEUDAZ>jzHe6iRR@MC0$RpK zKG$QDRav3v3{Vun%#k}#g$}Rt;I`-*M>Umnc{W4JcH!hT#>bm;l%-{!A0CkLZ9uzY z)-Y0`G7(hK-rFUxhja$gc*9)}-h}ZhNQ|Uqt&|(N8nIq2-Y{2SAY>B6J|A}rL>@1} z0#|p&7#m&2q2(@mn}d+nqf`OWl{K4orqpCCBT9)_X_1per9SZ#`V>cxE4Hayfla2A zW41);k!QU~Szx_e;P!M0%}xdh12W!cCrSl#2~nQz6y!tN%C7*}^dYu@Rd~#uBX%-9 z2nEK9-B9tVbOJ*TXmQVb=8KTTb+wRX4Y7s31rIrD+6}D5r&qu?7t#OjOOVm-m)~U9 z8gfBhxQWg$&)H<1XMoGYxru?997F$mFG0pf?74oNfD6U7z{3PwUVr5R=Jzk5s??5b z5fMUJYK)C;?G8|Q=$DK!F|m$gM{Ykc*ch`xzhB^kkB?z}y|<(6N*I_tC+I8zQtbLe zKuc>-mu_J%X}0$Sy4<+6hF8u2tLp=FItpc}La}7bE+U-o0c;ssFAxp=>pcFs39RHl z6Uu7FR3UJtosWnG*U=c{GM)B_=_Uw6E#Zgt<7|Iz!ekJ^{+UtC&5R}{el%28l$|Xa z4!8^jTbQuAzJ(9Y-olyVv)DH?x@#by39dZ3{LJrv}#vgF-{s_;Dv&anN zpu6v)VMvSf?y&3y?ff;2v8f?22tHCN7}1)RlY$-spfZ4h1A3fDfY<>u0u%jgqmK;7 zV*~S{Z}>QDF;>25 zJY&Qa-_d#9O0$RwoNTc8bYpSx*<##zFqEVa*=wYYhSmdAu0XGJAC<0xTqP9kMu(5J z-zQ->aDhT;C@E15GzR@NhB@{MO?dF)%ei?SHti)jh6D-mryTLQRJ zXTuBvQ%UQpVYnOoa}p!uxcNiDq}ZQx!xr!?TsvoDP^cD=iwR^jDj-ORNGz)d&{!`N zF6}FD`mRFJufV2&sVayrLmF6!VAnbnVvs21%+_|4o@>h@3rrV3j;4T%DsW@Ez($WD zAXF?M8GsCB;B^3190-^uc{NgLTTK(JBjx`I00ta1>hnWxdBXEu$xu824amyarP>B zW#i$?i@yH)VO+YljDz#zn4KEIpfcD$ZKHIx*294UYAdm6dtin3#(`-AS~5_jwlELJ zN2xbT@;5DDOU`cDiP_R3b*dTF?uOwK9Mb;kWh80sfc&@F7;$`}ptv$=m4l9y~<;;>mqDeq;*0ZqY6^+T;8n z3AIEr&y`q!NLJX^d{89!W090mB2BO*llDkcQWW23m?um7XXcCH)~A> z6c4sM3WiG^IHlTnZit{Ljs;qPqO?1{6*R!MkRVpjl`S?j6NrsV*AW;NXcn*%XiZSw zu-JhRB7pLe5J^G)S{hao1r6~)O*GimY=IWI&r$|3nvyon`Kfbbp%}rIba9=(gKNES zhjTGieTLqH;&@^!G8$_xB}G{&|-{BPVy}~Wf=JM92E*wb|8=n zz)UpVB_b50aG-k(qh$|F1M4^9(w7Xm+@hA$GE+&|&iPu+a5r1 zpd&dTQaiI~+vx+?!tBNb7Uy9kV5J`ZVn+aV={EF%X_&*akGDX6@Z0176Vw+sP`>*G zsPDm+FA2NFkE_IhVpJ#QA)_5gp`efM0}8eMg2K(I>gpZP`WB!C#km`x&8-GF7v~@Y z@7pxAfHQ*X^<$8Uktd@)5zwD>L{|MUE(4*{8Q{pFJLq->FoyT^w@*r`MF0ks!s=S@ zF?URJyUojr<`wUOO1fCw170!)3n$NhgI@a4NuSMCDx@OcBpty_0MAl%t7xOqdP zDC~|?zh7ZcRZXy^4mvzwu!U-Ljy7pbo1aT89#WP{3*eHP?q=Wz4Q+%N1~j#@N}A`Q z0l1)@<$~6PCFDLXE!SW>z=de{HQR##TdK-fqsylpuNm!?_;3Hwn-6#6MKMNu!(~o` z%9XT+zmxW_#^s2K&__PcRDE-{q|P73C~Yls?_dUUk=%tC=XJ*dEJ={VEJBKUd` za|Bt^XrL?uIF}P)Hvrp1?o`YKBc5Doi#JtpV6aq`fMHO;0WHMPZdcYg;KL{z+w55z z?3fblO>Q0N;=vX#<%+TpX>7EHG0?F`!sk|E84+wCN}!B2&lN3@QpGl4BI6`_$e2vp zmfr603%2laQlA^$-vl#ZR{t9F{h!!L8hsz{hpL#x-QG7~v@4>>fhp;{#BhZg0$3CY zPZ2;$nLSkBe9Yzmw_DDAT$}rM=+h!ZyF?pjItw4?>?A6c9@w9z0z{y=017xZircLx z#`yA^;H^o^&IyLZQ5xkp2gJ#slwx!?j^g;`{|l}i`hQ|eEx?G2s3sE`QrQk);w9tL zbXYmy#W6D+`zC@h1xoJWK<7DhsOwB`J-fq%qCWL*O1-KKBmu+!^GpWIz~)y0n-b>a@XL4xtJtnJP3@$uvlyo zlrcK;kh0(kIo1ZdBHtJTQWOCou|~2Phcflha&7U- zbb;BC68l%2XG;ROK#YrMHqOX0UI)Xr4+W;52SkZ+cbsu!f@*6L0i=qIH{+wrlfDyx z%J{o)YZ>6;Qif6~7?A*4$H-^n$3M?jWEhE&&>mC~*KUoI6Dd;8G}naJdAShzO4k{9 zGuz}VE3AwFF&T;GSP!+*BG6Wa?oU2O|D~hQFCWEYjrqObs?o2rm)6nw+t0uYYstL( zB>-F8b1PtjCWwmhHAxL4AH5G^k+4N1#v6 zTR^nfp>Y~{A^;Z>pg#drBM;L^S1`YC2{Th`y9Qi{1S@MjeDKM0*xc$ovb3Tnz6-P9 z+Km}}_QgRMXSToXnJ4SrGIdrkcFhs6ce_+(0!0cZda zd`vPxrSZEoWJ=llBKaE=L6$Z^rpdl(0bPcGERE02*e}t~MG`Q{Br=4|!zD4+jh_b_ zSK94Dm7QqdSdK5UFz)c{xI6j=loE`~6)3g^Ttz)APfbV;N^BfAEAsn- z)`P`ZW)4Ka66Xf*>Eb~dPF(Z@P{Z~!?CWCNVpmWiDISwaFR)6K_Xa}*6k^&+(nbTO zNzv0N0j>xHE-e1Q#-><72rLEW7XKa=r+$jf@~VxBRvuK#r9ANdL5LC}l}KQ`--u0B zVklOaENAi3=+|7@o(|fpASX0YLKM@=YDV0iO%)wnleyGgD~@KW9uOoruNh)1pJVH3 z!~u{Am4>8Kf$48rf1tqlaL1M$@93uBo6Epr7dST~SnNn{@*Td51F<}y=1q2W zOh3}1gLJE~NU>v6S&5*5v1YKup!I2tT>mzDV32{g|Ab$g)*j)Uq%3=dtYNe_(G6ZN5HJZU zV_&0K;gQ}1=zMq))#4hew@*SwI!}+siyJT1XV+1FaM3ba0(BR6oedv@GP8_=##_)%S`Py-BZM};-3lq3-c^-p-0`o5F9tPBgVE;Qn zxxUB5BG2-=bPMXv3LdtXOQ`FH72Z3^h=u_zdjnY70D<8?D0K$McHjk54y2^tt5r_a z>f1uQkP>YVw$y=_wqr_*uR2iF0BUk>P2+kElVm+?u;pHEE2~>rS?^ zXcUSab0&X&bF0GD8!H&;l_(Tpc6tQmHpsjG^Yx8B%2J_ID*X7Dm+;BC+xXV&M{xSY zEG}JN!n+?`$9LX3iVIhl@x`SD{J{^-V0vPEs@>>Ffj3`1;1*{0w@st9c8mU@SWNzS z76pxLA)K>3P+Po9k`@zzk<1Up)V)!1pu`wKQ<@ahS)>&lY5zR}Yc(I2Iv69v-Z#cT zr>QCsWRcMRxZ`&~h+&mPawJY3KxJutTgtABEmbi^LnQ{e9Ajbqu6Qa937#(LxUyUC zmPg!A*~Julwg!Q%p{|zLh^n{^_QfVQVdDVuq`o7G2L=;c6IEF7tnE-5pRufnza(*ioXeeM`%Rx>=i2U049~_9w zWmxvNNX(FfIj}@CUgM-r;;zL~NdYhl0E=nPS$>FYWxO@kEtD~w{bTHmZ!yF)mz-&? zH^>$8X+&01WPwZ*&4+7dxSl1$tdb-m3XB#JTS$N{@XM@Vpb_+D&NSDxQu~k*XRZq? z|9TvF2QiAPcfo60*!rzkfl@uWzzY$iP*B$wP`-B_yu1-W_-%G0pH8rafa=sd25+1I z3bxn8JYz;Y&ReA!r;lI9@#k(iU$wmeE(TYxPvg^bN1iCaC6vP~IDhE?E?l0+b4PCB zz}ynX$2Q%Xjqls`iP^5Pmsdw{_4+>CT^PrpDuS=gj)02;O!mDa7`bizTlN|eElQ#M z<>x3ryM_=2`6xk`-2pDCf5`5DmhIAVhBI8+0heJw#&C8^3n;;jZ#moymfEF6dttZK zfs{7TgHq;7otZ(l z5?5y71T9;D=s0y7Lh!{SByCG#saF>wGq%o2`WpQaO2W6QqLCq zGqPE-1z&^7k{jhdDeRW^wYQDf6(crP$A~k?jZ6$HKOq=x+-qFyb7f#sxsQ!Tf;Psn zClWT2Nti#0=ZObJ(m)k^jVT8JO~T5O1w}+YG{WkWu z#$SS0Rv>zS3K|0#n98w=G~?1#iH~O$6qmsxBu!zm3oM56@*Q-b6oU(w5=8PpS7?!$kS6N{SqDYd%gND~F;nc1;HZmB1^}aVY!4<% zjY4ssut~CFpAcA8`KCwoqaiN|VS<4HJLU@59;fXa6wF~f;KvLU7e9ttyahApLv&^3 zMY;;0OY}G~xzCBa&Grd13xxF!v^SgdugmXefiK$re8cAa88`(%ejcJ)ic~PFQ z*EY|_m*!(BrES`oH%BltGM7AT#NGtkc)-uGgP0u%!p!5Xm)7%@(IYAi70<%mi~KxWjc*j)59Mjj8C!AooC{oB7m|2r?j9NQ1{t0!a8 zs2Hd;Xk`QChnJzQ-nJ-KD&75(-K4`9ymlP=#Jn^8e9DcEi2{qp>bvEsGjGKIOaTQGRv> zpyH99*J4jcx$8&U0hQf8K8)Rx!X?zqiH_g~nr6B6_iD0NGIV9=m)s6;X#<67pVl5b zUHeQz9n_)+GR_fE%{|cGmRC3N&PUhr*2{-5Io`$k<^b<~bRDOU&th(N48Q*529#pl zxV?s3cUE!g*bLr&^)Qs%<@)4{+xYP8O$dOmzjhc$4o>3NXK^9vvXUO6*|m(R?> z7{RYTxQ26=7ce_Df(yNm0X953fM$kZVM+veCyUpWnvM-@AfW&dlNWzkeD4;mVC=lm%mHc@zKs&(Gr9 zZy&{Ix5VH6`YLYRUd8&>0AnL1e&g-uaOA*b4Op=r7cHkf17C;;zx&-&_`UC)vPl)% zY%eRy>e0k7Hw8Ru^zR@c@~=<96Ol}glge;%a3YOMu7NJeLb}OW-V79#wy&CaB_zZ-NjQ^|M7n1Tmkf}JU~XEdQ-~}kD;@Ek z9X`#`F%rmo<`6pymTlMU9uoo3-+*kb0Y<}AmgQo!4gib?UM#Q}ld{rX7$U~#7UBD6 z6|PMZE>99}jTQ-LMb>kL7=~5$-O|^1vto7$QC_yiTsW{T{$sL|FZ(y{wan3AHkE<7 z^I4gM+2VmDBtAPpl6;m3mcsYWeY}SC^>hqHW0NYmj=oO^FBjL=O%mfxQG!J<5MdA- zmqbK0zaa*bpPLMXRnB~2`%@AF+%QgXVw6h^t!)va&;gkqKnko!f}B&}sdD=9GLgx$ z_PRg$2>2GRs>o|;mds! z=u-!wpFac)^wa6HlU1Aw>f&v5e)ciEA+MR8M0N52s#6CXqx31cGWQ|731I8fgp(!|g7x(-u3Vo55wNz_#q#PX6iWuK*!SBDGX?0~ z6wG`CsJ;VR_ImmWKxI(=`XY)iZai|p#eyzLa!A~jm7#@xo#isTR-jOT<(3%3O?Mj- zCu#>TJf$`Jf1L?J!;fo6#3%zlQlMw&?@(v3WWY{CQq*!7yFa{8BV?1j_(tt^WZ9at z{qn=B_@DmQUt@W-k3tcC=QmE`kAL?il%>MfK;zQ2CA@NGJ}^M8+*rY(`3V5PXXo#t zC>a0n@4g5C_|w1o96$TjC4Bem$MD0SegSO^{_*d>5{~Q7esT^I;~o6dKa7u6mBxSk ztIu&{eggmO4_^fU{K;RO#p3cNn1RCwCUE$`M0owBYfIQaGm6oX66Y@6MWGmDqt@?RQ;wIR(1F)2pUoynZR z67Hv_vI#rH0vRSt0BW#c5^%)SyjJ2d)>te+E%q6i8D_gI39a&{p=nJ5TWppERM`cq z!b*pV!kXeLYvKtf8w#uz#G))RS&|AK$Wn=<2DU!w?3V3-7rRjKJKnC)FmRG012M`n zvy6>g^%300r4&ixq2gsmMhi4dj6z24RYmYMHU*hZBoYZy57ZR%vTq;`B(teAUbf@e z3GDiT_iqXHZo(?@mztGlnTP`!98eL|3w9t@%CQ{??)+E)#Dd4?!Acc*Y1 zltf(-Afe-mN^ z%L~Ag0gB!xW{=#malN&%!H7xH%%Ztf(@@)F0BvNoxHSvl43DjSEG1|;waxLMLb4j zF(TP9h@hZUOox@r6?T#$=gZ`MTSNrx z{iPgp#W+tEW4te&l^DUv_SEJ+u=Aq%dIUKdQC1=N;f4&TcVpcH6% z4V}OK)Q&li$yB?LWQ{7xuAsotA;V%=01THD)d2}+!qUnXuHRnAvBQ%Xak04DffNlk zN(MksSo}AbEJGwk4X}i^?VEcC&2}Rx8bX?B_`$T(X|UrFhaYvIECMeegNs*|u(mOP zQdSml;p!4LHU}unom+3Gqj2P4WN=K5cK{Ij{R+#gTMfz0Z+z`J{N>Lt;9vg9`}jLw zJBFhNC$YLdz}8lUx!DLzoO*5sgUU3dsek!57cdxT{NP(B-25ytK6O{)y20jVh4HZt zzV+r2Xe0R3zxoUl<6V6F%_HG;2lkI)e6)l0%>mXn26+BNba0=W9mCZdE7;t$wAwSr zXK}!RDrLdwbQBgAH*jcf0t-tU=yi)74R?3Gp0>vS^!yzxulDiQ%LlUbp#)n=ma4g@ z%C_J`3%FvzlqQg3jLFPSQ_lo%Hrsd~lX$3PjFM<#Ym$Pr8BoA(wz-O)<3wM8m@=p?I-bjwU(9^%NiRVIPsD;(-YdqzIrTdaE!A zgkx;406@Xk%+rw76-%CSgCt3)>fXk}%#WZ{ftl6sV5BX2at@LnlZO+}Vy+1Lzq!Y%$t-r!(|3Uy##28oLYnZCCAd9ZTKcn4aMh8ZaX6HfT z7+oxdjYRe{M?skG{~D8W9_!@^-0FT8ntIK7ne+dKlQdYKH&gLTzv2Uk8i3}XakZxgIEicTMs^LG;l5`}XJ zNkJ{j0B(Q$o=N3nJ4FQ1GcI8d8pic6reSn}$^CuI9@=Q{Bf3KOn4JjGU$oj)O$AmM?R&_~?j#5vDz*L6e$lj9vsj(5ZF+c8^)8tJyCCsFhFUH9j7 zVn@_=2W_xjBzu&N5>Nv}^3)qfxh==iCWqSV_~WmKgs<y5)WdT1(pod;PqHXRt199*UC&X{URW9oJayl`?KKEH4mBfS!@ zK0l9%vF;w`(>lu~f(Kdyr;qIeNMZs@SV&W59@%a&MO*Ui`sE1z)U87+{&aIo#k??O|E>h(LjnJmh`CU^m$)z`(h(d=AG(yv&7 zOG}@pvH&@gP-1rR&bHvNbY=#r1Yij}%pP#|Yzg1#xRxqLZn#LKd%H~}dP*0T)^m)4 zM~Tt4KJ?U5@@YYm5J8ML7)?L~6Co;UfGv^$Fb;%plQEN>f7tnH2s22G-BFgX?+rt? zjd~`6Po`lLfkY2nM}MU_URTOsQYv9#?^{?cPGO)X+BE?n^D1} z*vX9mvXR{Gca?%KKCavO!Gt6!q5!OTvtlDU16(AN8P$!9O~Qsj6L?9^L7Nv)76~o! zS{bdwbqW#e+9!G0`OT*lc>pGW9AX@(;^cu|I^+y;4cWHG!OYk(T-ZvMgmeh7vc4^D z9cct3TgRcQ3Fj9q(1{6j>cK|!G%Z55$@t_}T9htipsp=IU0c{0Q1~(#-9D6?!QjNcQ@&zg_I5akjM=FX%ubEqg%h**(chfMZ+!h2bY<}K zcQ0dntOKP8pI^L-AOGSKzWwGA%uJ2o`t4N|iZM0O!?8nCICpUYfBK`(@Y)OWc=w|l zICX5M;h$2~j`LR^Uc*P9-NyI6{v67(!1Y_J=#&c6lRaF$xq?6Wi?jIMzjGR=j?Lh$ zmk;7+zq*V;r6B^m`|)-BowuJuSum=~G=L>$#;v>SxOry{g<`yTazEaD`5=^PZwLSH zfB!x{Id>cX-9LRB&mEeo$!eOQOfV6xO~lANA@YTr|65a&)fmq#@d+>iU`eDyMiO?5 zzsAPxXy(k8^tIlHC5>DTUN8-*(Xb?>Hqa z6&!buljxUV4(SS8K};XYm~))Vhw|&@Wskgjtp7`}i|30}#RRPdWbGe=XG_Xd3DNIH zB8bAiJz5EnmHAi?4HCZ|$>0)?WrNA$*36mjYS#33H5|wrz}p zd2-r+Joq!tNATjt{|N+Zu1h63iH|dnRUE#*XLt}16jWl)%x;I@`9A%Mh|YM_|86Ct*Gj zBT&TXZk&J_^sEFc3!9Og*p%!Uv~NT{yL~lrm#5EQcE>{42zYrN(~~9lgo!S7ibwuB)cs7hPbA8pqgD{5At^$( zF3i9gYR|VGA~B-2U-LAimdI#IQWxqwqxJ9K1{$S1gxN7<-Z9&!CvBIcl&zaVyF1Tm z%8K0kWM2oLhJjJro66=DNi*?h@5eV(8-9$g_%yWc$p<+iwf_ReK&Y!2|- z-#NJ>qLwl^((f#Zzfw~kl*ndUl7dno!mr;gdfSP{atd7+2_|Y!~Bzmk6?? zfQy$R1@lyq>~CYD2oi(d^cZXL(21W5yul~2i)VH;dsPNA#{i~~as{LZR1$;GP(*pN zTMhtx4q>%(2Ev`#&)oUh8o7q$(OXy< zTMM5zvG_HR=|Zbjbk>gs1LYKOiNH&2Pe>lK~&WbG%l>6xA&X!_fdOnt5@LKOo6MDgo-Kp^GQCxXEG!I-8iQ4sE~4`0T9ROG?!9zND9r@AgL#zweU7QxlB^b_RX}Y|Gkza82EFl{2kH0tpM8lc z?`OB&O{f}!SC6B5_1Krk&xIM~ug;-3cMT1eiwLAp=zs5JnE9y({+*Xj1FOdgbRTbP z3}a$^9dEz>g=O3BSpRFRt@rTm2Pd$x*?k7Kz~a+tQ!si1m^|lfP41U`VvYHr&fP%y z?ibd4o1R=2RiXWkr15(Vo)Vr=<^AqDN!(3K+zTWFDpD56_B4|1{9ATHC+mRA&V_ew zjNWjnNebR*oaglTl##uzNE_R%RA6Jy=v{5X=U|9l^nKnPMI zz%@?yB61Ohp%r@{0Efl~NfbqGcPcsZsI5Pb_1&f20~@phptdtRsr|X#w3$8h$p>8Q zGBfTjZeV4#kLk%CuH0D0#Vd>W#_NZ71bkBC+brH0F|jA2E3r%EJ}0TfsOhVcfiWgB zT>{`@BmqsLT*xwDT*2&~(>euVOa{p4RE}hfm1jvFF`a@tQj4h$hPJA(J}XLDU_~*A z-LAY+(Y%&p0g!?!X-sqe7-uG>p?#;XZwx4L_dA|`%E0HeB=|CTwLBR3-i?XAAQjJO zL5S7$hPA|YKUu^vK1IOFdau~~?qnBa<0K(4aLgCwi!S5FMv2$mNdk#H-~y01Lt8fq zi;Jvgv2m`_=DS68@Fg|ZrC`d-H51t&Ga{dCkf(HcFs42hq`-a3wDB7b6V+#!(eFW6 z0jvR0HbqJVP+2ZKNJXCn?@<&|a$Ip7=1phPYMB-8zLOnw4qgNq4aj~__XePPmKifR z01S=-L>S*#NB|tN{Z=t1R!hwB5wKD)MS+_WhcSS%z)F9n;n(7oH9^_rlCY36=xSa; z0Z0x;%{j0Yd~*n>mO5Bp?t&RuxVj%igsJ%@%pAUJ$8#mQ5pDufAOkF-!EJ~f<~Z(n zfI^&vM~saa7H{Ip3<%rnC<5jJMgUb1ggF@LS^!yv>ycg?A!`up*?7c^5zRQUq_8qo zVxuIO7LX#?{w8t9w(Y9mRT5H(9E(t~N~AwFZrr%I?g*+lASN-+_47ysU!v3~_k5Au zOjqiOdqd`ON&JKm*+xK>fhGiNn%lw~x%L(rO`%4(>e3$tKlwTJgVK8}rz4wN!qS-?dI zU;`9uz}OW*_byOuCXAN*8RD2gn*;FGyC~m157PRv`?c%}bV+xHJSf4*$>0Q7$&6nT zosRc-Az)Wv%f0p6`*(A12VP=PRe$@21gT+K+x|W4z>6Zr=0M|@?_b0InNhs?@&PbW zG69=t1ebicQ1sN1B=IzVy!IMT)=hlqhJ!CuTlmK%z;5JX{XvB*H&(E3Y7~6q z(E!+b39>$EB~lO&`k4_AdHEg_px8>W6ho9X_?^N{EcIrwNu3N!cIZgMgUU~~Mk077 zZe}wLnGrJ9lYcDE!%+eyA#xj7ygrHLTT@^Kj81KWm0)yg0~7mJL%I`^pPoe#e4jW4 zE>Zy4g2>{$hTs4eC<*g7yY-Z?0&4{^8YE=~y2LndcWnx9{9PvZmGhrcD8TsIRmSS5 z!p#YVTN9}~3^nElYT%1X7#o}blo4P_SuO#5Z#-r)=1bjNx6XLUz?T$k8D^pj)Qof~ z#<;s{VH|*j@EvVW;RImvo@2}kqKz}rjo;n+wJ5vczy+Adf-4+1M#%nxq8dea{RALD zho-=$#K35~0b!8Mi;?+8tum@$-kheiJ-dB%Z~P@`1V&K)`a(!6+I}HXp!no6)aTbQ zc>5Ie@wuic^F0*)-36dn1*$PCJHEHgR)h78E`I#;m+;DqmvHF70;)>YE}39`ql5Q8 zJpTV@@7`+>oT~2X8@h1^L68K=Avn}4gcT7JltnJaVeQ{9bw17{-;U3Kcz zsdL?#`Q`WhK5RDQ1J@#dDTEdi4fftuoO=t{f4_CKd~9b+V9*D*Qw!1EBey&Da4>>~ zm;q#{8FDRFdvyZ<6_A)xbxd%6pq(=&Fa9&k_2Zs9dZ=$xm+S-x03H0d(){y|Sm2KS z;v6RpGs6M$@`5p6EIAGDV72h=PfmD=B3KOp|J^_OMww*DY-iOwQ0{e-IqN!JoykvD zZu@9?FUh(N_jkP@Q!hI@-e8JSpvd|6$06Xkr!SWY?$({D&*=E!_nyEHzxTw)zMXeI zxP!m?C1TG`A3&OIDzr_)q_RB?QEf?|GKM6E{j2(RV(MObKP@pLdil1x^|+5 zui``#?`(-(bSN!Y(`7N%CZo*tNxz%L7inS~_3t>YOm3bUNAPNmFpg%M4?vDHG`tmd zEiT-~d)#E(FDMr4$@+SBcUc!UYm*)eaiK3O5ciW8Ub0Z32F>>D7DiLO1pvWBID$D^ zvXmgjxdISq%y3>w?~kbIToyHz9>pYtD!-Dj$|I+NR-OHf-b0!WS! z5y3@`xbR#!xTsqBI}AT?>6R5`f!Djr*sGhr##-Nk4x?MJ11jXWD=4lojS=7pED;(4 zNQ?_&i(LPg85U*9A_6nO16VIYPo9Iu3yB346~I(Ps%jc@4i^(#h#5LCI0VqZpn);U zZLE0@(?~eQP`3LU7`Rh3C3C0}7TB~IElwCwA1y;=Qx)MQ!@Er&gBI72md6dN{$(89 zItOCH@tq5}@z&!AgW~GfK0p{FhLvDg#lj@Y!i8tQz(tHwwS0OoUP{d8E0yGQQJxZT zHw0T$XzO$_4o`_$hU5fH_1@VT=o;88hIw%sAk%;i1{{vAxk=l&RH>2%m8eaQkV|o~ z$V^nJLQAcQo{2BzXEv4~zXx01i@Js*s1{+qFn6|`V|=8jG)-mqkqJ84(W1FBniKQM zi!bGzB@W!p^#x1y&{N{;z?^e7hZ^-f!u2N+-+vtM-QGZBYScP+L9jkQ6t`A>-}-hx z-{7as@IkIo>!Ddg?2b=Ial!cOHz3z8LatqWINOVufV(GH|K*F|4{zW98`{SB)lXi+ z$=(X`#O06o_&GJ<9Q;9X^IIQp^FD+9fBlswp6!^I=4&fZ1E8#l;}}e@MI7$5ooo>xY`4)R)s-8VMx1? zfn7anf?atBOWuhup++aJ&{^V2_p>GU$~KW@=VbYK<06=n!-aCqdxf-@bGCY!gCTh- zObUu=u@j>vhX)HZx`r76hy@UW1T~v~dJmG=cqPHHTh!bwp%Em>lo{16<49xgH&Cn- zS`t8)%ebG}FM(_GRr$P1>y7MA5NP{v8I6fc14svRrT~%$XW_!+kSQ(VRRt6T5{J~9 zlq;pp<RWO7hr6E`#j=(I`o!Yq(5Af#1!aU$}<2Z}h9`g+bW zurL(yg@^ie{{QOffc33_-#)RbZ!0et!Mi}RGenEXk{gLyR!bFJ8sSC72`p0LN9lH| z(2{?zz;$(AbFFrpes0&!q5Q&!n@a39;+4U#tE*!dxXtt#QBS>B>Lu$Xs$btZS+^9HYIqtwr_BQgOBfy zujpVJBgUVW@3?ZtBmU6 zAtyjocerDr5V`i8W#Ppy?!6nvH}LdgN){KIraC7&FcS`sH~7E*;&puE=}Y+27amW| zGw%AS%DNLB${VfjM3NV6i0YoW+OGQ+;l;nh%f!y*_4BS%WA%m;RI;o^&VA#u_}U9x zuIf7w~ z{O|wjXSi}{AOFk$@I9=?;mq82vvdAA98WxYfF~Y3xNm`FNoZLXU0T-_JRH|G^)y0@ zYZ&r2d}->S>!PFiy0~Ck2(D+bh&fxl;8NR(q_|eHDAT|%o7=S=aT5f2wFa;E!K+n) zKEeQm$Z;ZT7b@ao>D_d^l`j6%@}QSoDfbpuKJqxU6It$WCnzr#LJ~J(ZZ&c*osbi{ ziA-z(BHRXmoukBwAS78-5kO#-^$HROo2x{kq^6%zkzV;KL7mWT3$CTv$_!@iVnsl5 zx1_X*#fnPI2u^gNc1K(N764|)z0SS_- z+BG`oB z=GT^Ml{tJHnf*}_f=(k;fOmiU6wX~b#%e!eSVin#JnCS&<~YgcD$1;un4V8gQ6kuD z1o5v;Uzco)?h-TN5+x!Ntkb{A@dD0GZb^8#7zg~xI{_~}9x$!AJT}fi;1VIy27(J0 zADRg+&A;{X4Am8FT`nRK0xbee7HV4N3rbD7II^s7wewEk5-FlO$EYzWwsVFU@K#HO za}rwYUt17qOfe!RF3u{LXp)^R$WALL4Nftw%1L zglcDL#g{ZuCL}P9MOu@ER@}yppS%=XYZYGLY}c*u(pMk1qDRw;(^V+f&5#85+*=L! zpa1E%Km<&=hEbPbmg&b&)4-CamoA^bD=ctL0#-8M~AY5rHU=B2$O}HEV#s&C)H^ZnQybHn6`-}4I{#8 z54>K3$5q;iEenIpkFed_G-|oe6}cv%y7*`ZhGkf@-ea@;flvIq<6}(-5;QlRr2?w( zQrs`))0`B00T3J@Hw!bwNoXN!K_X7$4GDv#UY2X1le2+KN|dDqt-@g=&aS3yE1PR{ z$}jXi(bfGxw;5oL>!#H10FU|T0zKiR5=PH0UBbe9-by}sIH0B zRwTtCk{9&a^wcsSBlOO=Rr+E9|X|!i{E#r5ZBiR2gCET{UnA1kn<3?e?5C(kz`iM8KFmCU)?M&X4qRqeB z!g3+bsZ#$fLJQJk5%@S#h3i&FOtdk|2`>%nMT_uKww;pYOlxXhAXbDP?xe~HrTg(UKcDgxCS>^;4N1O6J~6~Q!F>^3T7W1Ab3 z7RHoB=fV;X&qrgW&hJSIv>S%L^5ZCjZy#d#?c1rvNFIU~BWBQzJ6Qenl@x9LSZ`v& z=6g?nA}*KmnOETIFM*@C71v(?WTcPGc=@~z9f0-wifcbl;)xeRv@5S13?O{&UEth1 zS|01>yj`~ry%_GM^Pr+~Sw1l_i|NIL0gWI6fjg5KXOZTx(Oc!=gy|NI} zrn)XqcJknrVa&n{wpizQ(N1_-TGup9KE?5(GtpyFcyV)AFTPaiuI`%l;!CqAcH+zZ zxn8R9lIMq>^Kz!^r9L}F^ze4{CFcu~yO*;_Q5!jeC?aM1cz3-nZj?56(j@lk<#X6u z4+i<|<3@ymdzK6>G9kCQU_P#}yG?GFlfnEnYCu#@UkFhZfx~O?ycHdln^P zMp&=G>%AnljH^;Xi&Fa>Y?qp$Tr>GzXvv=^bvA=f%&D>yRX$tcCFDhS5?%xf3`p@4 z(j=w`r4|qq^FRa<0&)6z5>*Ul%VJ<$1#9{@+D=ohl@3-5U29sYab47N5iPr1^1I5h zguLs*Z$i`}t@MqD>K37(4p2!8_*@H};JRY9&}lKu zc`={k8(wgkE<%s5K~DBkWpSK}qa}$f3QP)20+}M@bSg2UEV}T(z`)=^AsW(Wml?!K zxJ@h{0tuVrNWfD0VntVAHWAK*X5?5!Vu6r}Cmdi=G80)do5%j;;99BNIkgeZEGE{7 zWt?MSt`0o^OSRvy{LD20<@wR=_b=n_bp{WDy(>@Qk(>V!G~F@B(FBPx!FBWNVPXVj zmxs1>$wcnF2r90?H1{&Wn%Oa40*JE9B?FO%;x2r2GhjV1ZtkJPfkdmb#6xbiR7h#t zRs^ehh7=*D#986vL()c$;BLpql`wBOT7v5~F;c}WQk0x3*&&w1Rwe>OQ*;PwZfrJZ z92Y2Vp65`Kj*?S4Z->%&HorkM zsbAz=Eh>_T?Ob=67;U9+-qAw&+Eoy{)`>o9)GpS&7=dng(1e;!^eC`j?czpfh%Z#^ z!pjk*M#yPy2&E?5ec8sJa&!nwmC|0cm~&jb$l%WsI~R<1 z#W)d$!T?_HA*}ZkFn1Vj(jTg`B`|!IZ6mfcZWZ^rybl-4PE`3K&%Kfm!9<9VGM1*u zs+x6LZFe~@EX~zY93@iDCoJrslo^2{)zK2jT8o^W-_ENd+NgA@?HRFM@VXOg;YXl} zvlQnG*TMZXbV+BNQi>2_CHbf$)1$`Kjiy~&4Y;qkC zY;j+J+jjn%*1*Z*kkcf#0MWTp{02mhfLP^})i~>93vW(h7G)kzX2z8N^SptI*hAe1 zIg2NS$)n~pu?Yp+xiK)?qMj`Bkzyi3lww3;yLW2yG#7JLXJ4(2R4xvdu{41iCk&f- zl&@EssYn4<=YFYm%my5_$E?a6d^7Et;z4HxAxlW!#dGEktModVpX#l*1g|jm*Z>*UpQ~oZJV8TXR zRuL#u+MKcvOdU6E431TB5p%Z0Ngxq+nTaxa6GXfa>LAS~+=js5up2{mgD7Ko@ehzk zE+9U84VWGRTSltN{20G4(7hE-fBfA~45;b!3 zR=7Ip{HY{rCr30BX5b=8={BY*;xB*k4u*m8XWxG;@k$!;rCY4^;!7j6C^~d}vxsje z;EJAB)ZUcVtvh(mOa0v*3^$7$(Gssl8{wtlcd2`uP68pS^)g2W$M%x31Mi8@#C4 zf*rMaYjq-vJt;+Kagbc!M6~2|5u2Qgy6a@tiq@UVDyGy4tFM8My>Q|=E*ZG%I556G zx@Wj(O!t{rD}?nq@M;YjM{CuvW+FDoBbU{-gF=xL7U{tRlbxvYP;GjFfPn0RND&f} zw0IJBwc?V&xRnvans%l+*n8d>hO|zh3Ce*rC6t{-wD$S&1-y+h9 zfZ2&r$IR?*G2pIqQuMH1J(Dn(?pM$woS%LV8VO3PGzpEV23ljR@u6JP>lXFJMUmTZ z6wtT^PM?BIDOOTqO2$_y{E-5N6(9tw`A&D9DFJa+tqF)zEp)DjMtR&Os&cw*_RgRj z*9m0rgS5!hh$M2PXBT4II04l?8Zt+Q(>aOAcvqBNE(wC#YU9-MYnr&2i-nP6^CX^k zsez`#=+X3eO^AWH5t`c|0Aa+9;ZN~M_&L_`og|Ls$d`(X7}eMp9P_QrJA9)-=XN0u zP=hFwix>IYZ{h$Q2E2KRaXc8?#|asg>g>ghq5+}N1Iqa3;%at?N_EU2M}(pqv&6Y; zYUC)3F45IXm)hyvXyj|83n(`^C1I^gB|0RzWlW(~ft|_(fB=G08qX*s!6mRg?i^{$ zW2jAK0#OD1QYfurSv0+H_ySfZPc&8Kd0do;D#A?l-)K?2IN4Zk4M)WsV4n>Ri31dL z2X)yUs3)w4;Shmd+Q-R1`F^VOy?s>c>9#GZJ!QQ0k>IV{gM-%?lzxi7{@z??W z$)A5cfhz5B|L6x#K># z+^7gGwPi^A>StH;EFPBIv>r)W@Jh^aqCN0xuYu*}omOxtOoS@3IA=@w%-*NqvJ+Y! z_6<95X;4dxaUn66B_*MtxEKjENs7ISf^+>dX>wPHBG_k$P5djieP|=Nq~@N=aPgnV z;>1`uOL&lO{=QZZlhY2V;l23iN*V^aWm9cyEpiLXpoD=L8rR9q5)(9+Q%0dK-c5Wd zu@#FJ4X|jDoQG~MK&CYm5fl;}7n~M$Q3M<~3Cf{1x9}L!&c3})JcJT0stN{DlqCdE zNY_DN@R+_Q6J-#nxG~^cS=3^!dFwzjPs0GmK2B>Q9B0TokwwiC`yvUzIo^?D8|D(> z1U(K8c3inU)xlEhzN_PaLxQMMalD{bhP&6kT$c^H%7mNye~R<*cepscWKl3{?#b2N z#obZ1p625l)jDMLbV8qT382-v*|;!U z7EHP+X&jjOw*2+90CoL%mc^O2^++|xj}$G>B?-062`C*!&CwFl{N3I!nY)tjpAdm1 zjYT4w1Q*9S%1#z7aW>fX+&J#82Pjxppg5+-CoRCfHfYfdG#{NCCQh}{C<`t@lGq5; z4M(}KS1VF?$L{!|A5ozf_Hpvx|A_%16?FR$!z=I93fz1SV#4(G$Do(a1HsmcqMvA- z=$>l{PO#V~{z7r*Y2fC!DZyqxkBwtjd^g-tJo0N`bu)=A`Y<}*hL9LPfAvbL4KFoq zU)^)rP=Iqr_)m*&F2r0>s?7jqdL^l?0%dn558aM;Qr#bAirYnvY{Jzw7eQ-;sAs(l z1AED#E_Bg~FVv|XO9IIK3oO)rNe?C`e5?;)U%9+Z$)Qw}Ejqu>)@aefv%p07!#lU| zlV7}r?|=JIeCN5Vw(wpSU+yg~=_l|UJn(On_rvv@M|khUyLkTD1U>Y(6{BLk3i#*$ z(;t`TNs2<{cKdqC#tAK|z3XK;QZ$bdVUf|29WT;|FTJ;ptB^gdFglYJ@qfbVQn7YdaS~)22%Tm@48%usMxoVVf4RCWZusj*KuQF)Nr5 zQ(jxoc_H6KRbR^*LxOX-pu&?~)F`JXk5*qt953OK%`Z~RR6duhv|wY^Gd?gmUS!}` zkOPv}+VBF|4FhiN6W%{ZB_?w}LvSO$ctHZ%HtwOihgvW*T)nru|K0UUfG5X^)F?4! z10f<7S4_Q6a;j6C2F*|$eS+PX5^sG5+jT48MJQHx}-WhvyL2Ms~1|&EI?O>^Xb|bi4t-a|6SRZ-Q^! zF_DG7YNnQD(IriAbE8CB9Hj;b6mW}3&fFX5kZZ$Ejv7ghyQt6K*vu*?l$9D2Ox?vu zKVt@tPa>}0I>sZH_p!GMWdLWMgLr$Ui-+xQ6J9`P2@o#(T{H#izbwnh#YN!*CM7)vA9WR!*oIGVrfL08ZW8>%iKW&5NNeRSnsEX zqHzQUYbFYVV+)uC+yM{4TpNkp2jwhC?rwtlWmR92_`(cxSV{roiU2HxNRq~cjJ^1xhJtxub6JmqpAz3JC9VS#qDCiR|pm-$~D6hBcQ9qaWQDFssV6w6hZ=Ya}l~3Atb<%&NFOtU{0CQ_{s`Mpm z1GKo7R+zGu8gNCNs+g@(g_bP9NL28^2pL2k48EK|K#7|%)VNq_x9Qrbd>S%?l50(P z+ip~=!;`Q>Oi;dvyW=0@{PZeFPF;<6eebEZZ9TQcid@vKo=39~Q+Y0&-fKj-xlg#e z0#f<b{~UY#9M0YP zZWUU{p$QCz&G!E0KuP!wHiIMv1x1j0PT)WYp+<~2lu9GSXCKAz>buoqzB|5JL+0Vh z!&x8w5YA1MQrpk@Hvt(HH@`(Vxt5|wQ0IWrkM}nK;NUgI`8R>_$ZnG7*ZIO9IXd*t zO^m;I4SeGekf}Bg?HqcY=%UHK4X(~F<+ONXVuRcH$d2EkH@1s9rb}ajpw2pNlV8Vp z@paN7g!L-miEHP}Z7~sU-#x{<*AMZ`;|EQZv7bB;mH@S%jIc)CB)k_~$S)=wP`Hgs zVK$lX86sKG!NPUV6qH5r&1bLRfBRqmk%?p-c;$>I!gnbFgcubU&ad%yE*eLL36 z{BeC!Y#05=;!HDTvoB**Ow;`Kmv)}FiYx98c!tn+W=rd2LBnb3zW3lv z6=8}aC5tl+EZ4bU9GeA-mf<3BjYrzF7WJ&&I-T~Yz?6#!V{l&O0Vn(@ zHmgT*VR{*>c)bc8DqX~FVGPXF+V-W@${Wdi^x6wNS+3U_OT28ZhQl6XE`JpYC zcXU&4H0=kUov>4%jv)ywmtR)UOKG^20XV$~#1(M+xf=V4`*h}H zRteyZVz>)jcpX^Z0K!SFW`3yfO?eDDJVAKvU4%D20N=dZ3M{mvfNvFDRIMpOYRi|X z?L;A!fD_W>mO!b;n>#?EwoxHRcCq@s8XL+B{9brjj2da0n4Ld2;v45KHS8CEy)v+x zbz>IExrdnIzt1~==%oh2qPvBfpZWW=AgCo@pUg7)UIL3k7j>Gg)z1F8fu13>IB{i3R4KxWcJF=MzsTa;FXF1A zrDMC~m_*YkVH^vU+B(s;3bnDL(rVNRDdje!|Gnk*BUJ*8D}?nP!ng*FEAWu&NQpBr zx3*}g-<9=M(C!^|rn{wIh3<~8jQFBCb`p#mWbav)w4lkZhb%OwO>mk+bDMf~YCih~ zo=bf8B&i54Xo2wL&*$7YTbiF|xUM@lP$iacJ+BcFNCKGmfFZL$5-3*;o(mIUin}HA zCZ;ts?t{k)1Z4tb1AqpAqB%OEi6jJ_1R*F?0%VF-9c{N~?L}0a816oHE5*uj$=|0q zQ5IroNTLgk0X$Hxde&4at~qi>TGJJQN@OexDLHl&QkFTLpO6-_AuwdDE7-~i@RymS8FA@G0@1`He!!U`kKBhZNR({s3R@|`AD zv^1%AbCz@!UyTL>$zsHd_7QNrBNLPIKB7=p|g1>fWXO>Ng>oKZTR_Bdaa1<-z>r) zJATst%o(;z)^HrBkI>GqYuj2H_-}&g`iU{ar1DsA6UV01R?Hi!Op zT`x|2A#?>!i63+Q<}qG={R4dWo7ZshV2x>#ruCzL4hqB+g|#7 zK4lNlRV|Ss3F-YAN?eYbNMHI~aRrAuhng2r`}5>hha~m)FTc;#i7d4hCoSUCE%Mqp z#98M&%I+B*z_JIFR-)u?q0)RKrEWNh5(9KIrt{7!LZ=E#&!0<;0%ZnqghqyNgbJrd zB6GFS7!r(kO8k)|@@R9;^G{HDE;w6#OlZhaqfo^c3IT_E7jS3)ibb5VyEXAM)Gh;? z`yj{1h%8oSF=7RT6~vMvYJm}>AWl@8WYSAK;r97o;+T(dJidj)z1K>kj!x<}Sr|-7 zY$0NVFeI^sCkPKv9U(kmP=$nufkw#sZ*jQ)G6r7ZLVOMbtue|ajB>SBh=;D4ngQ?% zC&N<^T*d|Y9aN=lK%9wwRG2p#x&YyIGtoUB2^&^$JO#psivmg`C|KeWS_$Xpv?Fllj4lkEg0;f%oGbSoCy2@H@jNF!9aa98?~B0F7D zg}eRzQWu?W*MoM+{m;Z;a66}>{4BZuva`uuFAFzyQkzZ&({K}~=ib8V=t*QJce;IZ zv`|FkRQ)WX2$Gz{P(M#t(ANyeOj&d}oiP6ASJL@lx48L=4vviQhxZX)x`6n-XMoe` z9s?U6?R058%9AXcaK)(j?l-SCk*qpNYip(Je30OEvKR#yFRbuqKX|e%(s^MwrZ9Pk z@cNtA@!B75;=lZ}XAzdJyT!rM&Png#V8MKGrMl2I)Lf>nqH->*_}kQOA?K~(%|xmb zTcGo%qGfQd6Htl^MoM&|MugJeOi?4}RMA@XTzD^@4U?lv;wq?T>=uB+SOgau2Jn!9 zxxs3nYosVQYm_%=&u^if!)14T1OX;5I&7yswH8%|3u`dJ(0yjL-4yVZ&2Zw1cgEc7 z?O5X%>Wl|G2kdeMYGxNi+TPZCR7Lx94nrehq6-NyiUhY8G8m|VM*)lG@wLogTMg@ zH22Hqa-o=-i@*dbyZ$D?6lPC~5UHdExw;k|4g?AjED>>%6jKq!2bcaG?hdbFk_k~J zOmPE|2{BHH8!62@eony_DM~JvAvNl7gzyLr>HIvH(k7p?SZ~Si4!cKTdNr1~B3Y z0Knnub!@^-fD{qZlt(ggdfq8HP^y5TPJGD(K6{VXsdj1)BQBeC)YLc!K+LZ=MEG;!qJOKmv*Y^8kus&1#ufrR_PXMvpLZKfUn;H z9dEFsQ0|16)z4przVsGOfAl=$u}f(3X`C(bxggbWhR-;xCveE`8_ zckGTcCWD+s1o!za<3gcu{HxIv5?6JDwS6J@e? zy81d~v1JHj5?g{e=WY@nA`w^vL??(cNCZM^%$xvG0c*r2+``QZKgAxd;@tEM20dsu zl})%qHV_eTmmaSUQdQ_wU+YFl^y8Xu59%foHW#^wZIaaUkZ(Mqrco<5cZPRvf{u=NyUV*HMK_O5 zvHthJ0=5y!K5FDc6*>+$`N!XfUfAF9UB0ZlS%HD$4Z=G&K*t+|m)`WjgSG)aiM1SvTrh~t{0l^gw6$*Eke&0k!5y&x7^k})oQeL+KqVP^W)^jHTRle zL3}BHQoSJF-j^+4NWa*~V#D^=a?5uM{FVNDZQ?&gJ?R`Q%TAW$M%Fn)!CVL z$Cv*$F*%^;+2?91;(@j8h$2qOwI;EODlvau;MOLxOs#7T4P@B45-rzps%$6!fIF+b z@>yJMju<1s-lc+ zOdvpt63GAr4`huHVu-n@Ls&@C)rt9`EL_X-?W2sYs+WO}^7fI$R-fU@8~S~O}Y z9HR8N#U@#${v59E+>0-HBMM87(E&skK>*GlUBU7C4V(@i0DOoT^X6t!ON0~84=P|z zZj}`Ak^(U%;WB^An{SE9Vr4oi#nqC2SHT=od`j!4OMahZQ8aJErC7Q^H5jzr=8YnV zaf8itVxn1cdkkT~5LUndb1Dr*e92Ch3_zwFIckIzi;`L66ERii3}vSbx!<8ij44}h z!~jQZ_yg?iKL+MYz%+mY*UxW6{rsu|I<)TBW>c<4a@n1hhTptVMdIDDJIX-wNza=U zo4@}J=%syNvlCptR0k7qGGXS3vw_AHp1Nw!xTfmY{h7`^v zV1kTyLimNbWP-dCUdqaUA!>wXLXCSwjUI5qzBn(YBC<5X2YK=3Y_X+@4lQUS_v2>S z{@$m1%TB!@(KMb?^SZ)wHVSe;w<}lb77oo_()m^Oeq@#93zyg}XL4A|<=RA$8j+=E zw%nJC#Z}JE7%o!oh%E43>V#?`PPFi~*zL)JumaTT=k#?aqGV=Eajswn-7T$0QtzAp z9SQ?@wTG}uVhhaO!b7TpPWk=8#FpBj>LW#^dRDv1z)o=49iPSg(?iT>(Zx_)d8MMZ z=ZS4O&5|F??gcTw$C2GD5|h}HoGvE3G!7SmOeV_Y1zUE$NNqc-F+z9#kv0S5A@}*D zbxH&7hD*Qzgq4)Xw2}$ukFHnIC7)--&k@i?tz4@P*Qn9)u#cnhym3;w?DV@5#Poa` zFEwPA3kP@ZOOcerbAOAY@D?_5*fk;ReU3BQo@$)4WGkSwiMGybm1*nrBH;Yp?}Fu^ z#K4F%gtl@{l)5qk$$)eKkb0SSa^*41yR%f<@wSQq5Lj$0B0DlizDUhHG)lc$`n{Hx!U7C*ru*Dy+a0^(lQ~3pm6Bh!$x&d0-@b*_ z&t3;&+{J}Hf6)bHa4t2PDSJ}lK*i3Q1(dw|r6@a6+4Um1($W4+c2k`#&C_m(U;Jw$ zyyTfr&vV2>Pw*AJE z2-Aos>NGH#MfSJ;PWO`Cdm4Q96_$k-_d)}67Yi^GS$d#t&vp?%dDdPqSrAXkj5xWq zpbL>A%taKS2jkAahcyp@D2X8=?2a$Q{kzu!^uU z38E8UvKW)yFIkuoQOM*Xfp(n~Ptj7dUA|s|2ltEdGTx-|bd#%&3E1$6!*h>=2w2Mr zMvY(9ex#3X@p2V=VosmUlf7D$e{AE^b8Wx-Ij?;Je0rDN&}>wKV|VP12RWF4 zO+@(p`xt-z8YoJG0N5R$qv(>)`06OBzDn3vFqcevX1Y*aq#Dz{8doIQh?#9*?pEnU zHj$_l+XnjDJ0@zaw1*+y$9rf=^dM?tMNLK@9{I8)xSZi`*~WHRxGxVH8G67u{_<1d zwGHQZX#|-3`u19w7e_k5h0eI|XTout%jbYxZLKWsXF8j#Z)*_3Qgt(0K}NPzJNw%@ z>u1|Umn=@ECLwjA3L1gMizy9QSG2Yesh_|lUJLr`cGc5TuG5P?1R6*1xJFpzR-#k` zohqP*(mn#SU{^pc`B`E4>@4wHb{i(U6cb&NC?leXlQu4w z!g&!?n6}mkQnQ;rJ7+c+GAkgcwZ@qt!B$rrd6jCIhk(0#7p;<+>Sx=zFdE08<5Q(` zPj>Nj94+m|mM-S071BS($1tr<5cWQRvVe6!u!v7Ut`#1Tin8te9JGoi!eAas{0Qnf zJhiu|;>Fp)9m>OocgsG2-0Gvp9e9O@qy9ja^aOas{ayN%{5k=XL*_ z)>?FFHx>GLk#^bMBA}pgz7*CF10i0+{?Rpz<1O4h_!~@|qiKm_BZ!DzWB~xS_Zgdj z&jeCIlnAB-$PGjwM2M2Pd7St{l-h~1&|+-28qum=7bp^IM@Gaj830-Au_U1*zeYt2 zp(=nB7fSPbQ4v;%T*FZjWa{nA{`EiOuozcjV(97+ad;p5xC)J2#WUwb?P31S9IdpU z?bb)T-5xw+~U< zhIS{DFOKNaV^LJ?%}-Vptp)s7mfoaA6lr4}b)v*pmzj4*)IrzM*M3%@{v%M`S-!%8z3=7)LQmmZ-y52E zQLgf?@Lk7*q2@d}|MNs!pt!pIUM~nJGlvVR&@uaZAzIWsS6TsP?q1o(WSKP$!Ph&t z4Mxi%jK5yJebKX{Ml%5>J6g_w>z0_oV%;>l#w5Ee1ccQdcwB?V0USo~5P)Gwut7GV z#c^AzyQPKZQjQZnC@^<70PK#hh~Og8+$vLYsbnD~eecAVK4ugZaf#@BGn}f8rGQd7q{SaIK|=%uLI`C16)!+zCKS{;Ky}{`YNJ%| zfbrr>BPfVAvC`G%Xs4C2o$W5h{aKmvyW~a=u_>%sY;ShH&{Q{$0!ut40gm})0X4K3j8n27CaBk3U z+hTWoR);_??0>odT}?vEjc);m&rs7~J>F1U{S`1A0s2`PyYig%!`le&+;p3X1b+8M zxl99N`sU-ndME;PeCkSiuCkyZpVMcRP_Y~z-offWy#&5{Xq%-whujxabOC0QGmrhy zyc$<(7qUX7u2QV=h&b<*7+@_sT`~xc2_$LqAxdUT%>v7owOGv;wF4Bq$f2|NQ8V-H zTZ-U!foLu&oUOmip^0Y+E@ysPmcP^c6kA&0v7UWxtB3?pn-MHKp4tT3`{6~6<}$iZ zrAN2k>xEyP+u_SZ-M#1hq#WJP`ub*B*hQVif#3v}86fvwq6%hlq3lelA`8xp7&VPW z{yO4ZGU}Zy%h#QWF|PR{vtYmsUaynj5{4wW3}a%o1P0hZxg3%*n&U*ATU)m9TRP|0 zPH@>ByQ4Z>WJ;n)v}jNU<;v7LU%coNUA!np7cnYsmjv3)4jOTcmkPh7CLUQnr(751 zxyCrfW{@H^R&UHf5duRZz=5EFz=2a;v$X7@#ODgvwjbE*RNv3x0CY;R)D~Ez863s2qE2P zW>i|AIiM3PSFGw=(k7h=FpOY4mn6UtRgiqUy{5~|6S(37t*)2Khz@tA?42Pex@Ddm}ov`}p%LspX-#%=- zU6hG}@ujz#AC13yz09lQrSpj2eiHGC%fQ|W6<~(5cfud^V7D+O0=<6=;f)V4yz&lc zitcASUdtC=bjcHecH!jQ4^6m)EKX!QSd!ihN}4QU+zyi>T6ax~>m}7|W=mNkRhZMJ zaa9yGuayQWT$f7x$h%!?<~hya=nG6E(+Bve&ht0-Ts2UU`}0aOxv5o0&23Y! z#%L+YSX@ib&NV$0*IpY@;I%*8004aBnahAGPN#_f_or{*YfoInx1YOG0kG(K1#QmV z*FtY|u~czp?pVPV7t10TcPVZp%YSS3HN1%8g%p{IDGARaZN}e$aJ|5Tg}(`A@VEk5 z{c{)wP#8f&=C&k7oY;hy{9#QwgK{Ql>eD;H<-Ww0o#3)Nz6xTCXmKv&xKNx>-7H0L z(JI7bVaCLj;&?G3Cg$2%$A9rqUjH|}L!zE19Y~i@M3d}z;gDP{6w@M_1Et#Apy_KN zs4!RrEQBzm^MObU7O#$%{(OY3mjNBvyTmU{tkIV9p09K6_II(b-+>}x3U~0~#lHX# zcOX1qlF6b(QvUT$iRv++$^gkg)evk!9uTqvh6fC^kE?foj6u(VFo1PLB(+ndLdq^_ znj0sfp*l`dOoy6=x!PK##TAv$@hv2oDiGZSD>yM~@igmWMNGwI14t6i>~b~8uLeo) zg?J4YPp(3SL)(;7iD)8M@iS46B3Cue*?MKXs6$B9C z>K0DdhX}fdy_09aIy$FID=Jm=s>t}7vU!_BWHYdwFX8;eC8VBW0#V1Xb6apUuw@` zB2837xn(8Nog?t|yJSWrQCHtU+y4(9#uR6q}4tbH8*p0o>j~)ZfjoKY0m&Vwz%^Z2i+e ze-=>`r<;g5iv`W1!dE%N1i?NIG#6iL8_=w=Xz9A0y9Hh>!Ghoc2e$-VI$WyTCA(xShBRptFRG3hfkrzo2wXhH9B&PA6*Xd# zg%<{h?VKJMAy5)pOl%3tu0GoG!ASaSZQao`g%$NKm=5&Y17h>_YW%2=FV}N%nkO(q zyog8N{~rMWr^5$08Q+E?Jx_=0*RcsV+r@s@f=FGZFw+VLC*MNA8ms9l*3;vKfs@0x zh24_d74!2dikP+O%*!!nFQ`_5tJMjY*UiO^RO)M(#I)$1&z54Aha00*xFaShygwmMyufz^kK zE5AW-d<5SSx z!})@2+x^_RSss4TW$^^BRi;!p7_L=4SF13YJ4G#4WCDr-l7vv5CQ`*0WN zI&sCfnJ6>J*!ii-RFx?qwS zloxIX5zWqT-a!Qsc)bP>CbkSCcuZmohvZ}-bF|bJ4ij6rHWMkR?zA=h7HW1;cMg}` z@s$=^G%cRhgcR+Bm*{Gq3j{aT@1r>#;?z4>P~9+7cDb|=UX9fm)BIhn%oo3G%@xnt z<&vU8NHHP?f(TRztc0LR&;SG)Qe0%9fLevdbD>4%!hkp-xSaE)ce|h!n4LXay9T#O*(nshiopRnF*t{`BBTpQJpxbL3Q&y zW}7%C?mbe)I``bU=d5kft1*>Q5WAFGG z9Phu0!~K^L`80_~P;eGmipzzo%LNJ+fvAFmx=jYFiq2yu&~RMl(0yNb-i{^I)kjyc zsfsVX@KU)gJ>SLgS|~WzOlTpzRO3fIjF&x_m#X+uLAy1^CgUL#M^Fk7zJWji<8%c< z_iTQepw=t74&Y#SlHDDjf#4D_y#6-iv5Sb`d>q)sPyTN(aQQ{Wh1Yx57?EXvby`)DVmd=*6(-)OLPVu`N#reVA&1Om3$5!iOA zB#AJd0YOyz1#^bGz~y?ki+!B|x5BRINW^_`s?bp*C$;06*sCU4FG>OnG9)+;*qzqo z(#kFO#tBtR!pra8x`itj_i*{*UajYK;tPoIySHy65aFrE54N&d^nOGZ&min8lRt*& zvUHr=8}N^R^ff?%lQU1sXLDQHi?peSZVWwLn?ci3)Uj27Wuc`AA~F|T()_;y4BOvz zks)jc=Sm~?aAy!ZzAw|4?K}m;BY$;&es;tu|;cnRpF1zDPE4Ek+Bx1%}5rGLJC~lS%CvowhDYHCKM4Mb4oSZKP zS#|NDB)DV;Oub%q$ke}M0dq&a28;k%O#6!L`dyJAw3_$ z=5A6-%|yycY#JErqo)w!Io!VRGcXbxM~ibMy&FVhi9V?bFM-r;E{Gd{rEL&|iyF8N=b@L+e=0y-Wq>DO{{#De__QAqgN{$J`j5Z)`~;WX zu{*rzvaROWFNd>0GN-CmsX}Z5lE`wEtee>{OaxLgcpBZesww$?HG&GU^7-uFu>GF9gEZp11&_6vd$>?u9CzdF-Gp#?M;7w!9To zq2LUmWt)qnlQ=%LPTzS;kv8+fS)Hl7gVH_T+K$!2ZqZdgYgaki!*yrk$RhJ)S+J?L z=x)K#z;nGgqHTi*dVp>V(QWVJ+}YCKzg}#iafLAE>gUl|EvW*UI2fF3SlyS3kOQh7KS-m2r>EiEJozxg?2uO$&o4~>73#s zFBReoS9R|M=K|byVog^souiXbYR-vGBuA5=RTttl#;mTWe$H>xWRp+_(;!TQ7IlbK*pNw*qpGfZPp&+s%DgiIbZC4Il%>l z#cCra;QFm&{N~jU@%(d-;L$7RieNx)S4K5)NjMOO!1uRs?ZgSar?{eXuF)xWQOF-K$G9;?A$We8-^kPWgR@6tAT9HH-m@a-d zvggOl7%Z-7N!(-fFii2TAFbAQ9#@swG7O*)QZrEo~zY7u6jSTOqf^j-2?C87~#u>u#5* z@LR&b#%dvik=(?ZOO>!1mwF}1~>O0!a6D%HeG=Oywx04{n{MkcbkNdfe0dHxjDNs~{dX7#A>ex^n7#lLpx zJ%OgBO3n4ux})rRCf?=uPA|@TL82nLDkz!EEyc_xxG2=PJj9e5J&;m4vm)Nx)~2MoJtP!>-zEVlx9xnaHlgkUXLD8Cb0aRwcj7lc&=RvS%j zp`_&QPPqN#(%vZY$OXui^XYTP1ipO)e)r~_H?TV%Sa{*14c7nuZy;AL;^e>iJ}~m< zSBdf$MjD}@h6fc%rdlp0oV9q~5 zAJf?;z&uEI()|vS3lpd=TGTRVx>lkyqC;MM02bUSXeafur4o83tiW?seDr4y!0lU- zyx1}mg1j?k@%K7s%hKa3)z1N(>z=c-#ds~mAwhCYT%nM8Ex{_FTkku8T6lqXpna5f zqTNJicYJB*{I+23;J0NF?f)-=ih*yVuLf?fQ=4q+_h`-~aCO1?e#n9=uL>loq8f-B zDSsCP3{@~PxKVPvcnB}&s%YvUyx!&FB1l=3sqPuZ zN|W=`|JQ$s)4%r(#BV?OaJXKWfRhQU|MU{VyEg#r=A*mg3nsdh^;R>2&Au#y zWf5Db6$Og;0q1;S;H?i%AObvnZ4b&deq45exb6mJK5oAb1Z*N9d9s)+(qcn(GRYR4 zOwTK-!cC_MkWy676hCSBaLO>i)dg54XN^($90Mig&{3Eva=;Hh=;NeDNdKJktqMGM9b_J z|G~Q-=+jPY*&Sd0`F|1)Vr8;qK|>=_4Rmf3a&88hWEK}{#1_Zzs1?EsJQA}{dar4X zL8!%Sssn(H*^$P-${XQwCD?+P-B{}(u6 z8?9P)999*bhCnKjp7qJo81(|~9Q+bOGHWLC7179omLs@G7oBP65ceZC&@2j0 zo$vxz2~O;*qtUTk&GQt& z*(;DY-p9#5`lBRzeNkO6Ljb?|0oMQV#Uv2z=A^sh3n{vwF0QEANmyQMRfw(!*lG(p zQz{GH$1aa0&zzf!D6?URpppkg)QL)2fOA8;a@E&BqvqpP=j@jI9<+9Y z+wS->uK}cUvNSB0TKAkp7HwdumD8aOFtyeOt6NBWM~pb}LR-z0)55tpECLWT*!F@{ zSUp!LE})>0KKr>AIt-QX;++{eGQ-Vfm3N}3a94B?U4P!oT$!e2P5LNjj!w0WJkr%? z=i2OPBZwPg*Jz3}hZSQOIH_Nn<_xjhd8zTp{1{9?Df6E+Ct>Gq;aY;zR4$jVRh@BA zOH`UH-kjV)oY*j2xn`1^iGXJ8sxC|0I51b0nzObztETE;DuRsN7iKbk3n3V%hiyKh zR9}$m3RX_(hkAvgy;%M)62%lO_blN;%zab*h#)1v9 z+Y|s$x5=<|sG-@Skh~ySSS}{InA@ecc5#^i=Gc*s7}3II$(@3kXwp|rSH26^s8ar! zbHL=^4;DLGM?#Rv36Em0$yZR>4vf?9e;x6=PtDydALaI*1`C+$^<{UpSB6n&U&@$mE z_qlLhs7yS3hbEb`A@7W^lOodBHN=$oF^Z$334i;_hxo?R7xBoIb0)rMQ(<^7v0?k= z+Qoxf-bpW}C>D4p4!jBz0ElwzydBI%bSAL%HJoRizh>M!T9oNJJw_M)P8%<3YoX^X z7e9&5tx?)ATC{n*x>y5^wtBkfv!I9Oq7_f9k!Ts_i>^|-yC3k2kNOMcDGCEDK`*cO^x4v;muzmZ6AN zaB*xE?|>=sBo{-{=6e@K%8fNrqd2AdR{;%Z#wQ8^5(R9xnO&QueaE1)A#eh#X7R=1 zCt3)VtUR?9#6$>h3IUK;k6aA2&Iaq zxJ*BRDJCH)i*P^o)lDFRo)ggMnir`O)Zb`w~dif*NQ8ypE>9T29g5WR&B--Pg{ zytY|fQ4wee6>{8w;k9uISJ3hHxl)OUJ2zI15~1U})bXxxT*xzCs>>ydDz(+9jUBbZ zOlZGvoGr8n-u10U&F_E_Vg$VKR5)~BA=O0%@sW!-{U_f~AEr+_$}$P!^H1P3My!AF zYUw529rr7|q~~k>AN~e%@c^g)@Y~Rf`z=G~vpg(L#_!(1_?It%k4|h6xN|b?jxV_A zvLv=F#)=9AB?}!kKq}PMX@y;FmgFk)(`|AO#RlwhW z;c>HtOA!WYj9l*#(?Z8LX(L*Fd(OSZ67B8rk*O?eJ3<$#rn4^VwFqcb; z5tZ6!u7E#ehD#4cqLL%1Q6g-2w|IupPH@>BJHe$!KuY_N!!Be{ZY)s{$K&vh7|}+k z$u-YCyCXLkHPI5sY4Jiwj+v6}K@1!aLUrJza}iheiG5x(yxu!pLa-{~EWU)qe&Ku> zQ*y}!r+xH-5V~69hV_!~w{yPqOc>ALa?BbIj4-$XnvzgdDy2;r3c>E9&AH=L7j2jB z`~;8O{&&FsWxR3epJNIa%OaPkHW+1hY8IvlQsxm#Eg)B&(86{b$$8{Xk5r-lrG>FM zeNq#5f^z`-I8ssv>OXq9LYavzPI1w{xZjC z$(JRk3X=0hsep62shnOATQa}JH5L&O1~AqWYV_L^v_GAh*cbIgi}?5>*!=nPX%hWu z#aE_?_?@S4!i3e&UkASG%$$!Tz69{?BkcX#p94@#&pwLHpMDcq1Ddk_y>Rd1lFse@I3lSi*^IeS+LvQiLnHZT>`h}+iM~* zouE)fj%9f70}nbtWEpH%^{s5i@AD0uKQcMsOHGLjX~V4sjM*h!eMkvYRE9sL3lF*rnJ_?`u7S0MBVwx z4O)sMRG?cZGgZfnuMrNN_`>f0EVzUrIb-rkEQ=_WMOB?H)eVRas+$EFD$Q)-crd<^ zN1a%c9U3rmUkJgR6ja7Hg7HU;ydOI^=kfR?-n;nEaBKgE=?+g)=P=YZB$he6`crCk zWF%*yo8p*5S1mq7nt5dEICZv=?BYs2!>+J+P-9E11P$t3yG|I8RLSh;4`hs<6f>&g zT8e`FaTn2KDN4#BZ$xIk?yD$hW06`WSBO(AP!R&xuWds7|)LJ=Hs9vanKe z((qa8y5p3E7q!cB4Rvz1SSyj+nMu4CDOO%4|8pc)XdWh4muZC)HMV2Ocz2cHlP=JKHk0x;hqm0 z?SsZ#aKZL=rt)0$B9#-BMBAv(V#V}=n6=f-vL)8lw-*5m4kIixU7Bdy5WuB@D1dnc zLTH_b?NpW0Pbj2sm-cm{ZeF2(~y6l>w3$ z<{|%_0Uo(5;M3zH_y}it%-V}4+C3+2jIua}`r2q|*_RlZ4KyRd(KO@v{)t!k3A@2UBo+0CPJoNC5p zPnWOaBS`=Xhi-GDf^>nQX)RK1cjX=oq}w`OO2?LOHR@ryPI#%YAnM#L^PhRK1c2kV zgz~%Gi7kDkXsKR$5F~K!{XE<+^@&yxAG?C-g{L2mcAVX@@Nu-y#_c2UFMo&eZ(ak4 zp?f1Bg81}R$P-uY?Sf$jUB8Xtm3PvK>2w0eDQzJ37Q)@JJ08;G{~rK);$Z5TLAQ 0 ? 1 : x < 0 ? -1 : 0; }; +var sqrt = Math.sqrt; +var tan = Math.tan; + +function acos(x) { + return x > 1 ? 0 : x < -1 ? pi : Math.acos(x); +} + +function asin(x) { + return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x); +} + +function haversin(x) { + return (x = sin(x / 2)) * x; +} + + +/***/ }), +/* 1 */ +/***/ (function(module, exports) { + +/** + * Graphology isGraph + * =================== + * + * Very simple function aiming at ensuring the given variable is a + * graphology instance. + */ + +/** + * Checking the value is a graphology instance. + * + * @param {any} value - Target value. + * @return {boolean} + */ +module.exports = function isGraph(value) { + return ( + value !== null && + typeof value === 'object' && + typeof value.addUndirectedEdgeWithKey === 'function' && + typeof value.dropNode === 'function' && + typeof value.multi === 'boolean' + ); +}; + + +/***/ }), +/* 2 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_create__ = __webpack_require__(282); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_0__src_create__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_creator__ = __webpack_require__(43); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_1__src_creator__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_local__ = __webpack_require__(311); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return __WEBPACK_IMPORTED_MODULE_2__src_local__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__src_matcher__ = __webpack_require__(145); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return __WEBPACK_IMPORTED_MODULE_3__src_matcher__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__src_mouse__ = __webpack_require__(312); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return __WEBPACK_IMPORTED_MODULE_4__src_mouse__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__src_namespace__ = __webpack_require__(72); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return __WEBPACK_IMPORTED_MODULE_5__src_namespace__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__src_namespaces__ = __webpack_require__(73); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "j", function() { return __WEBPACK_IMPORTED_MODULE_6__src_namespaces__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__src_point__ = __webpack_require__(44); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_7__src_point__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__src_select__ = __webpack_require__(143); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "k", function() { return __WEBPACK_IMPORTED_MODULE_8__src_select__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__src_selectAll__ = __webpack_require__(313); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "l", function() { return __WEBPACK_IMPORTED_MODULE_9__src_selectAll__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__src_selection_index__ = __webpack_require__(6); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "m", function() { return __WEBPACK_IMPORTED_MODULE_10__src_selection_index__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__src_selector__ = __webpack_require__(74); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "n", function() { return __WEBPACK_IMPORTED_MODULE_11__src_selector__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__src_selectorAll__ = __webpack_require__(144); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "o", function() { return __WEBPACK_IMPORTED_MODULE_12__src_selectorAll__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__src_selection_style__ = __webpack_require__(148); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "p", function() { return __WEBPACK_IMPORTED_MODULE_13__src_selection_style__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14__src_touch__ = __webpack_require__(314); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "q", function() { return __WEBPACK_IMPORTED_MODULE_14__src_touch__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15__src_touches__ = __webpack_require__(315); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "r", function() { return __WEBPACK_IMPORTED_MODULE_15__src_touches__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_16__src_window__ = __webpack_require__(75); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "s", function() { return __WEBPACK_IMPORTED_MODULE_16__src_window__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_17__src_selection_on__ = __webpack_require__(76); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return __WEBPACK_IMPORTED_MODULE_17__src_selection_on__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_17__src_selection_on__["a"]; }); + + + + + + + + + + + + + + + + + + + + +/***/ }), +/* 3 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = newInterval; +var t0 = new Date, + t1 = new Date; + +function newInterval(floori, offseti, count, field) { + + function interval(date) { + return floori(date = new Date(+date)), date; + } + + interval.floor = interval; + + interval.ceil = function(date) { + return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date; + }; + + interval.round = function(date) { + var d0 = interval(date), + d1 = interval.ceil(date); + return date - d0 < d1 - date ? d0 : d1; + }; + + interval.offset = function(date, step) { + return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; + }; + + interval.range = function(start, stop, step) { + var range = [], previous; + start = interval.ceil(start); + step = step == null ? 1 : Math.floor(step); + if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date + do range.push(previous = new Date(+start)), offseti(start, step), floori(start); + while (previous < start && start < stop); + return range; + }; + + interval.filter = function(test) { + return newInterval(function(date) { + if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1); + }, function(date, step) { + if (date >= date) { + if (step < 0) while (++step <= 0) { + while (offseti(date, -1), !test(date)) {} // eslint-disable-line no-empty + } else while (--step >= 0) { + while (offseti(date, +1), !test(date)) {} // eslint-disable-line no-empty + } + } + }); + }; + + if (count) { + interval.count = function(start, end) { + t0.setTime(+start), t1.setTime(+end); + floori(t0), floori(t1); + return Math.floor(count(t0, t1)); + }; + + interval.every = function(step) { + step = Math.floor(step); + return !isFinite(step) || !(step > 0) ? null + : !(step > 1) ? interval + : interval.filter(field + ? function(d) { return field(d) % step === 0; } + : function(d) { return interval.count(0, d) % step === 0; }); + }; + } + + return interval; +} + + +/***/ }), +/* 4 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_bisect__ = __webpack_require__(131); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_0__src_bisect__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_0__src_bisect__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_0__src_bisect__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_ascending__ = __webpack_require__(23); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_1__src_ascending__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_bisector__ = __webpack_require__(132); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return __WEBPACK_IMPORTED_MODULE_2__src_bisector__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__src_cross__ = __webpack_require__(258); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return __WEBPACK_IMPORTED_MODULE_3__src_cross__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__src_descending__ = __webpack_require__(259); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return __WEBPACK_IMPORTED_MODULE_4__src_descending__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__src_deviation__ = __webpack_require__(134); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return __WEBPACK_IMPORTED_MODULE_5__src_deviation__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__src_extent__ = __webpack_require__(136); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return __WEBPACK_IMPORTED_MODULE_6__src_extent__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__src_histogram__ = __webpack_require__(260); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "j", function() { return __WEBPACK_IMPORTED_MODULE_7__src_histogram__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__src_threshold_freedmanDiaconis__ = __webpack_require__(263); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "w", function() { return __WEBPACK_IMPORTED_MODULE_8__src_threshold_freedmanDiaconis__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__src_threshold_scott__ = __webpack_require__(264); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "x", function() { return __WEBPACK_IMPORTED_MODULE_9__src_threshold_scott__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__src_threshold_sturges__ = __webpack_require__(140); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "y", function() { return __WEBPACK_IMPORTED_MODULE_10__src_threshold_sturges__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__src_max__ = __webpack_require__(265); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "k", function() { return __WEBPACK_IMPORTED_MODULE_11__src_max__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__src_mean__ = __webpack_require__(266); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "l", function() { return __WEBPACK_IMPORTED_MODULE_12__src_mean__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__src_median__ = __webpack_require__(267); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "m", function() { return __WEBPACK_IMPORTED_MODULE_13__src_median__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14__src_merge__ = __webpack_require__(268); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "n", function() { return __WEBPACK_IMPORTED_MODULE_14__src_merge__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15__src_min__ = __webpack_require__(141); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "o", function() { return __WEBPACK_IMPORTED_MODULE_15__src_min__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_16__src_pairs__ = __webpack_require__(133); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "p", function() { return __WEBPACK_IMPORTED_MODULE_16__src_pairs__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_17__src_permute__ = __webpack_require__(269); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "q", function() { return __WEBPACK_IMPORTED_MODULE_17__src_permute__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_18__src_quantile__ = __webpack_require__(70); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "r", function() { return __WEBPACK_IMPORTED_MODULE_18__src_quantile__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_19__src_range__ = __webpack_require__(138); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "s", function() { return __WEBPACK_IMPORTED_MODULE_19__src_range__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_20__src_scan__ = __webpack_require__(270); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "t", function() { return __WEBPACK_IMPORTED_MODULE_20__src_scan__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_21__src_shuffle__ = __webpack_require__(271); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "u", function() { return __WEBPACK_IMPORTED_MODULE_21__src_shuffle__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_22__src_sum__ = __webpack_require__(272); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "v", function() { return __WEBPACK_IMPORTED_MODULE_22__src_sum__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_23__src_ticks__ = __webpack_require__(139); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "B", function() { return __WEBPACK_IMPORTED_MODULE_23__src_ticks__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "z", function() { return __WEBPACK_IMPORTED_MODULE_23__src_ticks__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "A", function() { return __WEBPACK_IMPORTED_MODULE_23__src_ticks__["c"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_24__src_transpose__ = __webpack_require__(142); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "C", function() { return __WEBPACK_IMPORTED_MODULE_24__src_transpose__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_25__src_variance__ = __webpack_require__(135); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "D", function() { return __WEBPACK_IMPORTED_MODULE_25__src_variance__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_26__src_zip__ = __webpack_require__(273); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "E", function() { return __WEBPACK_IMPORTED_MODULE_26__src_zip__["a"]; }); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + +/** + * Graphology isGraphConstructor + * ============================== + * + * Very simple function aiming at ensuring the given variable is a + * graphology constructor. + */ + +/** + * Checking the value is a graphology constructor. + * + * @param {any} value - Target value. + * @return {boolean} + */ +module.exports = function isGraphConstructor(value) { + return ( + value !== null && + typeof value === 'function' && + typeof value.prototype === 'object' && + typeof value.prototype.addUndirectedEdgeWithKey === 'function' && + typeof value.prototype.dropNode === 'function' + ); +}; + + +/***/ }), +/* 6 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return root; }); +/* harmony export (immutable) */ __webpack_exports__["a"] = Selection; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__select__ = __webpack_require__(283); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__selectAll__ = __webpack_require__(284); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__filter__ = __webpack_require__(285); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__data__ = __webpack_require__(286); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__enter__ = __webpack_require__(146); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__exit__ = __webpack_require__(288); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__merge__ = __webpack_require__(289); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__order__ = __webpack_require__(290); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__sort__ = __webpack_require__(291); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__call__ = __webpack_require__(292); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__nodes__ = __webpack_require__(293); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__node__ = __webpack_require__(294); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__size__ = __webpack_require__(295); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__empty__ = __webpack_require__(296); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14__each__ = __webpack_require__(297); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15__attr__ = __webpack_require__(298); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_16__style__ = __webpack_require__(148); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_17__property__ = __webpack_require__(299); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_18__classed__ = __webpack_require__(300); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_19__text__ = __webpack_require__(301); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_20__html__ = __webpack_require__(302); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_21__raise__ = __webpack_require__(303); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_22__lower__ = __webpack_require__(304); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_23__append__ = __webpack_require__(305); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_24__insert__ = __webpack_require__(306); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_25__remove__ = __webpack_require__(307); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_26__clone__ = __webpack_require__(308); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_27__datum__ = __webpack_require__(309); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_28__on__ = __webpack_require__(76); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_29__dispatch__ = __webpack_require__(310); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +var root = [null]; + +function Selection(groups, parents) { + this._groups = groups; + this._parents = parents; +} + +function selection() { + return new Selection([[document.documentElement]], root); +} + +Selection.prototype = selection.prototype = { + constructor: Selection, + select: __WEBPACK_IMPORTED_MODULE_0__select__["a" /* default */], + selectAll: __WEBPACK_IMPORTED_MODULE_1__selectAll__["a" /* default */], + filter: __WEBPACK_IMPORTED_MODULE_2__filter__["a" /* default */], + data: __WEBPACK_IMPORTED_MODULE_3__data__["a" /* default */], + enter: __WEBPACK_IMPORTED_MODULE_4__enter__["b" /* default */], + exit: __WEBPACK_IMPORTED_MODULE_5__exit__["a" /* default */], + merge: __WEBPACK_IMPORTED_MODULE_6__merge__["a" /* default */], + order: __WEBPACK_IMPORTED_MODULE_7__order__["a" /* default */], + sort: __WEBPACK_IMPORTED_MODULE_8__sort__["a" /* default */], + call: __WEBPACK_IMPORTED_MODULE_9__call__["a" /* default */], + nodes: __WEBPACK_IMPORTED_MODULE_10__nodes__["a" /* default */], + node: __WEBPACK_IMPORTED_MODULE_11__node__["a" /* default */], + size: __WEBPACK_IMPORTED_MODULE_12__size__["a" /* default */], + empty: __WEBPACK_IMPORTED_MODULE_13__empty__["a" /* default */], + each: __WEBPACK_IMPORTED_MODULE_14__each__["a" /* default */], + attr: __WEBPACK_IMPORTED_MODULE_15__attr__["a" /* default */], + style: __WEBPACK_IMPORTED_MODULE_16__style__["a" /* default */], + property: __WEBPACK_IMPORTED_MODULE_17__property__["a" /* default */], + classed: __WEBPACK_IMPORTED_MODULE_18__classed__["a" /* default */], + text: __WEBPACK_IMPORTED_MODULE_19__text__["a" /* default */], + html: __WEBPACK_IMPORTED_MODULE_20__html__["a" /* default */], + raise: __WEBPACK_IMPORTED_MODULE_21__raise__["a" /* default */], + lower: __WEBPACK_IMPORTED_MODULE_22__lower__["a" /* default */], + append: __WEBPACK_IMPORTED_MODULE_23__append__["a" /* default */], + insert: __WEBPACK_IMPORTED_MODULE_24__insert__["a" /* default */], + remove: __WEBPACK_IMPORTED_MODULE_25__remove__["a" /* default */], + clone: __WEBPACK_IMPORTED_MODULE_26__clone__["a" /* default */], + datum: __WEBPACK_IMPORTED_MODULE_27__datum__["a" /* default */], + on: __WEBPACK_IMPORTED_MODULE_28__on__["b" /* default */], + dispatch: __WEBPACK_IMPORTED_MODULE_29__dispatch__["a" /* default */] +}; + +/* harmony default export */ __webpack_exports__["b"] = (selection); + + +/***/ }), +/* 7 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_value__ = __webpack_require__(78); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_0__src_value__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_array__ = __webpack_require__(155); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_1__src_array__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_basis__ = __webpack_require__(81); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_2__src_basis__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__src_basisClosed__ = __webpack_require__(153); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_3__src_basisClosed__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__src_date__ = __webpack_require__(156); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return __WEBPACK_IMPORTED_MODULE_4__src_date__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__src_number__ = __webpack_require__(45); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "m", function() { return __WEBPACK_IMPORTED_MODULE_5__src_number__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__src_object__ = __webpack_require__(157); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "n", function() { return __WEBPACK_IMPORTED_MODULE_6__src_object__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__src_round__ = __webpack_require__(320); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "r", function() { return __WEBPACK_IMPORTED_MODULE_7__src_round__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__src_string__ = __webpack_require__(158); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "s", function() { return __WEBPACK_IMPORTED_MODULE_8__src_string__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__src_transform_index__ = __webpack_require__(321); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "t", function() { return __WEBPACK_IMPORTED_MODULE_9__src_transform_index__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "u", function() { return __WEBPACK_IMPORTED_MODULE_9__src_transform_index__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__src_zoom__ = __webpack_require__(324); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "v", function() { return __WEBPACK_IMPORTED_MODULE_10__src_zoom__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__src_rgb__ = __webpack_require__(152); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "o", function() { return __WEBPACK_IMPORTED_MODULE_11__src_rgb__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "p", function() { return __WEBPACK_IMPORTED_MODULE_11__src_rgb__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "q", function() { return __WEBPACK_IMPORTED_MODULE_11__src_rgb__["c"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__src_hsl__ = __webpack_require__(325); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "j", function() { return __WEBPACK_IMPORTED_MODULE_12__src_hsl__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "k", function() { return __WEBPACK_IMPORTED_MODULE_12__src_hsl__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__src_lab__ = __webpack_require__(326); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "l", function() { return __WEBPACK_IMPORTED_MODULE_13__src_lab__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14__src_hcl__ = __webpack_require__(327); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return __WEBPACK_IMPORTED_MODULE_14__src_hcl__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return __WEBPACK_IMPORTED_MODULE_14__src_hcl__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15__src_cubehelix__ = __webpack_require__(328); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return __WEBPACK_IMPORTED_MODULE_15__src_cubehelix__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return __WEBPACK_IMPORTED_MODULE_15__src_cubehelix__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_16__src_quantize__ = __webpack_require__(329); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "w", function() { return __WEBPACK_IMPORTED_MODULE_16__src_quantize__["a"]; }); + + + + + + + + + + + + + + + + + + + +/***/ }), +/* 8 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* unused harmony export CREATED */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return SCHEDULED; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return STARTING; }); +/* unused harmony export STARTED */ +/* unused harmony export RUNNING */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return ENDING; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ENDED; }); +/* harmony export (immutable) */ __webpack_exports__["g"] = init; +/* harmony export (immutable) */ __webpack_exports__["h"] = set; +/* harmony export (immutable) */ __webpack_exports__["f"] = get; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_dispatch__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_d3_timer__ = __webpack_require__(46); + + + +var emptyOn = Object(__WEBPACK_IMPORTED_MODULE_0_d3_dispatch__["a" /* dispatch */])("start", "end", "interrupt"); +var emptyTween = []; + +var CREATED = 0; +var SCHEDULED = 1; +var STARTING = 2; +var STARTED = 3; +var RUNNING = 4; +var ENDING = 5; +var ENDED = 6; + +/* harmony default export */ __webpack_exports__["e"] = (function(node, name, id, index, group, timing) { + var schedules = node.__transition; + if (!schedules) node.__transition = {}; + else if (id in schedules) return; + create(node, id, { + name: name, + index: index, // For context during callback. + group: group, // For context during callback. + on: emptyOn, + tween: emptyTween, + time: timing.time, + delay: timing.delay, + duration: timing.duration, + ease: timing.ease, + timer: null, + state: CREATED + }); +}); + +function init(node, id) { + var schedule = get(node, id); + if (schedule.state > CREATED) throw new Error("too late; already scheduled"); + return schedule; +} + +function set(node, id) { + var schedule = get(node, id); + if (schedule.state > STARTING) throw new Error("too late; already started"); + return schedule; +} + +function get(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id])) throw new Error("transition not found"); + return schedule; +} + +function create(node, id, self) { + var schedules = node.__transition, + tween; + + // Initialize the self timer when the transition is created. + // Note the actual delay is not known until the first callback! + schedules[id] = self; + self.timer = Object(__WEBPACK_IMPORTED_MODULE_1_d3_timer__["d" /* timer */])(schedule, 0, self.time); + + function schedule(elapsed) { + self.state = SCHEDULED; + self.timer.restart(start, self.delay, self.time); + + // If the elapsed delay is less than our first sleep, start immediately. + if (self.delay <= elapsed) start(elapsed - self.delay); + } + + function start(elapsed) { + var i, j, n, o; + + // If the state is not SCHEDULED, then we previously errored on start. + if (self.state !== SCHEDULED) return stop(); + + for (i in schedules) { + o = schedules[i]; + if (o.name !== self.name) continue; + + // While this element already has a starting transition during this frame, + // defer starting an interrupting transition until that transition has a + // chance to tick (and possibly end); see d3/d3-transition#54! + if (o.state === STARTED) return Object(__WEBPACK_IMPORTED_MODULE_1_d3_timer__["c" /* timeout */])(start); + + // Interrupt the active transition, if any. + // Dispatch the interrupt event. + if (o.state === RUNNING) { + o.state = ENDED; + o.timer.stop(); + o.on.call("interrupt", node, node.__data__, o.index, o.group); + delete schedules[i]; + } + + // Cancel any pre-empted transitions. No interrupt event is dispatched + // because the cancelled transitions never started. Note that this also + // removes this transition from the pending list! + else if (+i < id) { + o.state = ENDED; + o.timer.stop(); + delete schedules[i]; + } + } + + // Defer the first tick to end of the current frame; see d3/d3#1576. + // Note the transition may be canceled after start and before the first tick! + // Note this must be scheduled before the start event; see d3/d3-transition#16! + // Assuming this is successful, subsequent callbacks go straight to tick. + Object(__WEBPACK_IMPORTED_MODULE_1_d3_timer__["c" /* timeout */])(function() { + if (self.state === STARTED) { + self.state = RUNNING; + self.timer.restart(tick, self.delay, self.time); + tick(elapsed); + } + }); + + // Dispatch the start event. + // Note this must be done before the tween are initialized. + self.state = STARTING; + self.on.call("start", node, node.__data__, self.index, self.group); + if (self.state !== STARTING) return; // interrupted + self.state = STARTED; + + // Initialize the tween, deleting null tween. + tween = new Array(n = self.tween.length); + for (i = 0, j = -1; i < n; ++i) { + if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { + tween[++j] = o; + } + } + tween.length = j + 1; + } + + function tick(elapsed) { + var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), + i = -1, + n = tween.length; + + while (++i < n) { + tween[i].call(null, t); + } + + // Dispatch the end event. + if (self.state === ENDING) { + self.on.call("end", node, node.__data__, self.index, self.group); + stop(); + } + } + + function stop() { + self.state = ENDED; + self.timer.stop(); + delete schedules[id]; + for (var i in schedules) return; // eslint-disable-line no-unused-vars + delete node.__transition; + } +} + + +/***/ }), +/* 9 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_color__ = __webpack_require__(79); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_0__src_color__["e"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return __WEBPACK_IMPORTED_MODULE_0__src_color__["g"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_0__src_color__["f"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_lab__ = __webpack_require__(318); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return __WEBPACK_IMPORTED_MODULE_1__src_lab__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_1__src_lab__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_cubehelix__ = __webpack_require__(319); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_2__src_cubehelix__["a"]; }); + + + + + +/***/ }), +/* 10 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = projection; +/* harmony export (immutable) */ __webpack_exports__["b"] = projectionMutator; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__clip_antimeridian__ = __webpack_require__(171); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__clip_circle__ = __webpack_require__(177); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__clip_rectangle__ = __webpack_require__(50); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__compose__ = __webpack_require__(170); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__identity__ = __webpack_require__(92); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__math__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__rotation__ = __webpack_require__(49); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__transform__ = __webpack_require__(51); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__fit__ = __webpack_require__(95); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__resample__ = __webpack_require__(423); + + + + + + + + + + + +var transformRadians = Object(__WEBPACK_IMPORTED_MODULE_7__transform__["b" /* transformer */])({ + point: function(x, y) { + this.stream.point(x * __WEBPACK_IMPORTED_MODULE_5__math__["r" /* radians */], y * __WEBPACK_IMPORTED_MODULE_5__math__["r" /* radians */]); + } +}); + +function transformRotate(rotate) { + return Object(__WEBPACK_IMPORTED_MODULE_7__transform__["b" /* transformer */])({ + point: function(x, y) { + var r = rotate(x, y); + return this.stream.point(r[0], r[1]); + } + }); +} + +function projection(project) { + return projectionMutator(function() { return project; })(); +} + +function projectionMutator(projectAt) { + var project, + k = 150, // scale + x = 480, y = 250, // translate + dx, dy, lambda = 0, phi = 0, // center + deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate + theta = null, preclip = __WEBPACK_IMPORTED_MODULE_0__clip_antimeridian__["a" /* default */], // clip angle + x0 = null, y0, x1, y1, postclip = __WEBPACK_IMPORTED_MODULE_4__identity__["a" /* default */], // clip extent + delta2 = 0.5, projectResample = Object(__WEBPACK_IMPORTED_MODULE_9__resample__["a" /* default */])(projectTransform, delta2), // precision + cache, + cacheStream; + + function projection(point) { + point = projectRotate(point[0] * __WEBPACK_IMPORTED_MODULE_5__math__["r" /* radians */], point[1] * __WEBPACK_IMPORTED_MODULE_5__math__["r" /* radians */]); + return [point[0] * k + dx, dy - point[1] * k]; + } + + function invert(point) { + point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k); + return point && [point[0] * __WEBPACK_IMPORTED_MODULE_5__math__["h" /* degrees */], point[1] * __WEBPACK_IMPORTED_MODULE_5__math__["h" /* degrees */]]; + } + + function projectTransform(x, y) { + return x = project(x, y), [x[0] * k + dx, dy - x[1] * k]; + } + + projection.stream = function(stream) { + return cache && cacheStream === stream ? cache : cache = transformRadians(transformRotate(rotate)(preclip(projectResample(postclip(cacheStream = stream))))); + }; + + projection.preclip = function(_) { + return arguments.length ? (preclip = _, theta = undefined, reset()) : preclip; + }; + + projection.postclip = function(_) { + return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip; + }; + + projection.clipAngle = function(_) { + return arguments.length ? (preclip = +_ ? Object(__WEBPACK_IMPORTED_MODULE_1__clip_circle__["a" /* default */])(theta = _ * __WEBPACK_IMPORTED_MODULE_5__math__["r" /* radians */]) : (theta = null, __WEBPACK_IMPORTED_MODULE_0__clip_antimeridian__["a" /* default */]), reset()) : theta * __WEBPACK_IMPORTED_MODULE_5__math__["h" /* degrees */]; + }; + + projection.clipExtent = function(_) { + return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, __WEBPACK_IMPORTED_MODULE_4__identity__["a" /* default */]) : Object(__WEBPACK_IMPORTED_MODULE_2__clip_rectangle__["a" /* default */])(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }; + + projection.scale = function(_) { + return arguments.length ? (k = +_, recenter()) : k; + }; + + projection.translate = function(_) { + return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y]; + }; + + projection.center = function(_) { + return arguments.length ? (lambda = _[0] % 360 * __WEBPACK_IMPORTED_MODULE_5__math__["r" /* radians */], phi = _[1] % 360 * __WEBPACK_IMPORTED_MODULE_5__math__["r" /* radians */], recenter()) : [lambda * __WEBPACK_IMPORTED_MODULE_5__math__["h" /* degrees */], phi * __WEBPACK_IMPORTED_MODULE_5__math__["h" /* degrees */]]; + }; + + projection.rotate = function(_) { + return arguments.length ? (deltaLambda = _[0] % 360 * __WEBPACK_IMPORTED_MODULE_5__math__["r" /* radians */], deltaPhi = _[1] % 360 * __WEBPACK_IMPORTED_MODULE_5__math__["r" /* radians */], deltaGamma = _.length > 2 ? _[2] % 360 * __WEBPACK_IMPORTED_MODULE_5__math__["r" /* radians */] : 0, recenter()) : [deltaLambda * __WEBPACK_IMPORTED_MODULE_5__math__["h" /* degrees */], deltaPhi * __WEBPACK_IMPORTED_MODULE_5__math__["h" /* degrees */], deltaGamma * __WEBPACK_IMPORTED_MODULE_5__math__["h" /* degrees */]]; + }; + + projection.precision = function(_) { + return arguments.length ? (projectResample = Object(__WEBPACK_IMPORTED_MODULE_9__resample__["a" /* default */])(projectTransform, delta2 = _ * _), reset()) : Object(__WEBPACK_IMPORTED_MODULE_5__math__["u" /* sqrt */])(delta2); + }; + + projection.fitExtent = function(extent, object) { + return Object(__WEBPACK_IMPORTED_MODULE_8__fit__["a" /* fitExtent */])(projection, extent, object); + }; + + projection.fitSize = function(size, object) { + return Object(__WEBPACK_IMPORTED_MODULE_8__fit__["c" /* fitSize */])(projection, size, object); + }; + + projection.fitWidth = function(width, object) { + return Object(__WEBPACK_IMPORTED_MODULE_8__fit__["d" /* fitWidth */])(projection, width, object); + }; + + projection.fitHeight = function(height, object) { + return Object(__WEBPACK_IMPORTED_MODULE_8__fit__["b" /* fitHeight */])(projection, height, object); + }; + + function recenter() { + projectRotate = Object(__WEBPACK_IMPORTED_MODULE_3__compose__["a" /* default */])(rotate = Object(__WEBPACK_IMPORTED_MODULE_6__rotation__["b" /* rotateRadians */])(deltaLambda, deltaPhi, deltaGamma), project); + var center = project(lambda, phi); + dx = x - center[0] * k; + dy = y + center[1] * k; + return reset(); + } + + function reset() { + cache = cacheStream = null; + return projection; + } + + return function() { + project = projectAt.apply(this, arguments); + projection.invert = project.invert && invert; + return recenter(); + }; +} + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +var freeGlobal = __webpack_require__(215); + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +module.exports = root; + + +/***/ }), +/* 12 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return durationSecond; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return durationMinute; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return durationHour; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return durationDay; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return durationWeek; }); +var durationSecond = 1e3; +var durationMinute = 6e4; +var durationHour = 36e5; +var durationDay = 864e5; +var durationWeek = 6048e5; + + +/***/ }), +/* 13 */ +/***/ (function(module, exports) { + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +module.exports = isObject; + + +/***/ }), +/* 14 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = Transition; +/* harmony export (immutable) */ __webpack_exports__["b"] = transition; +/* harmony export (immutable) */ __webpack_exports__["c"] = newId; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_selection__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__attr__ = __webpack_require__(335); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__attrTween__ = __webpack_require__(336); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__delay__ = __webpack_require__(337); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__duration__ = __webpack_require__(338); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__ease__ = __webpack_require__(339); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__filter__ = __webpack_require__(340); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__merge__ = __webpack_require__(341); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__on__ = __webpack_require__(342); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__remove__ = __webpack_require__(343); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__select__ = __webpack_require__(344); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__selectAll__ = __webpack_require__(345); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__selection__ = __webpack_require__(346); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__style__ = __webpack_require__(347); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14__styleTween__ = __webpack_require__(348); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_15__text__ = __webpack_require__(349); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_16__transition__ = __webpack_require__(350); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_17__tween__ = __webpack_require__(47); + + + + + + + + + + + + + + + + + + + +var id = 0; + +function Transition(groups, parents, name, id) { + this._groups = groups; + this._parents = parents; + this._name = name; + this._id = id; +} + +function transition(name) { + return Object(__WEBPACK_IMPORTED_MODULE_0_d3_selection__["m" /* selection */])().transition(name); +} + +function newId() { + return ++id; +} + +var selection_prototype = __WEBPACK_IMPORTED_MODULE_0_d3_selection__["m" /* selection */].prototype; + +Transition.prototype = transition.prototype = { + constructor: Transition, + select: __WEBPACK_IMPORTED_MODULE_10__select__["a" /* default */], + selectAll: __WEBPACK_IMPORTED_MODULE_11__selectAll__["a" /* default */], + filter: __WEBPACK_IMPORTED_MODULE_6__filter__["a" /* default */], + merge: __WEBPACK_IMPORTED_MODULE_7__merge__["a" /* default */], + selection: __WEBPACK_IMPORTED_MODULE_12__selection__["a" /* default */], + transition: __WEBPACK_IMPORTED_MODULE_16__transition__["a" /* default */], + call: selection_prototype.call, + nodes: selection_prototype.nodes, + node: selection_prototype.node, + size: selection_prototype.size, + empty: selection_prototype.empty, + each: selection_prototype.each, + on: __WEBPACK_IMPORTED_MODULE_8__on__["a" /* default */], + attr: __WEBPACK_IMPORTED_MODULE_1__attr__["a" /* default */], + attrTween: __WEBPACK_IMPORTED_MODULE_2__attrTween__["a" /* default */], + style: __WEBPACK_IMPORTED_MODULE_13__style__["a" /* default */], + styleTween: __WEBPACK_IMPORTED_MODULE_14__styleTween__["a" /* default */], + text: __WEBPACK_IMPORTED_MODULE_15__text__["a" /* default */], + remove: __WEBPACK_IMPORTED_MODULE_9__remove__["a" /* default */], + tween: __WEBPACK_IMPORTED_MODULE_17__tween__["a" /* default */], + delay: __WEBPACK_IMPORTED_MODULE_3__delay__["a" /* default */], + duration: __WEBPACK_IMPORTED_MODULE_4__duration__["a" /* default */], + ease: __WEBPACK_IMPORTED_MODULE_5__ease__["a" /* default */] +}; + + +/***/ }), +/* 15 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = noop; +function noop() {} + + +/***/ }), +/* 16 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_dispatch__ = __webpack_require__(280); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_0__src_dispatch__["a"]; }); + + + +/***/ }), +/* 17 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_path__ = __webpack_require__(370); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_0__src_path__["a"]; }); + + + +/***/ }), +/* 18 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +function streamGeometry(geometry, stream) { + if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) { + streamGeometryType[geometry.type](geometry, stream); + } +} + +var streamObjectType = { + Feature: function(object, stream) { + streamGeometry(object.geometry, stream); + }, + FeatureCollection: function(object, stream) { + var features = object.features, i = -1, n = features.length; + while (++i < n) streamGeometry(features[i].geometry, stream); + } +}; + +var streamGeometryType = { + Sphere: function(object, stream) { + stream.sphere(); + }, + Point: function(object, stream) { + object = object.coordinates; + stream.point(object[0], object[1], object[2]); + }, + MultiPoint: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]); + }, + LineString: function(object, stream) { + streamLine(object.coordinates, stream, 0); + }, + MultiLineString: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) streamLine(coordinates[i], stream, 0); + }, + Polygon: function(object, stream) { + streamPolygon(object.coordinates, stream); + }, + MultiPolygon: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) streamPolygon(coordinates[i], stream); + }, + GeometryCollection: function(object, stream) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) streamGeometry(geometries[i], stream); + } +}; + +function streamLine(coordinates, stream, closed) { + var i = -1, n = coordinates.length - closed, coordinate; + stream.lineStart(); + while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]); + stream.lineEnd(); +} + +function streamPolygon(coordinates, stream) { + var i = -1, n = coordinates.length; + stream.polygonStart(); + while (++i < n) streamLine(coordinates[i], stream, 1); + stream.polygonEnd(); +} + +/* harmony default export */ __webpack_exports__["a"] = (function(object, stream) { + if (object && streamObjectType.hasOwnProperty(object.type)) { + streamObjectType[object.type](object, stream); + } else { + streamGeometry(object, stream); + } +}); + + +/***/ }), +/* 19 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return map; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return slice; }); +var array = Array.prototype; + +var map = array.map; +var slice = array.slice; + + +/***/ }), +/* 20 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(x) { + return function constant() { + return x; + }; +}); + + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIsNative = __webpack_require__(572), + getValue = __webpack_require__(577); + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; +} + +module.exports = getNative; + + +/***/ }), +/* 22 */ +/***/ (function(module, exports) { + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +module.exports = isObjectLike; + + +/***/ }), +/* 23 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; +}); + + +/***/ }), +/* 24 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(x) { + return function() { + return x; + }; +}); + + +/***/ }), +/* 25 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +// Adds floating point numbers with twice the normal precision. +// Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and +// Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3) +// 305–363 (1997). +// Code adapted from GeographicLib by Charles F. F. Karney, +// http://geographiclib.sourceforge.net/ + +/* harmony default export */ __webpack_exports__["a"] = (function() { + return new Adder; +}); + +function Adder() { + this.reset(); +} + +Adder.prototype = { + constructor: Adder, + reset: function() { + this.s = // rounded value + this.t = 0; // exact error + }, + add: function(y) { + add(temp, y, this.t); + add(this, temp.s, this.s); + if (this.s) this.t += temp.t; + else this.s = temp.t; + }, + valueOf: function() { + return this.s; + } +}; + +var temp = new Adder; + +function add(adder, a, b) { + var x = adder.s = a + b, + bv = x - a, + av = x - bv; + adder.t = (a - av) + (b - bv); +} + + +/***/ }), +/* 26 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function() { + return Math.random(); +}); + + +/***/ }), +/* 27 */ +/***/ (function(module, exports) { + +/** + * Performs a + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) + * comparison between two values to determine if they are equivalent. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + * @example + * + * var object = { 'a': 1 }; + * var other = { 'a': 1 }; + * + * _.eq(object, object); + * // => true + * + * _.eq(object, other); + * // => false + * + * _.eq('a', 'a'); + * // => true + * + * _.eq('a', Object('a')); + * // => false + * + * _.eq(NaN, NaN); + * // => true + */ +function eq(value, other) { + return value === other || (value !== value && other !== other); +} + +module.exports = eq; + + +/***/ }), +/* 28 */ +/***/ (function(module, exports, __webpack_require__) { + +var Symbol = __webpack_require__(114), + getRawTag = __webpack_require__(573), + objectToString = __webpack_require__(574); + +/** `Object#toString` result references. */ +var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); +} + +module.exports = baseGetTag; + + +/***/ }), +/* 29 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(x) { + return x === null ? NaN : +x; +}); + + +/***/ }), +/* 30 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["c"] = hue; +/* harmony export (immutable) */ __webpack_exports__["b"] = gamma; +/* harmony export (immutable) */ __webpack_exports__["a"] = nogamma; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__constant__ = __webpack_require__(154); + + +function linear(a, d) { + return function(t) { + return a + t * d; + }; +} + +function exponential(a, b, y) { + return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { + return Math.pow(a + t * b, y); + }; +} + +function hue(a, b) { + var d = b - a; + return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : Object(__WEBPACK_IMPORTED_MODULE_0__constant__["a" /* default */])(isNaN(a) ? b : a); +} + +function gamma(y) { + return (y = +y) === 1 ? nogamma : function(a, b) { + return b - a ? exponential(a, b, y) : Object(__WEBPACK_IMPORTED_MODULE_0__constant__["a" /* default */])(isNaN(a) ? b : a); + }; +} + +function nogamma(a, b) { + var d = b - a; + return d ? linear(a, d) : Object(__WEBPACK_IMPORTED_MODULE_0__constant__["a" /* default */])(isNaN(a) ? b : a); +} + + +/***/ }), +/* 31 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_nest__ = __webpack_require__(371); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_0__src_nest__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_set__ = __webpack_require__(372); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return __WEBPACK_IMPORTED_MODULE_1__src_set__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_map__ = __webpack_require__(84); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_2__src_map__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__src_keys__ = __webpack_require__(373); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_3__src_keys__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__src_values__ = __webpack_require__(374); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return __WEBPACK_IMPORTED_MODULE_4__src_values__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__src_entries__ = __webpack_require__(375); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_5__src_entries__["a"]; }); + + + + + + + + +/***/ }), +/* 32 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["g"] = spherical; +/* harmony export (immutable) */ __webpack_exports__["a"] = cartesian; +/* harmony export (immutable) */ __webpack_exports__["d"] = cartesianDot; +/* harmony export (immutable) */ __webpack_exports__["c"] = cartesianCross; +/* harmony export (immutable) */ __webpack_exports__["b"] = cartesianAddInPlace; +/* harmony export (immutable) */ __webpack_exports__["f"] = cartesianScale; +/* harmony export (immutable) */ __webpack_exports__["e"] = cartesianNormalizeInPlace; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(0); + + +function spherical(cartesian) { + return [Object(__WEBPACK_IMPORTED_MODULE_0__math__["e" /* atan2 */])(cartesian[1], cartesian[0]), Object(__WEBPACK_IMPORTED_MODULE_0__math__["c" /* asin */])(cartesian[2])]; +} + +function cartesian(spherical) { + var lambda = spherical[0], phi = spherical[1], cosPhi = Object(__WEBPACK_IMPORTED_MODULE_0__math__["g" /* cos */])(phi); + return [cosPhi * Object(__WEBPACK_IMPORTED_MODULE_0__math__["g" /* cos */])(lambda), cosPhi * Object(__WEBPACK_IMPORTED_MODULE_0__math__["t" /* sin */])(lambda), Object(__WEBPACK_IMPORTED_MODULE_0__math__["t" /* sin */])(phi)]; +} + +function cartesianDot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + +function cartesianCross(a, b) { + return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]]; +} + +// TODO return a +function cartesianAddInPlace(a, b) { + a[0] += b[0], a[1] += b[1], a[2] += b[2]; +} + +function cartesianScale(vector, k) { + return [vector[0] * k, vector[1] * k, vector[2] * k]; +} + +// TODO return d +function cartesianNormalizeInPlace(d) { + var l = Object(__WEBPACK_IMPORTED_MODULE_0__math__["u" /* sqrt */])(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + d[0] /= l, d[1] /= l, d[2] /= l; +} + + +/***/ }), +/* 33 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = azimuthalRaw; +/* harmony export (immutable) */ __webpack_exports__["a"] = azimuthalInvert; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(0); + + +function azimuthalRaw(scale) { + return function(x, y) { + var cx = Object(__WEBPACK_IMPORTED_MODULE_0__math__["g" /* cos */])(x), + cy = Object(__WEBPACK_IMPORTED_MODULE_0__math__["g" /* cos */])(y), + k = scale(cx * cy); + return [ + k * cy * Object(__WEBPACK_IMPORTED_MODULE_0__math__["t" /* sin */])(x), + k * Object(__WEBPACK_IMPORTED_MODULE_0__math__["t" /* sin */])(y) + ]; + } +} + +function azimuthalInvert(angle) { + return function(x, y) { + var z = Object(__WEBPACK_IMPORTED_MODULE_0__math__["u" /* sqrt */])(x * x + y * y), + c = angle(z), + sc = Object(__WEBPACK_IMPORTED_MODULE_0__math__["t" /* sin */])(c), + cc = Object(__WEBPACK_IMPORTED_MODULE_0__math__["g" /* cos */])(c); + return [ + Object(__WEBPACK_IMPORTED_MODULE_0__math__["e" /* atan2 */])(x * sc, z * cc), + Object(__WEBPACK_IMPORTED_MODULE_0__math__["c" /* asin */])(z && y * sc / z) + ]; + } +} + + +/***/ }), +/* 34 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (x1 - x0) / parent.value; + + while (++i < n) { + node = nodes[i], node.y0 = y0, node.y1 = y1; + node.x0 = x0, node.x1 = x0 += node.value * k; + } +}); + + +/***/ }), +/* 35 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = linearish; +/* harmony export (immutable) */ __webpack_exports__["a"] = linear; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__continuous__ = __webpack_require__(54); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__tickFormat__ = __webpack_require__(483); + + + + + +function linearish(scale) { + var domain = scale.domain; + + scale.ticks = function(count) { + var d = domain(); + return Object(__WEBPACK_IMPORTED_MODULE_0_d3_array__["B" /* ticks */])(d[0], d[d.length - 1], count == null ? 10 : count); + }; + + scale.tickFormat = function(count, specifier) { + return Object(__WEBPACK_IMPORTED_MODULE_3__tickFormat__["a" /* default */])(domain(), count, specifier); + }; + + scale.nice = function(count) { + if (count == null) count = 10; + + var d = domain(), + i0 = 0, + i1 = d.length - 1, + start = d[i0], + stop = d[i1], + step; + + if (stop < start) { + step = start, start = stop, stop = step; + step = i0, i0 = i1, i1 = step; + } + + step = Object(__WEBPACK_IMPORTED_MODULE_0_d3_array__["z" /* tickIncrement */])(start, stop, count); + + if (step > 0) { + start = Math.floor(start / step) * step; + stop = Math.ceil(stop / step) * step; + step = Object(__WEBPACK_IMPORTED_MODULE_0_d3_array__["z" /* tickIncrement */])(start, stop, count); + } else if (step < 0) { + start = Math.ceil(start * step) / step; + stop = Math.floor(stop * step) / step; + step = Object(__WEBPACK_IMPORTED_MODULE_0_d3_array__["z" /* tickIncrement */])(start, stop, count); + } + + if (step > 0) { + d[i0] = Math.floor(start / step) * step; + d[i1] = Math.ceil(stop / step) * step; + domain(d); + } else if (step < 0) { + d[i0] = Math.ceil(start * step) / step; + d[i1] = Math.floor(stop * step) / step; + domain(d); + } + + return scale; + }; + + return scale; +} + +function linear() { + var scale = Object(__WEBPACK_IMPORTED_MODULE_2__continuous__["b" /* default */])(__WEBPACK_IMPORTED_MODULE_2__continuous__["c" /* deinterpolateLinear */], __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__["m" /* interpolateNumber */]); + + scale.copy = function() { + return Object(__WEBPACK_IMPORTED_MODULE_2__continuous__["a" /* copy */])(scale, linear()); + }; + + return linearish(scale); +} + + +/***/ }), +/* 36 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(s) { + return s.match(/.{6}/g).map(function(x) { + return "#" + x; + }); +}); + + +/***/ }), +/* 37 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return abs; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return atan2; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return cos; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return max; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return min; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "k", function() { return sin; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "l", function() { return sqrt; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return epsilon; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "j", function() { return pi; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return halfPi; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "m", function() { return tau; }); +/* harmony export (immutable) */ __webpack_exports__["b"] = acos; +/* harmony export (immutable) */ __webpack_exports__["c"] = asin; +var abs = Math.abs; +var atan2 = Math.atan2; +var cos = Math.cos; +var max = Math.max; +var min = Math.min; +var sin = Math.sin; +var sqrt = Math.sqrt; + +var epsilon = 1e-12; +var pi = Math.PI; +var halfPi = pi / 2; +var tau = 2 * pi; + +function acos(x) { + return x > 1 ? 0 : x < -1 ? pi : Math.acos(x); +} + +function asin(x) { + return x >= 1 ? halfPi : x <= -1 ? -halfPi : Math.asin(x); +} + + +/***/ }), +/* 38 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(series, order) { + if (!((n = series.length) > 1)) return; + for (var i = 1, j, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { + s0 = s1, s1 = series[order[i]]; + for (j = 0; j < m; ++j) { + s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1]; + } + } +}); + + +/***/ }), +/* 39 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(series) { + var n = series.length, o = new Array(n); + while (--n >= 0) o[n] = n; + return o; +}); + + +/***/ }), +/* 40 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return epsilon; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return epsilon2; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return beaches; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return cells; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return circles; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return edges; }); +/* harmony export (immutable) */ __webpack_exports__["d"] = Diagram; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Beach__ = __webpack_require__(542); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Cell__ = __webpack_require__(210); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__Circle__ = __webpack_require__(211); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__Edge__ = __webpack_require__(109); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__RedBlackTree__ = __webpack_require__(108); + + + + + + +var epsilon = 1e-6; +var epsilon2 = 1e-12; +var beaches; +var cells; +var circles; +var edges; + +function triangleArea(a, b, c) { + return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]); +} + +function lexicographic(a, b) { + return b[1] - a[1] + || b[0] - a[0]; +} + +function Diagram(sites, extent) { + var site = sites.sort(lexicographic).pop(), + x, + y, + circle; + + edges = []; + cells = new Array(sites.length); + beaches = new __WEBPACK_IMPORTED_MODULE_4__RedBlackTree__["b" /* default */]; + circles = new __WEBPACK_IMPORTED_MODULE_4__RedBlackTree__["b" /* default */]; + + while (true) { + circle = __WEBPACK_IMPORTED_MODULE_2__Circle__["c" /* firstCircle */]; + if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) { + if (site[0] !== x || site[1] !== y) { + Object(__WEBPACK_IMPORTED_MODULE_0__Beach__["a" /* addBeach */])(site); + x = site[0], y = site[1]; + } + site = sites.pop(); + } else if (circle) { + Object(__WEBPACK_IMPORTED_MODULE_0__Beach__["b" /* removeBeach */])(circle.arc); + } else { + break; + } + } + + Object(__WEBPACK_IMPORTED_MODULE_1__Cell__["d" /* sortCellHalfedges */])(); + + if (extent) { + var x0 = +extent[0][0], + y0 = +extent[0][1], + x1 = +extent[1][0], + y1 = +extent[1][1]; + Object(__WEBPACK_IMPORTED_MODULE_3__Edge__["a" /* clipEdges */])(x0, y0, x1, y1); + Object(__WEBPACK_IMPORTED_MODULE_1__Cell__["b" /* clipCells */])(x0, y0, x1, y1); + } + + this.edges = edges; + this.cells = cells; + + beaches = + circles = + edges = + cells = null; +} + +Diagram.prototype = { + constructor: Diagram, + + polygons: function() { + var edges = this.edges; + + return this.cells.map(function(cell) { + var polygon = cell.halfedges.map(function(i) { return Object(__WEBPACK_IMPORTED_MODULE_1__Cell__["a" /* cellHalfedgeStart */])(cell, edges[i]); }); + polygon.data = cell.site.data; + return polygon; + }); + }, + + triangles: function() { + var triangles = [], + edges = this.edges; + + this.cells.forEach(function(cell, i) { + if (!(m = (halfedges = cell.halfedges).length)) return; + var site = cell.site, + halfedges, + j = -1, + m, + s0, + e1 = edges[halfedges[m - 1]], + s1 = e1.left === site ? e1.right : e1.left; + + while (++j < m) { + s0 = s1; + e1 = edges[halfedges[j]]; + s1 = e1.left === site ? e1.right : e1.left; + if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) { + triangles.push([site.data, s0.data, s1.data]); + } + } + }); + + return triangles; + }, + + links: function() { + return this.edges.filter(function(edge) { + return edge.right; + }).map(function(edge) { + return { + source: edge.left.data, + target: edge.right.data + }; + }); + }, + + find: function(x, y, radius) { + var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell; + + // Use the previously-found cell, or start with an arbitrary one. + while (!(cell = that.cells[i1])) if (++i1 >= n) return null; + var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy; + + // Traverse the half-edges to find a closer cell, if any. + do { + cell = that.cells[i0 = i1], i1 = null; + cell.halfedges.forEach(function(e) { + var edge = that.edges[e], v = edge.left; + if ((v === cell.site || !v) && !(v = edge.right)) return; + var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy; + if (v2 < d2) d2 = v2, i1 = v.index; + }); + } while (i1 !== null); + + that._found = i0; + + return radius == null || d2 <= radius * radius ? cell.site : null; + } +} + + +/***/ }), +/* 41 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +/** + * Graphology Custom Errors + * ========================= + * + * Defining custom errors for ease of use & easy unit tests across + * implementations (normalized typology rather than relying on error + * messages to check whether the correct error was found). + */ +var GraphError = exports.GraphError = function (_Error) { + _inherits(GraphError, _Error); + + function GraphError(message, data) { + _classCallCheck(this, GraphError); + + var _this = _possibleConstructorReturn(this, _Error.call(this)); + + _this.name = 'GraphError'; + _this.message = message || ''; + _this.data = data || {}; + return _this; + } + + return GraphError; +}(Error); + +var InvalidArgumentsGraphError = exports.InvalidArgumentsGraphError = function (_GraphError) { + _inherits(InvalidArgumentsGraphError, _GraphError); + + function InvalidArgumentsGraphError(message, data) { + _classCallCheck(this, InvalidArgumentsGraphError); + + var _this2 = _possibleConstructorReturn(this, _GraphError.call(this, message, data)); + + _this2.name = 'InvalidArgumentsGraphError'; + + // This is V8 specific to enhance stack readability + if (typeof Error.captureStackTrace === 'function') Error.captureStackTrace(_this2, InvalidArgumentsGraphError.prototype.constructor); + return _this2; + } + + return InvalidArgumentsGraphError; +}(GraphError); + +var NotFoundGraphError = exports.NotFoundGraphError = function (_GraphError2) { + _inherits(NotFoundGraphError, _GraphError2); + + function NotFoundGraphError(message, data) { + _classCallCheck(this, NotFoundGraphError); + + var _this3 = _possibleConstructorReturn(this, _GraphError2.call(this, message, data)); + + _this3.name = 'NotFoundGraphError'; + + // This is V8 specific to enhance stack readability + if (typeof Error.captureStackTrace === 'function') Error.captureStackTrace(_this3, NotFoundGraphError.prototype.constructor); + return _this3; + } + + return NotFoundGraphError; +}(GraphError); + +var UsageGraphError = exports.UsageGraphError = function (_GraphError3) { + _inherits(UsageGraphError, _GraphError3); + + function UsageGraphError(message, data) { + _classCallCheck(this, UsageGraphError); + + var _this4 = _possibleConstructorReturn(this, _GraphError3.call(this, message, data)); + + _this4.name = 'UsageGraphError'; + + // This is V8 specific to enhance stack readability + if (typeof Error.captureStackTrace === 'function') Error.captureStackTrace(_this4, UsageGraphError.prototype.constructor); + return _this4; + } + + return UsageGraphError; +}(GraphError); + +/***/ }), +/* 42 */ +/***/ (function(module, exports, __webpack_require__) { + +var apply = __webpack_require__(225), + baseRest = __webpack_require__(119), + customDefaultsMerge = __webpack_require__(626), + mergeWith = __webpack_require__(643); + +/** + * This method is like `_.defaults` except that it recursively assigns + * default properties. + * + * **Note:** This method mutates `object`. + * + * @static + * @memberOf _ + * @since 3.10.0 + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaults + * @example + * + * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); + * // => { 'a': { 'b': 2, 'c': 3 } } + */ +var defaultsDeep = baseRest(function(args) { + args.push(undefined, customDefaultsMerge); + return apply(mergeWith, undefined, args); +}); + +module.exports = defaultsDeep; + + +/***/ }), +/* 43 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__namespace__ = __webpack_require__(72); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__namespaces__ = __webpack_require__(73); + + + +function creatorInherit(name) { + return function() { + var document = this.ownerDocument, + uri = this.namespaceURI; + return uri === __WEBPACK_IMPORTED_MODULE_1__namespaces__["b" /* xhtml */] && document.documentElement.namespaceURI === __WEBPACK_IMPORTED_MODULE_1__namespaces__["b" /* xhtml */] + ? document.createElement(name) + : document.createElementNS(uri, name); + }; +} + +function creatorFixed(fullname) { + return function() { + return this.ownerDocument.createElementNS(fullname.space, fullname.local); + }; +} + +/* harmony default export */ __webpack_exports__["a"] = (function(name) { + var fullname = Object(__WEBPACK_IMPORTED_MODULE_0__namespace__["a" /* default */])(name); + return (fullname.local + ? creatorFixed + : creatorInherit)(fullname); +}); + + +/***/ }), +/* 44 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(node, event) { + var svg = node.ownerSVGElement || node; + + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + point.x = event.clientX, point.y = event.clientY; + point = point.matrixTransform(node.getScreenCTM().inverse()); + return [point.x, point.y]; + } + + var rect = node.getBoundingClientRect(); + return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; +}); + + +/***/ }), +/* 45 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(a, b) { + return a = +a, b -= a, function(t) { + return a + b * t; + }; +}); + + +/***/ }), +/* 46 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_timer__ = __webpack_require__(83); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_0__src_timer__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_0__src_timer__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return __WEBPACK_IMPORTED_MODULE_0__src_timer__["d"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_timeout__ = __webpack_require__(332); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_1__src_timeout__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_interval__ = __webpack_require__(333); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_2__src_interval__["a"]; }); + + + + + + + +/***/ }), +/* 47 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = tweenValue; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__schedule__ = __webpack_require__(8); + + +function tweenRemove(id, name) { + var tween0, tween1; + return function() { + var schedule = Object(__WEBPACK_IMPORTED_MODULE_0__schedule__["h" /* set */])(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = tween0 = tween; + for (var i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1 = tween1.slice(); + tween1.splice(i, 1); + break; + } + } + } + + schedule.tween = tween1; + }; +} + +function tweenFunction(id, name, value) { + var tween0, tween1; + if (typeof value !== "function") throw new Error; + return function() { + var schedule = Object(__WEBPACK_IMPORTED_MODULE_0__schedule__["h" /* set */])(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = (tween0 = tween).slice(); + for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1[i] = t; + break; + } + } + if (i === n) tween1.push(t); + } + + schedule.tween = tween1; + }; +} + +/* harmony default export */ __webpack_exports__["a"] = (function(name, value) { + var id = this._id; + + name += ""; + + if (arguments.length < 2) { + var tween = Object(__WEBPACK_IMPORTED_MODULE_0__schedule__["f" /* get */])(this.node(), id).tween; + for (var i = 0, n = tween.length, t; i < n; ++i) { + if ((t = tween[i]).name === name) { + return t.value; + } + } + return null; + } + + return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); +}); + +function tweenValue(transition, name, value) { + var id = transition._id; + + transition.each(function() { + var schedule = Object(__WEBPACK_IMPORTED_MODULE_0__schedule__["h" /* set */])(this, id); + (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); + }); + + return function(node) { + return Object(__WEBPACK_IMPORTED_MODULE_0__schedule__["f" /* get */])(node, id).value[name]; + }; +} + + +/***/ }), +/* 48 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__formatDecimal__ = __webpack_require__(91); + + +/* harmony default export */ __webpack_exports__["a"] = (function(x) { + return x = Object(__WEBPACK_IMPORTED_MODULE_0__formatDecimal__["a" /* default */])(Math.abs(x)), x ? x[1] : NaN; +}); + + +/***/ }), +/* 49 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = rotateRadians; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__compose__ = __webpack_require__(170); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math__ = __webpack_require__(0); + + + +function rotationIdentity(lambda, phi) { + return [lambda > __WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */] ? lambda - __WEBPACK_IMPORTED_MODULE_1__math__["w" /* tau */] : lambda < -__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */] ? lambda + __WEBPACK_IMPORTED_MODULE_1__math__["w" /* tau */] : lambda, phi]; +} + +rotationIdentity.invert = rotationIdentity; + +function rotateRadians(deltaLambda, deltaPhi, deltaGamma) { + return (deltaLambda %= __WEBPACK_IMPORTED_MODULE_1__math__["w" /* tau */]) ? (deltaPhi || deltaGamma ? Object(__WEBPACK_IMPORTED_MODULE_0__compose__["a" /* default */])(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) + : rotationLambda(deltaLambda)) + : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) + : rotationIdentity); +} + +function forwardRotationLambda(deltaLambda) { + return function(lambda, phi) { + return lambda += deltaLambda, [lambda > __WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */] ? lambda - __WEBPACK_IMPORTED_MODULE_1__math__["w" /* tau */] : lambda < -__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */] ? lambda + __WEBPACK_IMPORTED_MODULE_1__math__["w" /* tau */] : lambda, phi]; + }; +} + +function rotationLambda(deltaLambda) { + var rotation = forwardRotationLambda(deltaLambda); + rotation.invert = forwardRotationLambda(-deltaLambda); + return rotation; +} + +function rotationPhiGamma(deltaPhi, deltaGamma) { + var cosDeltaPhi = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(deltaPhi), + sinDeltaPhi = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(deltaPhi), + cosDeltaGamma = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(deltaGamma), + sinDeltaGamma = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(deltaGamma); + + function rotation(lambda, phi) { + var cosPhi = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(phi), + x = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(lambda) * cosPhi, + y = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(lambda) * cosPhi, + z = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(phi), + k = z * cosDeltaPhi + x * sinDeltaPhi; + return [ + Object(__WEBPACK_IMPORTED_MODULE_1__math__["e" /* atan2 */])(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), + Object(__WEBPACK_IMPORTED_MODULE_1__math__["c" /* asin */])(k * cosDeltaGamma + y * sinDeltaGamma) + ]; + } + + rotation.invert = function(lambda, phi) { + var cosPhi = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(phi), + x = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(lambda) * cosPhi, + y = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(lambda) * cosPhi, + z = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(phi), + k = z * cosDeltaGamma - y * sinDeltaGamma; + return [ + Object(__WEBPACK_IMPORTED_MODULE_1__math__["e" /* atan2 */])(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), + Object(__WEBPACK_IMPORTED_MODULE_1__math__["c" /* asin */])(k * cosDeltaPhi - x * sinDeltaPhi) + ]; + }; + + return rotation; +} + +/* harmony default export */ __webpack_exports__["a"] = (function(rotate) { + rotate = rotateRadians(rotate[0] * __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */], rotate[1] * __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */], rotate.length > 2 ? rotate[2] * __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */] : 0); + + function forward(coordinates) { + coordinates = rotate(coordinates[0] * __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */], coordinates[1] * __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */]); + return coordinates[0] *= __WEBPACK_IMPORTED_MODULE_1__math__["h" /* degrees */], coordinates[1] *= __WEBPACK_IMPORTED_MODULE_1__math__["h" /* degrees */], coordinates; + } + + forward.invert = function(coordinates) { + coordinates = rotate.invert(coordinates[0] * __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */], coordinates[1] * __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */]); + return coordinates[0] *= __WEBPACK_IMPORTED_MODULE_1__math__["h" /* degrees */], coordinates[1] *= __WEBPACK_IMPORTED_MODULE_1__math__["h" /* degrees */], coordinates; + }; + + return forward; +}); + + +/***/ }), +/* 50 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = clipRectangle; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__buffer__ = __webpack_require__(173); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__line__ = __webpack_require__(413); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__rejoin__ = __webpack_require__(174); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_d3_array__ = __webpack_require__(4); + + + + + + +var clipMax = 1e9, clipMin = -clipMax; + +// TODO Use d3-polygon’s polygonContains here for the ring check? +// TODO Eliminate duplicate buffering in clipBuffer and polygon.push? + +function clipRectangle(x0, y0, x1, y1) { + + function visible(x, y) { + return x0 <= x && x <= x1 && y0 <= y && y <= y1; + } + + function interpolate(from, to, direction, stream) { + var a = 0, a1 = 0; + if (from == null + || (a = corner(from, direction)) !== (a1 = corner(to, direction)) + || comparePoint(from, to) < 0 ^ direction > 0) { + do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); + while ((a = (a + direction + 4) % 4) !== a1); + } else { + stream.point(to[0], to[1]); + } + } + + function corner(p, direction) { + return Object(__WEBPACK_IMPORTED_MODULE_0__math__["a" /* abs */])(p[0] - x0) < __WEBPACK_IMPORTED_MODULE_0__math__["i" /* epsilon */] ? direction > 0 ? 0 : 3 + : Object(__WEBPACK_IMPORTED_MODULE_0__math__["a" /* abs */])(p[0] - x1) < __WEBPACK_IMPORTED_MODULE_0__math__["i" /* epsilon */] ? direction > 0 ? 2 : 1 + : Object(__WEBPACK_IMPORTED_MODULE_0__math__["a" /* abs */])(p[1] - y0) < __WEBPACK_IMPORTED_MODULE_0__math__["i" /* epsilon */] ? direction > 0 ? 1 : 0 + : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon + } + + function compareIntersection(a, b) { + return comparePoint(a.x, b.x); + } + + function comparePoint(a, b) { + var ca = corner(a, 1), + cb = corner(b, 1); + return ca !== cb ? ca - cb + : ca === 0 ? b[1] - a[1] + : ca === 1 ? a[0] - b[0] + : ca === 2 ? a[1] - b[1] + : b[0] - a[0]; + } + + return function(stream) { + var activeStream = stream, + bufferStream = Object(__WEBPACK_IMPORTED_MODULE_1__buffer__["a" /* default */])(), + segments, + polygon, + ring, + x__, y__, v__, // first point + x_, y_, v_, // previous point + first, + clean; + + var clipStream = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: polygonStart, + polygonEnd: polygonEnd + }; + + function point(x, y) { + if (visible(x, y)) activeStream.point(x, y); + } + + function polygonInside() { + var winding = 0; + + for (var i = 0, n = polygon.length; i < n; ++i) { + for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) { + a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1]; + if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; } + else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; } + } + } + + return winding; + } + + // Buffer geometry within a polygon and then clip it en masse. + function polygonStart() { + activeStream = bufferStream, segments = [], polygon = [], clean = true; + } + + function polygonEnd() { + var startInside = polygonInside(), + cleanInside = clean && startInside, + visible = (segments = Object(__WEBPACK_IMPORTED_MODULE_4_d3_array__["n" /* merge */])(segments)).length; + if (cleanInside || visible) { + stream.polygonStart(); + if (cleanInside) { + stream.lineStart(); + interpolate(null, null, 1, stream); + stream.lineEnd(); + } + if (visible) { + Object(__WEBPACK_IMPORTED_MODULE_3__rejoin__["a" /* default */])(segments, compareIntersection, startInside, interpolate, stream); + } + stream.polygonEnd(); + } + activeStream = stream, segments = polygon = ring = null; + } + + function lineStart() { + clipStream.point = linePoint; + if (polygon) polygon.push(ring = []); + first = true; + v_ = false; + x_ = y_ = NaN; + } + + // TODO rather than special-case polygons, simply handle them separately. + // Ideally, coincident intersection points should be jittered to avoid + // clipping issues. + function lineEnd() { + if (segments) { + linePoint(x__, y__); + if (v__ && v_) bufferStream.rejoin(); + segments.push(bufferStream.result()); + } + clipStream.point = point; + if (v_) activeStream.lineEnd(); + } + + function linePoint(x, y) { + var v = visible(x, y); + if (polygon) ring.push([x, y]); + if (first) { + x__ = x, y__ = y, v__ = v; + first = false; + if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + } + } else { + if (v && v_) activeStream.point(x, y); + else { + var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], + b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))]; + if (Object(__WEBPACK_IMPORTED_MODULE_2__line__["a" /* default */])(a, b, x0, y0, x1, y1)) { + if (!v_) { + activeStream.lineStart(); + activeStream.point(a[0], a[1]); + } + activeStream.point(b[0], b[1]); + if (!v) activeStream.lineEnd(); + clean = false; + } else if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + clean = false; + } + } + } + x_ = x, y_ = y, v_ = v; + } + + return clipStream; + }; +} + + +/***/ }), +/* 51 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = transformer; +/* harmony default export */ __webpack_exports__["a"] = (function(methods) { + return { + stream: transformer(methods) + }; +}); + +function transformer(methods) { + return function(stream) { + var s = new TransformStream; + for (var key in methods) s[key] = methods[key]; + s.stream = stream; + return s; + }; +} + +function TransformStream() {} + +TransformStream.prototype = { + constructor: TransformStream, + point: function(x, y) { this.stream.point(x, y); }, + sphere: function() { this.stream.sphere(); }, + lineStart: function() { this.stream.lineStart(); }, + lineEnd: function() { this.stream.lineEnd(); }, + polygonStart: function() { this.stream.polygonStart(); }, + polygonEnd: function() { this.stream.polygonEnd(); } +}; + + +/***/ }), +/* 52 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (y1 - y0) / parent.value; + + while (++i < n) { + node = nodes[i], node.x0 = x0, node.x1 = x1; + node.y0 = y0, node.y1 = y0 += node.value * k; + } +}); + + +/***/ }), +/* 53 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__request__ = __webpack_require__(100); + + +/* harmony default export */ __webpack_exports__["a"] = (function(defaultMimeType, response) { + return function(url, callback) { + var r = Object(__WEBPACK_IMPORTED_MODULE_0__request__["a" /* default */])(url).mimeType(defaultMimeType).response(response); + if (callback != null) { + if (typeof callback !== "function") throw new Error("invalid callback: " + callback); + return r.get(callback); + } + return r; + }; +}); + + +/***/ }), +/* 54 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["c"] = deinterpolateLinear; +/* harmony export (immutable) */ __webpack_exports__["a"] = copy; +/* harmony export (immutable) */ __webpack_exports__["b"] = continuous; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__array__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__constant__ = __webpack_require__(101); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__number__ = __webpack_require__(191); + + + + + + +var unit = [0, 1]; + +function deinterpolateLinear(a, b) { + return (b -= (a = +a)) + ? function(x) { return (x - a) / b; } + : Object(__WEBPACK_IMPORTED_MODULE_3__constant__["a" /* default */])(b); +} + +function deinterpolateClamp(deinterpolate) { + return function(a, b) { + var d = deinterpolate(a = +a, b = +b); + return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); }; + }; +} + +function reinterpolateClamp(reinterpolate) { + return function(a, b) { + var r = reinterpolate(a = +a, b = +b); + return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); }; + }; +} + +function bimap(domain, range, deinterpolate, reinterpolate) { + var d0 = domain[0], d1 = domain[1], r0 = range[0], r1 = range[1]; + if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0); + else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1); + return function(x) { return r0(d0(x)); }; +} + +function polymap(domain, range, deinterpolate, reinterpolate) { + var j = Math.min(domain.length, range.length) - 1, + d = new Array(j), + r = new Array(j), + i = -1; + + // Reverse descending domains. + if (domain[j] < domain[0]) { + domain = domain.slice().reverse(); + range = range.slice().reverse(); + } + + while (++i < j) { + d[i] = deinterpolate(domain[i], domain[i + 1]); + r[i] = reinterpolate(range[i], range[i + 1]); + } + + return function(x) { + var i = Object(__WEBPACK_IMPORTED_MODULE_0_d3_array__["b" /* bisect */])(domain, x, 1, j) - 1; + return r[i](d[i](x)); + }; +} + +function copy(source, target) { + return target + .domain(source.domain()) + .range(source.range()) + .interpolate(source.interpolate()) + .clamp(source.clamp()); +} + +// deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1]. +// reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b]. +function continuous(deinterpolate, reinterpolate) { + var domain = unit, + range = unit, + interpolate = __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__["a" /* interpolate */], + clamp = false, + piecewise, + output, + input; + + function rescale() { + piecewise = Math.min(domain.length, range.length) > 2 ? polymap : bimap; + output = input = null; + return scale; + } + + function scale(x) { + return (output || (output = piecewise(domain, range, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate)))(+x); + } + + scale.invert = function(y) { + return (input || (input = piecewise(range, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y); + }; + + scale.domain = function(_) { + return arguments.length ? (domain = __WEBPACK_IMPORTED_MODULE_2__array__["a" /* map */].call(_, __WEBPACK_IMPORTED_MODULE_4__number__["a" /* default */]), rescale()) : domain.slice(); + }; + + scale.range = function(_) { + return arguments.length ? (range = __WEBPACK_IMPORTED_MODULE_2__array__["b" /* slice */].call(_), rescale()) : range.slice(); + }; + + scale.rangeRound = function(_) { + return range = __WEBPACK_IMPORTED_MODULE_2__array__["b" /* slice */].call(_), interpolate = __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__["r" /* interpolateRound */], rescale(); + }; + + scale.clamp = function(_) { + return arguments.length ? (clamp = !!_, rescale()) : clamp; + }; + + scale.interpolate = function(_) { + return arguments.length ? (interpolate = _, rescale()) : interpolate; + }; + + return rescale(); +} + + +/***/ }), +/* 55 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_interval__ = __webpack_require__(3); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return __WEBPACK_IMPORTED_MODULE_0__src_interval__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_millisecond__ = __webpack_require__(489); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return __WEBPACK_IMPORTED_MODULE_1__src_millisecond__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return __WEBPACK_IMPORTED_MODULE_1__src_millisecond__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "L", function() { return __WEBPACK_IMPORTED_MODULE_1__src_millisecond__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "M", function() { return __WEBPACK_IMPORTED_MODULE_1__src_millisecond__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_second__ = __webpack_require__(490); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "r", function() { return __WEBPACK_IMPORTED_MODULE_2__src_second__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "s", function() { return __WEBPACK_IMPORTED_MODULE_2__src_second__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "V", function() { return __WEBPACK_IMPORTED_MODULE_2__src_second__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "W", function() { return __WEBPACK_IMPORTED_MODULE_2__src_second__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__src_minute__ = __webpack_require__(491); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "j", function() { return __WEBPACK_IMPORTED_MODULE_3__src_minute__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "k", function() { return __WEBPACK_IMPORTED_MODULE_3__src_minute__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__src_hour__ = __webpack_require__(492); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return __WEBPACK_IMPORTED_MODULE_4__src_hour__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return __WEBPACK_IMPORTED_MODULE_4__src_hour__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__src_day__ = __webpack_require__(493); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_5__src_day__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_5__src_day__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__src_week__ = __webpack_require__(494); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "B", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["g"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "C", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["h"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "t", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["g"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "u", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["h"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "l", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "m", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["d"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "x", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["k"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "y", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["l"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "z", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["m"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "A", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["n"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "v", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["i"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "w", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["j"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "p", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["e"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "q", function() { return __WEBPACK_IMPORTED_MODULE_6__src_week__["f"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__src_month__ = __webpack_require__(495); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "n", function() { return __WEBPACK_IMPORTED_MODULE_7__src_month__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "o", function() { return __WEBPACK_IMPORTED_MODULE_7__src_month__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__src_year__ = __webpack_require__(496); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "D", function() { return __WEBPACK_IMPORTED_MODULE_8__src_year__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "E", function() { return __WEBPACK_IMPORTED_MODULE_8__src_year__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__src_utcMinute__ = __webpack_require__(497); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "N", function() { return __WEBPACK_IMPORTED_MODULE_9__src_utcMinute__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "O", function() { return __WEBPACK_IMPORTED_MODULE_9__src_utcMinute__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__src_utcHour__ = __webpack_require__(498); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "J", function() { return __WEBPACK_IMPORTED_MODULE_10__src_utcHour__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "K", function() { return __WEBPACK_IMPORTED_MODULE_10__src_utcHour__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__src_utcDay__ = __webpack_require__(499); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "F", function() { return __WEBPACK_IMPORTED_MODULE_11__src_utcDay__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "G", function() { return __WEBPACK_IMPORTED_MODULE_11__src_utcDay__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__ = __webpack_require__(500); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "_5", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["g"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "_6", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["h"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "X", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["g"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "Y", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["h"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "P", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "Q", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["d"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "_1", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["k"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "_2", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["l"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "_3", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["m"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "_4", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["n"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "Z", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["i"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "_0", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["j"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "H", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "I", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "T", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["e"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "U", function() { return __WEBPACK_IMPORTED_MODULE_12__src_utcWeek__["f"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__src_utcMonth__ = __webpack_require__(501); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "R", function() { return __WEBPACK_IMPORTED_MODULE_13__src_utcMonth__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "S", function() { return __WEBPACK_IMPORTED_MODULE_13__src_utcMonth__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_14__src_utcYear__ = __webpack_require__(502); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "_7", function() { return __WEBPACK_IMPORTED_MODULE_14__src_utcYear__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "_8", function() { return __WEBPACK_IMPORTED_MODULE_14__src_utcYear__["b"]; }); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/***/ }), +/* 56 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +function Linear(context) { + this._context = context; +} + +Linear.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; // proceed + default: this._context.lineTo(x, y); break; + } + } +}; + +/* harmony default export */ __webpack_exports__["a"] = (function(context) { + return new Linear(context); +}); + + +/***/ }), +/* 57 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function() {}); + + +/***/ }), +/* 58 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["c"] = point; +/* harmony export (immutable) */ __webpack_exports__["a"] = Basis; +function point(that, x, y) { + that._context.bezierCurveTo( + (2 * that._x0 + that._x1) / 3, + (2 * that._y0 + that._y1) / 3, + (that._x0 + 2 * that._x1) / 3, + (that._y0 + 2 * that._y1) / 3, + (that._x0 + 4 * that._x1 + x) / 6, + (that._y0 + 4 * that._y1 + y) / 6 + ); +} + +function Basis(context) { + this._context = context; +} + +Basis.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 3: point(this, this._x1, this._y1); // proceed + case 2: this._context.lineTo(this._x1, this._y1); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed + default: point(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } +}; + +/* harmony default export */ __webpack_exports__["b"] = (function(context) { + return new Basis(context); +}); + + +/***/ }), +/* 59 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["c"] = point; +/* harmony export (immutable) */ __webpack_exports__["a"] = Cardinal; +function point(that, x, y) { + that._context.bezierCurveTo( + that._x1 + that._k * (that._x2 - that._x0), + that._y1 + that._k * (that._y2 - that._y0), + that._x2 + that._k * (that._x1 - x), + that._y2 + that._k * (that._y1 - y), + that._x2, + that._y2 + ); +} + +function Cardinal(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +Cardinal.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x2, this._y2); break; + case 3: point(this, this._x1, this._y1); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; this._x1 = x, this._y1 = y; break; + case 2: this._point = 3; // proceed + default: point(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +/* harmony default export */ __webpack_exports__["b"] = ((function custom(tension) { + + function cardinal(context) { + return new Cardinal(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +})(0)); + + +/***/ }), +/* 60 */ +/***/ (function(module, exports) { + +var g; + +// This works in non-strict mode +g = (function() { + return this; +})(); + +try { + // This works if eval is allowed (see CSP) + g = g || Function("return this")() || (1,eval)("this"); +} catch(e) { + // This works if the window reference is available + if(typeof window === "object") + g = window; +} + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + +module.exports = g; + + +/***/ }), +/* 61 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +exports.assign = assign; +exports.getMatchingEdge = getMatchingEdge; +exports.isBunch = isBunch; +exports.isGraph = isGraph; +exports.isPlainObject = isPlainObject; +exports.overBunch = overBunch; +exports.prettyPrint = prettyPrint; +exports.privateProperty = privateProperty; +exports.readOnlyProperty = readOnlyProperty; +exports.incrementalId = incrementalId; +/** + * Graphology Utilities + * ===================== + * + * Collection of helpful functions used by the implementation. + */ + +/** + * Very simple Object.assign-like function. + * + * @param {object} target - First object. + * @param {object} [...objects] - Objects to merge. + * @return {object} + */ +function assign() { + var target = arguments[0] || {}; + + for (var i = 1, l = arguments.length; i < l; i++) { + if (!arguments[i]) continue; + + for (var k in arguments[i]) { + target[k] = arguments[i][k]; + } + } + + return target; +} + +/** + * Function returning the first matching edge for given path. + * Note: this function does not check the existence of source & target. This + * must be performed by the caller. + * + * @param {Graph} graph - Target graph. + * @param {any} source - Source node. + * @param {any} target - Target node. + * @param {string} type - Type of the edge (mixed, directed or undirected). + * @return {string|null} + */ +function getMatchingEdge(graph, source, target, type) { + var sourceData = graph._nodes.get(source); + + var edge = null; + + if (type === 'mixed') { + edge = sourceData.out && sourceData.out[target] || sourceData.undirected && sourceData.undirected[target]; + } else if (type === 'directed') { + edge = sourceData.out && sourceData.out[target]; + } else { + edge = sourceData.undirected && sourceData.undirected[target]; + } + + return edge; +} + +/** + * Checks whether the given value is a potential bunch. + * + * @param {mixed} value - Target value. + * @return {boolean} + */ +function isBunch(value) { + return !!value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && (Array.isArray(value) || typeof Map === 'function' && value instanceof Map || typeof Set === 'function' && value instanceof Set || !(value instanceof Date) && !(value instanceof RegExp)); +} + +/** + * Checks whether the given value is a Graph implementation instance. + * + * @param {mixed} value - Target value. + * @return {boolean} + */ +function isGraph(value) { + return value !== null && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && typeof value.addUndirectedEdgeWithKey === 'function' && typeof value.dropNode === 'function'; +} + +/** + * Checks whether the given value is a plain object. + * + * @param {mixed} value - Target value. + * @return {boolean} + */ +function isPlainObject(value) { + return (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value !== null && value.constructor === Object; +} + +/** + * Iterates over the provided bunch. + * + * @param {object} bunch - Target bunch. + * @param {function} callback - Function to call. + */ +function overBunch(bunch, callback) { + + // Array iteration + if (Array.isArray(bunch)) { + for (var i = 0, l = bunch.length; i < l; i++) { + callback(bunch[i], null); + } + } + + // Map & Set iteration + else if (typeof bunch.forEach === 'function') { + var iterator = bunch.entries(); + + var step = void 0; + + while (step = iterator.next()) { + var _step = step, + value = _step.value, + done = _step.done; + + + if (done) break; + + var k = value[0], + v = value[1]; + + + if (v === k) callback(v, null);else callback(k, v); + } + } + + // Plain object iteration + else { + for (var key in bunch) { + var attributes = bunch[key]; + + callback(key, attributes); + } + } +} + +/** + * Pretty prints the given integer. + * + * @param {number} integer - Target integer. + * @return {string} - The pretty string. + */ +function prettyPrint(integer) { + var string = '' + integer; + + var prettyString = ''; + + for (var i = 0, l = string.length; i < l; i++) { + var j = l - i - 1; + + prettyString = string[j] + prettyString; + + if (!((i - 2) % 3) && i !== l - 1) prettyString = ',' + prettyString; + } + + return prettyString; +} + +/** + * Creates a "private" property for the given member name by concealing it + * using the `enumerable` option. + * + * @param {object} target - Target object. + * @param {string} name - Member name. + */ +function privateProperty(target, name, value) { + Object.defineProperty(target, name, { + enumerable: false, + configurable: false, + writable: true, + value: value + }); +} + +/** + * Creates a read-only property for the given member name & the given getter. + * + * @param {object} target - Target object. + * @param {string} name - Member name. + * @param {mixed} value - The attached getter or fixed value. + */ +function readOnlyProperty(target, name, value) { + var descriptor = { + enumerable: true, + configurable: true + }; + + if (typeof value === 'function') { + descriptor.get = value; + } else { + descriptor.value = value; + descriptor.writable = false; + } + + Object.defineProperty(target, name, descriptor); +} + +/** + * Creates a function generating incremental ids for edges. + * + * @return {function} + */ +function incrementalId() { + var i = 0; + + return function () { + return '_geid' + i++ + '_'; + }; +} + +/***/ }), +/* 62 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +var R = typeof Reflect === 'object' ? Reflect : null +var ReflectApply = R && typeof R.apply === 'function' + ? R.apply + : function ReflectApply(target, receiver, args) { + return Function.prototype.apply.call(target, receiver, args); + } + +var ReflectOwnKeys +if (R && typeof R.ownKeys === 'function') { + ReflectOwnKeys = R.ownKeys +} else if (Object.getOwnPropertySymbols) { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target) + .concat(Object.getOwnPropertySymbols(target)); + }; +} else { + ReflectOwnKeys = function ReflectOwnKeys(target) { + return Object.getOwnPropertyNames(target); + }; +} + +function ProcessEmitWarning(warning) { + if (console && console.warn) console.warn(warning); +} + +var NumberIsNaN = Number.isNaN || function NumberIsNaN(value) { + return value !== value; +} + +function EventEmitter() { + EventEmitter.init.call(this); +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._eventsCount = 0; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +var defaultMaxListeners = 10; + +Object.defineProperty(EventEmitter, 'defaultMaxListeners', { + enumerable: true, + get: function() { + return defaultMaxListeners; + }, + set: function(arg) { + if (typeof arg !== 'number' || arg < 0 || NumberIsNaN(arg)) { + throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received ' + arg + '.'); + } + defaultMaxListeners = arg; + } +}); + +EventEmitter.init = function() { + + if (this._events === undefined || + this._events === Object.getPrototypeOf(this)._events) { + this._events = Object.create(null); + this._eventsCount = 0; + } + + this._maxListeners = this._maxListeners || undefined; +}; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { + if (typeof n !== 'number' || n < 0 || NumberIsNaN(n)) { + throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.'); + } + this._maxListeners = n; + return this; +}; + +function $getMaxListeners(that) { + if (that._maxListeners === undefined) + return EventEmitter.defaultMaxListeners; + return that._maxListeners; +} + +EventEmitter.prototype.getMaxListeners = function getMaxListeners() { + return $getMaxListeners(this); +}; + +EventEmitter.prototype.emit = function emit(type) { + var args = []; + for (var i = 1; i < arguments.length; i++) args.push(arguments[i]); + var doError = (type === 'error'); + + var events = this._events; + if (events !== undefined) + doError = (doError && events.error === undefined); + else if (!doError) + return false; + + // If there is no 'error' event listener then throw. + if (doError) { + var er; + if (args.length > 0) + er = args[0]; + if (er instanceof Error) { + // Note: The comments on the `throw` lines are intentional, they show + // up in Node's output if this results in an unhandled exception. + throw er; // Unhandled 'error' event + } + // At least give some kind of context to the user + var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : '')); + err.context = er; + throw err; // Unhandled 'error' event + } + + var handler = events[type]; + + if (handler === undefined) + return false; + + if (typeof handler === 'function') { + ReflectApply(handler, this, args); + } else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + ReflectApply(listeners[i], this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + if (typeof listener !== 'function') { + throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); + } + + events = target._events; + if (events === undefined) { + events = target._events = Object.create(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener !== undefined) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (existing === undefined) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + // If we've already got an array, just append. + } else if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + + // Check for listener leak + m = $getMaxListeners(target); + if (m > 0 && existing.length > m && !existing.warned) { + existing.warned = true; + // No error code for this since it is a Warning + // eslint-disable-next-line no-restricted-syntax + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' ' + String(type) + ' listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + ProcessEmitWarning(w); + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + var args = []; + for (var i = 0; i < arguments.length; i++) args.push(arguments[i]); + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + ReflectApply(this.listener, this.target, args); + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = onceWrapper.bind(state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + if (typeof listener !== 'function') { + throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); + } + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + if (typeof listener !== 'function') { + throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); + } + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + if (typeof listener !== 'function') { + throw new TypeError('The "listener" argument must be of type Function. Received type ' + typeof listener); + } + + events = this._events; + if (events === undefined) + return this; + + list = events[type]; + if (list === undefined) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else { + spliceOne(list, position); + } + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener !== undefined) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (events === undefined) + return this; + + // not listening for removeListener, no need to emit + if (events.removeListener === undefined) { + if (arguments.length === 0) { + this._events = Object.create(null); + this._eventsCount = 0; + } else if (events[type] !== undefined) { + if (--this._eventsCount === 0) + this._events = Object.create(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = Object.keys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = Object.create(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners !== undefined) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (events === undefined) + return []; + + var evlistener = events[type]; + if (evlistener === undefined) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? + unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events !== undefined) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener !== undefined) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; +}; + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function spliceOne(list, index) { + for (; index + 1 < list.length; index++) + list[index] = list[index + 1]; + list.pop(); +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + + +/***/ }), +/* 63 */ +/***/ (function(module, exports, __webpack_require__) { + +var listCacheClear = __webpack_require__(562), + listCacheDelete = __webpack_require__(563), + listCacheGet = __webpack_require__(564), + listCacheHas = __webpack_require__(565), + listCacheSet = __webpack_require__(566); + +/** + * Creates an list cache object. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function ListCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `ListCache`. +ListCache.prototype.clear = listCacheClear; +ListCache.prototype['delete'] = listCacheDelete; +ListCache.prototype.get = listCacheGet; +ListCache.prototype.has = listCacheHas; +ListCache.prototype.set = listCacheSet; + +module.exports = ListCache; + + +/***/ }), +/* 64 */ +/***/ (function(module, exports, __webpack_require__) { + +var eq = __webpack_require__(27); + +/** + * Gets the index at which the `key` is found in `array` of key-value pairs. + * + * @private + * @param {Array} array The array to inspect. + * @param {*} key The key to search for. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function assocIndexOf(array, key) { + var length = array.length; + while (length--) { + if (eq(array[length][0], key)) { + return length; + } + } + return -1; +} + +module.exports = assocIndexOf; + + +/***/ }), +/* 65 */ +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(21); + +/* Built-in method references that are verified to be native. */ +var nativeCreate = getNative(Object, 'create'); + +module.exports = nativeCreate; + + +/***/ }), +/* 66 */ +/***/ (function(module, exports, __webpack_require__) { + +var isKeyable = __webpack_require__(586); + +/** + * Gets the data for `map`. + * + * @private + * @param {Object} map The map to query. + * @param {string} key The reference key. + * @returns {*} Returns the map data. + */ +function getMapData(map, key) { + var data = map.__data__; + return isKeyable(key) + ? data[typeof key == 'string' ? 'string' : 'hash'] + : data.map; +} + +module.exports = getMapData; + + +/***/ }), +/* 67 */ +/***/ (function(module, exports) { + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; + +module.exports = isArray; + + +/***/ }), +/* 68 */ +/***/ (function(module, exports, __webpack_require__) { + +var isFunction = __webpack_require__(113), + isLength = __webpack_require__(223); + +/** + * Checks if `value` is array-like. A value is considered array-like if it's + * not a function and has a `value.length` that's an integer greater than or + * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + * @example + * + * _.isArrayLike([1, 2, 3]); + * // => true + * + * _.isArrayLike(document.body.children); + * // => true + * + * _.isArrayLike('abc'); + * // => true + * + * _.isArrayLike(_.noop); + * // => false + */ +function isArrayLike(value) { + return value != null && isLength(value.length) && !isFunction(value); +} + +module.exports = isArrayLike; + + +/***/ }), +/* 69 */ +/***/ (function(module, exports, __webpack_require__) { + +var createRange = __webpack_require__(652); + +/** + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to, but not including, `end`. A step of `-1` is used if a negative + * `start` is specified without an `end` or `step`. If `end` is not specified, + * it's set to `start` with `start` then set to `0`. + * + * **Note:** JavaScript follows the IEEE-754 standard for resolving + * floating-point values which can produce unexpected results. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {number} [start=0] The start of the range. + * @param {number} end The end of the range. + * @param {number} [step=1] The value to increment or decrement by. + * @returns {Array} Returns the range of numbers. + * @see _.inRange, _.rangeRight + * @example + * + * _.range(4); + * // => [0, 1, 2, 3] + * + * _.range(-4); + * // => [0, -1, -2, -3] + * + * _.range(1, 5); + * // => [1, 2, 3, 4] + * + * _.range(0, 20, 5); + * // => [0, 5, 10, 15] + * + * _.range(0, -4, -1); + * // => [0, -1, -2, -3] + * + * _.range(1, 4, 0); + * // => [1, 1, 1] + * + * _.range(0); + * // => [] + */ +var range = createRange(); + +module.exports = range; + + +/***/ }), +/* 70 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__number__ = __webpack_require__(29); + + +/* harmony default export */ __webpack_exports__["a"] = (function(values, p, valueof) { + if (valueof == null) valueof = __WEBPACK_IMPORTED_MODULE_0__number__["a" /* default */]; + if (!(n = values.length)) return; + if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values); + if (p >= 1) return +valueof(values[n - 1], n - 1, values); + var n, + i = (n - 1) * p, + i0 = Math.floor(i), + value0 = +valueof(values[i0], i0, values), + value1 = +valueof(values[i0 + 1], i0 + 1, values); + return value0 + (value1 - value0) * (i - i0); +}); + + +/***/ }), +/* 71 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_drag__ = __webpack_require__(281); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_0__src_drag__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_nodrag__ = __webpack_require__(149); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_1__src_nodrag__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_1__src_nodrag__["b"]; }); + + + + +/***/ }), +/* 72 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__namespaces__ = __webpack_require__(73); + + +/* harmony default export */ __webpack_exports__["a"] = (function(name) { + var prefix = name += "", i = prefix.indexOf(":"); + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); + return __WEBPACK_IMPORTED_MODULE_0__namespaces__["a" /* default */].hasOwnProperty(prefix) ? {space: __WEBPACK_IMPORTED_MODULE_0__namespaces__["a" /* default */][prefix], local: name} : name; +}); + + +/***/ }), +/* 73 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return xhtml; }); +var xhtml = "http://www.w3.org/1999/xhtml"; + +/* harmony default export */ __webpack_exports__["a"] = ({ + svg: "http://www.w3.org/2000/svg", + xhtml: xhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" +}); + + +/***/ }), +/* 74 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +function none() {} + +/* harmony default export */ __webpack_exports__["a"] = (function(selector) { + return selector == null ? none : function() { + return this.querySelector(selector); + }; +}); + + +/***/ }), +/* 75 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(node) { + return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node + || (node.document && node) // node is a Window + || node.defaultView; // node is a Document +}); + + +/***/ }), +/* 76 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return event; }); +/* harmony export (immutable) */ __webpack_exports__["a"] = customEvent; +var filterEvents = {}; + +var event = null; + +if (typeof document !== "undefined") { + var element = document.documentElement; + if (!("onmouseenter" in element)) { + filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"}; + } +} + +function filterContextListener(listener, index, group) { + listener = contextListener(listener, index, group); + return function(event) { + var related = event.relatedTarget; + if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) { + listener.call(this, event); + } + }; +} + +function contextListener(listener, index, group) { + return function(event1) { + var event0 = event; // Events can be reentrant (e.g., focus). + event = event1; + try { + listener.call(this, this.__data__, index, group); + } finally { + event = event0; + } + }; +} + +function parseTypenames(typenames) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + return {type: t, name: name}; + }); +} + +function onRemove(typename) { + return function() { + var on = this.__on; + if (!on) return; + for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { + if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + } else { + on[++i] = o; + } + } + if (++i) on.length = i; + else delete this.__on; + }; +} + +function onAdd(typename, value, capture) { + var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener; + return function(d, i, group) { + var on = this.__on, o, listener = wrap(value, i, group); + if (on) for (var j = 0, m = on.length; j < m; ++j) { + if ((o = on[j]).type === typename.type && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + this.addEventListener(o.type, o.listener = listener, o.capture = capture); + o.value = value; + return; + } + } + this.addEventListener(typename.type, listener, capture); + o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture}; + if (!on) this.__on = [o]; + else on.push(o); + }; +} + +/* harmony default export */ __webpack_exports__["b"] = (function(typename, value, capture) { + var typenames = parseTypenames(typename + ""), i, n = typenames.length, t; + + if (arguments.length < 2) { + var on = this.node().__on; + if (on) for (var j = 0, m = on.length, o; j < m; ++j) { + for (i = 0, o = on[j]; i < n; ++i) { + if ((t = typenames[i]).type === o.type && t.name === o.name) { + return o.value; + } + } + } + return; + } + + on = value ? onAdd : onRemove; + if (capture == null) capture = false; + for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture)); + return this; +}); + +function customEvent(event1, listener, that, args) { + var event0 = event; + event1.sourceEvent = event; + event = event1; + try { + return listener.apply(that, args); + } finally { + event = event0; + } +} + + +/***/ }), +/* 77 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__selection_on__ = __webpack_require__(76); + + +/* harmony default export */ __webpack_exports__["a"] = (function() { + var current = __WEBPACK_IMPORTED_MODULE_0__selection_on__["c" /* event */], source; + while (source = current.sourceEvent) current = source; + return current; +}); + + +/***/ }), +/* 78 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__rgb__ = __webpack_require__(152); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__array__ = __webpack_require__(155); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__date__ = __webpack_require__(156); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__number__ = __webpack_require__(45); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__object__ = __webpack_require__(157); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__string__ = __webpack_require__(158); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__constant__ = __webpack_require__(154); + + + + + + + + + +/* harmony default export */ __webpack_exports__["a"] = (function(a, b) { + var t = typeof b, c; + return b == null || t === "boolean" ? Object(__WEBPACK_IMPORTED_MODULE_7__constant__["a" /* default */])(b) + : (t === "number" ? __WEBPACK_IMPORTED_MODULE_4__number__["a" /* default */] + : t === "string" ? ((c = Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__["a" /* color */])(b)) ? (b = c, __WEBPACK_IMPORTED_MODULE_1__rgb__["a" /* default */]) : __WEBPACK_IMPORTED_MODULE_6__string__["a" /* default */]) + : b instanceof __WEBPACK_IMPORTED_MODULE_0_d3_color__["a" /* color */] ? __WEBPACK_IMPORTED_MODULE_1__rgb__["a" /* default */] + : b instanceof Date ? __WEBPACK_IMPORTED_MODULE_3__date__["a" /* default */] + : Array.isArray(b) ? __WEBPACK_IMPORTED_MODULE_2__array__["a" /* default */] + : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? __WEBPACK_IMPORTED_MODULE_5__object__["a" /* default */] + : __WEBPACK_IMPORTED_MODULE_4__number__["a" /* default */])(a, b); +}); + + +/***/ }), +/* 79 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = Color; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return darker; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return brighter; }); +/* harmony export (immutable) */ __webpack_exports__["e"] = color; +/* harmony export (immutable) */ __webpack_exports__["h"] = rgbConvert; +/* harmony export (immutable) */ __webpack_exports__["g"] = rgb; +/* harmony export (immutable) */ __webpack_exports__["b"] = Rgb; +/* unused harmony export hslConvert */ +/* harmony export (immutable) */ __webpack_exports__["f"] = hsl; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__define__ = __webpack_require__(80); + + +function Color() {} + +var darker = 0.7; +var brighter = 1 / darker; + +var reI = "\\s*([+-]?\\d+)\\s*", + reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*", + reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*", + reHex3 = /^#([0-9a-f]{3})$/, + reHex6 = /^#([0-9a-f]{6})$/, + reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"), + reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"), + reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"), + reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"), + reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"), + reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$"); + +var named = { + aliceblue: 0xf0f8ff, + antiquewhite: 0xfaebd7, + aqua: 0x00ffff, + aquamarine: 0x7fffd4, + azure: 0xf0ffff, + beige: 0xf5f5dc, + bisque: 0xffe4c4, + black: 0x000000, + blanchedalmond: 0xffebcd, + blue: 0x0000ff, + blueviolet: 0x8a2be2, + brown: 0xa52a2a, + burlywood: 0xdeb887, + cadetblue: 0x5f9ea0, + chartreuse: 0x7fff00, + chocolate: 0xd2691e, + coral: 0xff7f50, + cornflowerblue: 0x6495ed, + cornsilk: 0xfff8dc, + crimson: 0xdc143c, + cyan: 0x00ffff, + darkblue: 0x00008b, + darkcyan: 0x008b8b, + darkgoldenrod: 0xb8860b, + darkgray: 0xa9a9a9, + darkgreen: 0x006400, + darkgrey: 0xa9a9a9, + darkkhaki: 0xbdb76b, + darkmagenta: 0x8b008b, + darkolivegreen: 0x556b2f, + darkorange: 0xff8c00, + darkorchid: 0x9932cc, + darkred: 0x8b0000, + darksalmon: 0xe9967a, + darkseagreen: 0x8fbc8f, + darkslateblue: 0x483d8b, + darkslategray: 0x2f4f4f, + darkslategrey: 0x2f4f4f, + darkturquoise: 0x00ced1, + darkviolet: 0x9400d3, + deeppink: 0xff1493, + deepskyblue: 0x00bfff, + dimgray: 0x696969, + dimgrey: 0x696969, + dodgerblue: 0x1e90ff, + firebrick: 0xb22222, + floralwhite: 0xfffaf0, + forestgreen: 0x228b22, + fuchsia: 0xff00ff, + gainsboro: 0xdcdcdc, + ghostwhite: 0xf8f8ff, + gold: 0xffd700, + goldenrod: 0xdaa520, + gray: 0x808080, + green: 0x008000, + greenyellow: 0xadff2f, + grey: 0x808080, + honeydew: 0xf0fff0, + hotpink: 0xff69b4, + indianred: 0xcd5c5c, + indigo: 0x4b0082, + ivory: 0xfffff0, + khaki: 0xf0e68c, + lavender: 0xe6e6fa, + lavenderblush: 0xfff0f5, + lawngreen: 0x7cfc00, + lemonchiffon: 0xfffacd, + lightblue: 0xadd8e6, + lightcoral: 0xf08080, + lightcyan: 0xe0ffff, + lightgoldenrodyellow: 0xfafad2, + lightgray: 0xd3d3d3, + lightgreen: 0x90ee90, + lightgrey: 0xd3d3d3, + lightpink: 0xffb6c1, + lightsalmon: 0xffa07a, + lightseagreen: 0x20b2aa, + lightskyblue: 0x87cefa, + lightslategray: 0x778899, + lightslategrey: 0x778899, + lightsteelblue: 0xb0c4de, + lightyellow: 0xffffe0, + lime: 0x00ff00, + limegreen: 0x32cd32, + linen: 0xfaf0e6, + magenta: 0xff00ff, + maroon: 0x800000, + mediumaquamarine: 0x66cdaa, + mediumblue: 0x0000cd, + mediumorchid: 0xba55d3, + mediumpurple: 0x9370db, + mediumseagreen: 0x3cb371, + mediumslateblue: 0x7b68ee, + mediumspringgreen: 0x00fa9a, + mediumturquoise: 0x48d1cc, + mediumvioletred: 0xc71585, + midnightblue: 0x191970, + mintcream: 0xf5fffa, + mistyrose: 0xffe4e1, + moccasin: 0xffe4b5, + navajowhite: 0xffdead, + navy: 0x000080, + oldlace: 0xfdf5e6, + olive: 0x808000, + olivedrab: 0x6b8e23, + orange: 0xffa500, + orangered: 0xff4500, + orchid: 0xda70d6, + palegoldenrod: 0xeee8aa, + palegreen: 0x98fb98, + paleturquoise: 0xafeeee, + palevioletred: 0xdb7093, + papayawhip: 0xffefd5, + peachpuff: 0xffdab9, + peru: 0xcd853f, + pink: 0xffc0cb, + plum: 0xdda0dd, + powderblue: 0xb0e0e6, + purple: 0x800080, + rebeccapurple: 0x663399, + red: 0xff0000, + rosybrown: 0xbc8f8f, + royalblue: 0x4169e1, + saddlebrown: 0x8b4513, + salmon: 0xfa8072, + sandybrown: 0xf4a460, + seagreen: 0x2e8b57, + seashell: 0xfff5ee, + sienna: 0xa0522d, + silver: 0xc0c0c0, + skyblue: 0x87ceeb, + slateblue: 0x6a5acd, + slategray: 0x708090, + slategrey: 0x708090, + snow: 0xfffafa, + springgreen: 0x00ff7f, + steelblue: 0x4682b4, + tan: 0xd2b48c, + teal: 0x008080, + thistle: 0xd8bfd8, + tomato: 0xff6347, + turquoise: 0x40e0d0, + violet: 0xee82ee, + wheat: 0xf5deb3, + white: 0xffffff, + whitesmoke: 0xf5f5f5, + yellow: 0xffff00, + yellowgreen: 0x9acd32 +}; + +Object(__WEBPACK_IMPORTED_MODULE_0__define__["a" /* default */])(Color, color, { + displayable: function() { + return this.rgb().displayable(); + }, + toString: function() { + return this.rgb() + ""; + } +}); + +function color(format) { + var m; + format = (format + "").trim().toLowerCase(); + return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00 + : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000 + : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) + : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) + : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) + : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) + : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) + : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) + : named.hasOwnProperty(format) ? rgbn(named[format]) + : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) + : null; +} + +function rgbn(n) { + return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); +} + +function rgba(r, g, b, a) { + if (a <= 0) r = g = b = NaN; + return new Rgb(r, g, b, a); +} + +function rgbConvert(o) { + if (!(o instanceof Color)) o = color(o); + if (!o) return new Rgb; + o = o.rgb(); + return new Rgb(o.r, o.g, o.b, o.opacity); +} + +function rgb(r, g, b, opacity) { + return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); +} + +function Rgb(r, g, b, opacity) { + this.r = +r; + this.g = +g; + this.b = +b; + this.opacity = +opacity; +} + +Object(__WEBPACK_IMPORTED_MODULE_0__define__["a" /* default */])(Rgb, rgb, Object(__WEBPACK_IMPORTED_MODULE_0__define__["b" /* extend */])(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + rgb: function() { + return this; + }, + displayable: function() { + return (0 <= this.r && this.r <= 255) + && (0 <= this.g && this.g <= 255) + && (0 <= this.b && this.b <= 255) + && (0 <= this.opacity && this.opacity <= 1); + }, + toString: function() { + var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); + return (a === 1 ? "rgb(" : "rgba(") + + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + + (a === 1 ? ")" : ", " + a + ")"); + } +})); + +function hsla(h, s, l, a) { + if (a <= 0) h = s = l = NaN; + else if (l <= 0 || l >= 1) h = s = NaN; + else if (s <= 0) h = NaN; + return new Hsl(h, s, l, a); +} + +function hslConvert(o) { + if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Color)) o = color(o); + if (!o) return new Hsl; + if (o instanceof Hsl) return o; + o = o.rgb(); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + h = NaN, + s = max - min, + l = (max + min) / 2; + if (s) { + if (r === max) h = (g - b) / s + (g < b) * 6; + else if (g === max) h = (b - r) / s + 2; + else h = (r - g) / s + 4; + s /= l < 0.5 ? max + min : 2 - max - min; + h *= 60; + } else { + s = l > 0 && l < 1 ? 0 : h; + } + return new Hsl(h, s, l, o.opacity); +} + +function hsl(h, s, l, opacity) { + return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); +} + +function Hsl(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; +} + +Object(__WEBPACK_IMPORTED_MODULE_0__define__["a" /* default */])(Hsl, hsl, Object(__WEBPACK_IMPORTED_MODULE_0__define__["b" /* extend */])(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + rgb: function() { + var h = this.h % 360 + (this.h < 0) * 360, + s = isNaN(h) || isNaN(this.s) ? 0 : this.s, + l = this.l, + m2 = l + (l < 0.5 ? l : 1 - l) * s, + m1 = 2 * l - m2; + return new Rgb( + hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), + hsl2rgb(h, m1, m2), + hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), + this.opacity + ); + }, + displayable: function() { + return (0 <= this.s && this.s <= 1 || isNaN(this.s)) + && (0 <= this.l && this.l <= 1) + && (0 <= this.opacity && this.opacity <= 1); + } +})); + +/* From FvD 13.37, CSS Color Module Level 3 */ +function hsl2rgb(h, m1, m2) { + return (h < 60 ? m1 + (m2 - m1) * h / 60 + : h < 180 ? m2 + : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 + : m1) * 255; +} + + +/***/ }), +/* 80 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = extend; +/* harmony default export */ __webpack_exports__["a"] = (function(constructor, factory, prototype) { + constructor.prototype = factory.prototype = prototype; + prototype.constructor = constructor; +}); + +function extend(parent, definition) { + var prototype = Object.create(parent.prototype); + for (var key in definition) prototype[key] = definition[key]; + return prototype; +} + + +/***/ }), +/* 81 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = basis; +function basis(t1, v0, v1, v2, v3) { + var t2 = t1 * t1, t3 = t2 * t1; + return ((1 - 3 * t1 + 3 * t2 - t3) * v0 + + (4 - 6 * t2 + 3 * t3) * v1 + + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 + + t3 * v3) / 6; +} + +/* harmony default export */ __webpack_exports__["b"] = (function(values) { + var n = values.length - 1; + return function(t) { + var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), + v1 = values[i], + v2 = values[i + 1], + v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, + v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; +}); + + +/***/ }), +/* 82 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_selection_index__ = __webpack_require__(330); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_transition_index__ = __webpack_require__(14); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_1__src_transition_index__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_active__ = __webpack_require__(361); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_2__src_active__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__src_interrupt__ = __webpack_require__(159); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_3__src_interrupt__["a"]; }); + + + + + + +/***/ }), +/* 83 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = now; +/* harmony export (immutable) */ __webpack_exports__["a"] = Timer; +/* harmony export (immutable) */ __webpack_exports__["c"] = timer; +/* harmony export (immutable) */ __webpack_exports__["d"] = timerFlush; +var frame = 0, // is an animation frame pending? + timeout = 0, // is a timeout pending? + interval = 0, // are any timers active? + pokeDelay = 1000, // how frequently we check for clock skew + taskHead, + taskTail, + clockLast = 0, + clockNow = 0, + clockSkew = 0, + clock = typeof performance === "object" && performance.now ? performance : Date, + setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); }; + +function now() { + return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); +} + +function clearNow() { + clockNow = 0; +} + +function Timer() { + this._call = + this._time = + this._next = null; +} + +Timer.prototype = timer.prototype = { + constructor: Timer, + restart: function(callback, delay, time) { + if (typeof callback !== "function") throw new TypeError("callback is not a function"); + time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); + if (!this._next && taskTail !== this) { + if (taskTail) taskTail._next = this; + else taskHead = this; + taskTail = this; + } + this._call = callback; + this._time = time; + sleep(); + }, + stop: function() { + if (this._call) { + this._call = null; + this._time = Infinity; + sleep(); + } + } +}; + +function timer(callback, delay, time) { + var t = new Timer; + t.restart(callback, delay, time); + return t; +} + +function timerFlush() { + now(); // Get the current time, if not already set. + ++frame; // Pretend we’ve set an alarm, if we haven’t already. + var t = taskHead, e; + while (t) { + if ((e = clockNow - t._time) >= 0) t._call.call(null, e); + t = t._next; + } + --frame; +} + +function wake() { + clockNow = (clockLast = clock.now()) + clockSkew; + frame = timeout = 0; + try { + timerFlush(); + } finally { + frame = 0; + nap(); + clockNow = 0; + } +} + +function poke() { + var now = clock.now(), delay = now - clockLast; + if (delay > pokeDelay) clockSkew -= delay, clockLast = now; +} + +function nap() { + var t0, t1 = taskHead, t2, time = Infinity; + while (t1) { + if (t1._call) { + if (time > t1._time) time = t1._time; + t0 = t1, t1 = t1._next; + } else { + t2 = t1._next, t1._next = null; + t1 = t0 ? t0._next = t2 : taskHead = t2; + } + } + taskTail = t0; + sleep(time); +} + +function sleep(time) { + if (frame) return; // Soonest alarm already set, or will be. + if (timeout) timeout = clearTimeout(timeout); + var delay = time - clockNow; // Strictly less than if we recomputed clockNow. + if (delay > 24) { + if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew); + if (interval) interval = clearInterval(interval); + } else { + if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay); + frame = 1, setFrame(wake); + } +} + + +/***/ }), +/* 84 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return prefix; }); +var prefix = "$"; + +function Map() {} + +Map.prototype = map.prototype = { + constructor: Map, + has: function(key) { + return (prefix + key) in this; + }, + get: function(key) { + return this[prefix + key]; + }, + set: function(key, value) { + this[prefix + key] = value; + return this; + }, + remove: function(key) { + var property = prefix + key; + return property in this && delete this[property]; + }, + clear: function() { + for (var property in this) if (property[0] === prefix) delete this[property]; + }, + keys: function() { + var keys = []; + for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); + return keys; + }, + values: function() { + var values = []; + for (var property in this) if (property[0] === prefix) values.push(this[property]); + return values; + }, + entries: function() { + var entries = []; + for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); + return entries; + }, + size: function() { + var size = 0; + for (var property in this) if (property[0] === prefix) ++size; + return size; + }, + empty: function() { + for (var property in this) if (property[0] === prefix) return false; + return true; + }, + each: function(f) { + for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); + } +}; + +function map(object, f) { + var map = new Map; + + // Copy constructor. + if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); + + // Index array by numeric index or specified key function. + else if (Array.isArray(object)) { + var i = -1, + n = object.length, + o; + + if (f == null) while (++i < n) map.set(i, object[i]); + else while (++i < n) map.set(f(o = object[i], i, object), o); + } + + // Convert object to map. + else if (object) for (var key in object) map.set(key, object[key]); + + return map; +} + +/* harmony default export */ __webpack_exports__["a"] = (map); + + +/***/ }), +/* 85 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_dsv__ = __webpack_require__(86); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return __WEBPACK_IMPORTED_MODULE_0__src_dsv__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_csv__ = __webpack_require__(376); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_1__src_csv__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_1__src_csv__["d"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_1__src_csv__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_1__src_csv__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_tsv__ = __webpack_require__(377); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return __WEBPACK_IMPORTED_MODULE_2__src_tsv__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return __WEBPACK_IMPORTED_MODULE_2__src_tsv__["d"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return __WEBPACK_IMPORTED_MODULE_2__src_tsv__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return __WEBPACK_IMPORTED_MODULE_2__src_tsv__["b"]; }); + + + + + +/***/ }), +/* 86 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var EOL = {}, + EOF = {}, + QUOTE = 34, + NEWLINE = 10, + RETURN = 13; + +function objectConverter(columns) { + return new Function("d", "return {" + columns.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + "]"; + }).join(",") + "}"); +} + +function customConverter(columns, f) { + var object = objectConverter(columns); + return function(row, i) { + return f(object(row), i, columns); + }; +} + +// Compute unique columns in order of discovery. +function inferColumns(rows) { + var columnSet = Object.create(null), + columns = []; + + rows.forEach(function(row) { + for (var column in row) { + if (!(column in columnSet)) { + columns.push(columnSet[column] = column); + } + } + }); + + return columns; +} + +/* harmony default export */ __webpack_exports__["a"] = (function(delimiter) { + var reFormat = new RegExp("[\"" + delimiter + "\n\r]"), + DELIMITER = delimiter.charCodeAt(0); + + function parse(text, f) { + var convert, columns, rows = parseRows(text, function(row, i) { + if (convert) return convert(row, i - 1); + columns = row, convert = f ? customConverter(row, f) : objectConverter(row); + }); + rows.columns = columns || []; + return rows; + } + + function parseRows(text, f) { + var rows = [], // output rows + N = text.length, + I = 0, // current character index + n = 0, // current line number + t, // current token + eof = N <= 0, // current token followed by EOF? + eol = false; // current token followed by EOL? + + // Strip the trailing newline. + if (text.charCodeAt(N - 1) === NEWLINE) --N; + if (text.charCodeAt(N - 1) === RETURN) --N; + + function token() { + if (eof) return EOF; + if (eol) return eol = false, EOL; + + // Unescape quotes. + var i, j = I, c; + if (text.charCodeAt(j) === QUOTE) { + while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE); + if ((i = I) >= N) eof = true; + else if ((c = text.charCodeAt(I++)) === NEWLINE) eol = true; + else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; } + return text.slice(j + 1, i - 1).replace(/""/g, "\""); + } + + // Find next delimiter or newline. + while (I < N) { + if ((c = text.charCodeAt(i = I++)) === NEWLINE) eol = true; + else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; } + else if (c !== DELIMITER) continue; + return text.slice(j, i); + } + + // Return last token before EOF. + return eof = true, text.slice(j, N); + } + + while ((t = token()) !== EOF) { + var row = []; + while (t !== EOL && t !== EOF) row.push(t), t = token(); + if (f && (row = f(row, n++)) == null) continue; + rows.push(row); + } + + return rows; + } + + function format(rows, columns) { + if (columns == null) columns = inferColumns(rows); + return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) { + return columns.map(function(column) { + return formatValue(row[column]); + }).join(delimiter); + })).join("\n"); + } + + function formatRows(rows) { + return rows.map(formatRow).join("\n"); + } + + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } + + function formatValue(text) { + return text == null ? "" + : reFormat.test(text += "") ? "\"" + text.replace(/"/g, "\"\"") + "\"" + : text; + } + + return { + parse: parse, + parseRows: parseRows, + format: format, + formatRows: formatRows + }; +}); + + +/***/ }), +/* 87 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function() { + return (Math.random() - 0.5) * 1e-6; +}); + + +/***/ }), +/* 88 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_quadtree__ = __webpack_require__(381); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_0__src_quadtree__["a"]; }); + + + +/***/ }), +/* 89 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(node, x0, y0, x1, y1) { + this.node = node; + this.x0 = x0; + this.y0 = y0; + this.x1 = x1; + this.y1 = y1; +}); + + +/***/ }), +/* 90 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__ = __webpack_require__(399); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__["c"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_locale__ = __webpack_require__(164); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_1__src_locale__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_formatSpecifier__ = __webpack_require__(165); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return __WEBPACK_IMPORTED_MODULE_2__src_formatSpecifier__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__src_precisionFixed__ = __webpack_require__(405); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return __WEBPACK_IMPORTED_MODULE_3__src_precisionFixed__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__src_precisionPrefix__ = __webpack_require__(406); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return __WEBPACK_IMPORTED_MODULE_4__src_precisionPrefix__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__src_precisionRound__ = __webpack_require__(407); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return __WEBPACK_IMPORTED_MODULE_5__src_precisionRound__["a"]; }); + + + + + + + + +/***/ }), +/* 91 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +// Computes the decimal coefficient and exponent of the specified number x with +// significant digits p, where x is positive and p is in [1, 21] or undefined. +// For example, formatDecimal(1.23) returns ["123", 0]. +/* harmony default export */ __webpack_exports__["a"] = (function(x, p) { + if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity + var i, coefficient = x.slice(0, i); + + // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ + // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). + return [ + coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, + +x.slice(i + 1) + ]; +}); + + +/***/ }), +/* 92 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(x) { + return x; +}); + + +/***/ }), +/* 93 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = conicEqualAreaRaw; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__conic__ = __webpack_require__(94); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__cylindricalEqualArea__ = __webpack_require__(424); + + + + +function conicEqualAreaRaw(y0, y1) { + var sy0 = Object(__WEBPACK_IMPORTED_MODULE_0__math__["t" /* sin */])(y0), n = (sy0 + Object(__WEBPACK_IMPORTED_MODULE_0__math__["t" /* sin */])(y1)) / 2; + + // Are the parallels symmetrical around the Equator? + if (Object(__WEBPACK_IMPORTED_MODULE_0__math__["a" /* abs */])(n) < __WEBPACK_IMPORTED_MODULE_0__math__["i" /* epsilon */]) return Object(__WEBPACK_IMPORTED_MODULE_2__cylindricalEqualArea__["a" /* cylindricalEqualAreaRaw */])(y0); + + var c = 1 + sy0 * (2 * n - sy0), r0 = Object(__WEBPACK_IMPORTED_MODULE_0__math__["u" /* sqrt */])(c) / n; + + function project(x, y) { + var r = Object(__WEBPACK_IMPORTED_MODULE_0__math__["u" /* sqrt */])(c - 2 * n * Object(__WEBPACK_IMPORTED_MODULE_0__math__["t" /* sin */])(y)) / n; + return [r * Object(__WEBPACK_IMPORTED_MODULE_0__math__["t" /* sin */])(x *= n), r0 - r * Object(__WEBPACK_IMPORTED_MODULE_0__math__["g" /* cos */])(x)]; + } + + project.invert = function(x, y) { + var r0y = r0 - y; + return [Object(__WEBPACK_IMPORTED_MODULE_0__math__["e" /* atan2 */])(x, Object(__WEBPACK_IMPORTED_MODULE_0__math__["a" /* abs */])(r0y)) / n * Object(__WEBPACK_IMPORTED_MODULE_0__math__["s" /* sign */])(r0y), Object(__WEBPACK_IMPORTED_MODULE_0__math__["c" /* asin */])((c - (x * x + r0y * r0y) * n * n) / (2 * n))]; + }; + + return project; +} + +/* harmony default export */ __webpack_exports__["b"] = (function() { + return Object(__WEBPACK_IMPORTED_MODULE_1__conic__["a" /* conicProjection */])(conicEqualAreaRaw) + .scale(155.424) + .center([0, 33.6442]); +}); + + +/***/ }), +/* 94 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = conicProjection; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__index__ = __webpack_require__(10); + + + +function conicProjection(projectAt) { + var phi0 = 0, + phi1 = __WEBPACK_IMPORTED_MODULE_0__math__["o" /* pi */] / 3, + m = Object(__WEBPACK_IMPORTED_MODULE_1__index__["b" /* projectionMutator */])(projectAt), + p = m(phi0, phi1); + + p.parallels = function(_) { + return arguments.length ? m(phi0 = _[0] * __WEBPACK_IMPORTED_MODULE_0__math__["r" /* radians */], phi1 = _[1] * __WEBPACK_IMPORTED_MODULE_0__math__["r" /* radians */]) : [phi0 * __WEBPACK_IMPORTED_MODULE_0__math__["h" /* degrees */], phi1 * __WEBPACK_IMPORTED_MODULE_0__math__["h" /* degrees */]]; + }; + + return p; +} + + +/***/ }), +/* 95 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = fitExtent; +/* harmony export (immutable) */ __webpack_exports__["c"] = fitSize; +/* harmony export (immutable) */ __webpack_exports__["d"] = fitWidth; +/* harmony export (immutable) */ __webpack_exports__["b"] = fitHeight; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__stream__ = __webpack_require__(18); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__path_bounds__ = __webpack_require__(180); + + + +function fit(projection, fitBounds, object) { + var clip = projection.clipExtent && projection.clipExtent(); + projection.scale(150).translate([0, 0]); + if (clip != null) projection.clipExtent(null); + Object(__WEBPACK_IMPORTED_MODULE_0__stream__["a" /* default */])(object, projection.stream(__WEBPACK_IMPORTED_MODULE_1__path_bounds__["a" /* default */])); + fitBounds(__WEBPACK_IMPORTED_MODULE_1__path_bounds__["a" /* default */].result()); + if (clip != null) projection.clipExtent(clip); + return projection; +} + +function fitExtent(projection, extent, object) { + return fit(projection, function(b) { + var w = extent[1][0] - extent[0][0], + h = extent[1][1] - extent[0][1], + k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), + x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2, + y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2; + projection.scale(150 * k).translate([x, y]); + }, object); +} + +function fitSize(projection, size, object) { + return fitExtent(projection, [[0, 0], size], object); +} + +function fitWidth(projection, width, object) { + return fit(projection, function(b) { + var w = +width, + k = w / (b[1][0] - b[0][0]), + x = (w - k * (b[1][0] + b[0][0])) / 2, + y = -k * b[0][1]; + projection.scale(150 * k).translate([x, y]); + }, object); +} + +function fitHeight(projection, height, object) { + return fit(projection, function(b) { + var h = +height, + k = h / (b[1][1] - b[0][1]), + x = -k * b[0][0], + y = (h - k * (b[1][1] + b[0][1])) / 2; + projection.scale(150 * k).translate([x, y]); + }, object); +} + + +/***/ }), +/* 96 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["c"] = mercatorRaw; +/* harmony export (immutable) */ __webpack_exports__["b"] = mercatorProjection; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__rotation__ = __webpack_require__(49); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__index__ = __webpack_require__(10); + + + + +function mercatorRaw(lambda, phi) { + return [lambda, Object(__WEBPACK_IMPORTED_MODULE_0__math__["n" /* log */])(Object(__WEBPACK_IMPORTED_MODULE_0__math__["v" /* tan */])((__WEBPACK_IMPORTED_MODULE_0__math__["l" /* halfPi */] + phi) / 2))]; +} + +mercatorRaw.invert = function(x, y) { + return [x, 2 * Object(__WEBPACK_IMPORTED_MODULE_0__math__["d" /* atan */])(Object(__WEBPACK_IMPORTED_MODULE_0__math__["k" /* exp */])(y)) - __WEBPACK_IMPORTED_MODULE_0__math__["l" /* halfPi */]]; +}; + +/* harmony default export */ __webpack_exports__["a"] = (function() { + return mercatorProjection(mercatorRaw) + .scale(961 / __WEBPACK_IMPORTED_MODULE_0__math__["w" /* tau */]); +}); + +function mercatorProjection(project) { + var m = Object(__WEBPACK_IMPORTED_MODULE_2__index__["a" /* default */])(project), + center = m.center, + scale = m.scale, + translate = m.translate, + clipExtent = m.clipExtent, + x0 = null, y0, x1, y1; // clip extent + + m.scale = function(_) { + return arguments.length ? (scale(_), reclip()) : scale(); + }; + + m.translate = function(_) { + return arguments.length ? (translate(_), reclip()) : translate(); + }; + + m.center = function(_) { + return arguments.length ? (center(_), reclip()) : center(); + }; + + m.clipExtent = function(_) { + return arguments.length ? ((_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1])), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }; + + function reclip() { + var k = __WEBPACK_IMPORTED_MODULE_0__math__["o" /* pi */] * scale(), + t = m(Object(__WEBPACK_IMPORTED_MODULE_1__rotation__["a" /* default */])(m.rotate()).invert([0, 0])); + return clipExtent(x0 == null + ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw + ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]] + : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]); + } + + return reclip(); +} + + +/***/ }), +/* 97 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["c"] = hierarchy; +/* harmony export (immutable) */ __webpack_exports__["b"] = computeHeight; +/* harmony export (immutable) */ __webpack_exports__["a"] = Node; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__count__ = __webpack_require__(438); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__each__ = __webpack_require__(439); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__eachBefore__ = __webpack_require__(440); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__eachAfter__ = __webpack_require__(441); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__sum__ = __webpack_require__(442); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__sort__ = __webpack_require__(443); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__path__ = __webpack_require__(444); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__ancestors__ = __webpack_require__(445); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__descendants__ = __webpack_require__(446); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__leaves__ = __webpack_require__(447); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__links__ = __webpack_require__(448); + + + + + + + + + + + + +function hierarchy(data, children) { + var root = new Node(data), + valued = +data.value && (root.value = data.value), + node, + nodes = [root], + child, + childs, + i, + n; + + if (children == null) children = defaultChildren; + + while (node = nodes.pop()) { + if (valued) node.value = +node.data.value; + if ((childs = children(node.data)) && (n = childs.length)) { + node.children = new Array(n); + for (i = n - 1; i >= 0; --i) { + nodes.push(child = node.children[i] = new Node(childs[i])); + child.parent = node; + child.depth = node.depth + 1; + } + } + } + + return root.eachBefore(computeHeight); +} + +function node_copy() { + return hierarchy(this).eachBefore(copyData); +} + +function defaultChildren(d) { + return d.children; +} + +function copyData(node) { + node.data = node.data.data; +} + +function computeHeight(node) { + var height = 0; + do node.height = height; + while ((node = node.parent) && (node.height < ++height)); +} + +function Node(data) { + this.data = data; + this.depth = + this.height = 0; + this.parent = null; +} + +Node.prototype = hierarchy.prototype = { + constructor: Node, + count: __WEBPACK_IMPORTED_MODULE_0__count__["a" /* default */], + each: __WEBPACK_IMPORTED_MODULE_1__each__["a" /* default */], + eachAfter: __WEBPACK_IMPORTED_MODULE_3__eachAfter__["a" /* default */], + eachBefore: __WEBPACK_IMPORTED_MODULE_2__eachBefore__["a" /* default */], + sum: __WEBPACK_IMPORTED_MODULE_4__sum__["a" /* default */], + sort: __WEBPACK_IMPORTED_MODULE_5__sort__["a" /* default */], + path: __WEBPACK_IMPORTED_MODULE_6__path__["a" /* default */], + ancestors: __WEBPACK_IMPORTED_MODULE_7__ancestors__["a" /* default */], + descendants: __WEBPACK_IMPORTED_MODULE_8__descendants__["a" /* default */], + leaves: __WEBPACK_IMPORTED_MODULE_9__leaves__["a" /* default */], + links: __WEBPACK_IMPORTED_MODULE_10__links__["a" /* default */], + copy: node_copy +}; + + +/***/ }), +/* 98 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = optional; +/* harmony export (immutable) */ __webpack_exports__["b"] = required; +function optional(f) { + return f == null ? null : required(f); +} + +function required(f) { + if (typeof f !== "function") throw new Error; + return f; +} + + +/***/ }), +/* 99 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return phi; }); +/* harmony export (immutable) */ __webpack_exports__["c"] = squarifyRatio; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__dice__ = __webpack_require__(34); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__slice__ = __webpack_require__(52); + + + +var phi = (1 + Math.sqrt(5)) / 2; + +function squarifyRatio(ratio, parent, x0, y0, x1, y1) { + var rows = [], + nodes = parent.children, + row, + nodeValue, + i0 = 0, + i1 = 0, + n = nodes.length, + dx, dy, + value = parent.value, + sumValue, + minValue, + maxValue, + newRatio, + minRatio, + alpha, + beta; + + while (i0 < n) { + dx = x1 - x0, dy = y1 - y0; + + // Find the next non-empty node. + do sumValue = nodes[i1++].value; while (!sumValue && i1 < n); + minValue = maxValue = sumValue; + alpha = Math.max(dy / dx, dx / dy) / (value * ratio); + beta = sumValue * sumValue * alpha; + minRatio = Math.max(maxValue / beta, beta / minValue); + + // Keep adding nodes while the aspect ratio maintains or improves. + for (; i1 < n; ++i1) { + sumValue += nodeValue = nodes[i1].value; + if (nodeValue < minValue) minValue = nodeValue; + if (nodeValue > maxValue) maxValue = nodeValue; + beta = sumValue * sumValue * alpha; + newRatio = Math.max(maxValue / beta, beta / minValue); + if (newRatio > minRatio) { sumValue -= nodeValue; break; } + minRatio = newRatio; + } + + // Position and record the row orientation. + rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)}); + if (row.dice) Object(__WEBPACK_IMPORTED_MODULE_0__dice__["a" /* default */])(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1); + else Object(__WEBPACK_IMPORTED_MODULE_1__slice__["a" /* default */])(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1); + value -= sumValue, i0 = i1; + } + + return rows; +} + +/* harmony default export */ __webpack_exports__["a"] = ((function custom(ratio) { + + function squarify(parent, x0, y0, x1, y1) { + squarifyRatio(ratio, parent, x0, y0, x1, y1); + } + + squarify.ratio = function(x) { + return custom((x = +x) > 1 ? x : 1); + }; + + return squarify; +})(phi)); + + +/***/ }), +/* 100 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_collection__ = __webpack_require__(31); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_d3_dispatch__ = __webpack_require__(16); + + + +/* harmony default export */ __webpack_exports__["a"] = (function(url, callback) { + var request, + event = Object(__WEBPACK_IMPORTED_MODULE_1_d3_dispatch__["a" /* dispatch */])("beforesend", "progress", "load", "error"), + mimeType, + headers = Object(__WEBPACK_IMPORTED_MODULE_0_d3_collection__["c" /* map */])(), + xhr = new XMLHttpRequest, + user = null, + password = null, + response, + responseType, + timeout = 0; + + // If IE does not support CORS, use XDomainRequest. + if (typeof XDomainRequest !== "undefined" + && !("withCredentials" in xhr) + && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest; + + "onload" in xhr + ? xhr.onload = xhr.onerror = xhr.ontimeout = respond + : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); }; + + function respond(o) { + var status = xhr.status, result; + if (!status && hasResponse(xhr) + || status >= 200 && status < 300 + || status === 304) { + if (response) { + try { + result = response.call(request, xhr); + } catch (e) { + event.call("error", request, e); + return; + } + } else { + result = xhr; + } + event.call("load", request, result); + } else { + event.call("error", request, o); + } + } + + xhr.onprogress = function(e) { + event.call("progress", request, e); + }; + + request = { + header: function(name, value) { + name = (name + "").toLowerCase(); + if (arguments.length < 2) return headers.get(name); + if (value == null) headers.remove(name); + else headers.set(name, value + ""); + return request; + }, + + // If mimeType is non-null and no Accept header is set, a default is used. + mimeType: function(value) { + if (!arguments.length) return mimeType; + mimeType = value == null ? null : value + ""; + return request; + }, + + // Specifies what type the response value should take; + // for instance, arraybuffer, blob, document, or text. + responseType: function(value) { + if (!arguments.length) return responseType; + responseType = value; + return request; + }, + + timeout: function(value) { + if (!arguments.length) return timeout; + timeout = +value; + return request; + }, + + user: function(value) { + return arguments.length < 1 ? user : (user = value == null ? null : value + "", request); + }, + + password: function(value) { + return arguments.length < 1 ? password : (password = value == null ? null : value + "", request); + }, + + // Specify how to convert the response content to a specific type; + // changes the callback value on "load" events. + response: function(value) { + response = value; + return request; + }, + + // Alias for send("GET", …). + get: function(data, callback) { + return request.send("GET", data, callback); + }, + + // Alias for send("POST", …). + post: function(data, callback) { + return request.send("POST", data, callback); + }, + + // If callback is non-null, it will be used for error and load events. + send: function(method, data, callback) { + xhr.open(method, url, true, user, password); + if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*"); + if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); }); + if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType); + if (responseType != null) xhr.responseType = responseType; + if (timeout > 0) xhr.timeout = timeout; + if (callback == null && typeof data === "function") callback = data, data = null; + if (callback != null && callback.length === 1) callback = fixCallback(callback); + if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); }); + event.call("beforesend", request, xhr); + xhr.send(data == null ? null : data); + return request; + }, + + abort: function() { + xhr.abort(); + return request; + }, + + on: function() { + var value = event.on.apply(event, arguments); + return value === event ? request : value; + } + }; + + if (callback != null) { + if (typeof callback !== "function") throw new Error("invalid callback: " + callback); + return request.get(callback); + } + + return request; +}); + +function fixCallback(callback) { + return function(error, xhr) { + callback(error == null ? xhr : null); + }; +} + +function hasResponse(xhr) { + var type = xhr.responseType; + return type && type !== "text" + ? xhr.response // null on error + : xhr.responseText; // "" on error +} + + +/***/ }), +/* 101 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(x) { + return function() { + return x; + }; +}); + + +/***/ }), +/* 102 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__ = __webpack_require__(103); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__["d"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return __WEBPACK_IMPORTED_MODULE_0__src_defaultLocale__["e"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_locale__ = __webpack_require__(194); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return __WEBPACK_IMPORTED_MODULE_1__src_locale__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_isoFormat__ = __webpack_require__(195); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_2__src_isoFormat__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__src_isoParse__ = __webpack_require__(503); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_3__src_isoParse__["a"]; }); + + + + + + +/***/ }), +/* 103 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return timeFormat; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return timeParse; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return utcFormat; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return utcParse; }); +/* harmony export (immutable) */ __webpack_exports__["a"] = defaultLocale; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__locale__ = __webpack_require__(194); + + +var locale; +var timeFormat; +var timeParse; +var utcFormat; +var utcParse; + +defaultLocale({ + dateTime: "%x, %X", + date: "%-m/%-d/%Y", + time: "%-I:%M:%S %p", + periods: ["AM", "PM"], + days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], + shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], + months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] +}); + +function defaultLocale(definition) { + locale = Object(__WEBPACK_IMPORTED_MODULE_0__locale__["a" /* default */])(definition); + timeFormat = locale.format; + timeParse = locale.parse; + utcFormat = locale.utcFormat; + utcParse = locale.utcParse; + return locale; +} + + +/***/ }), +/* 104 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_path__ = __webpack_require__(17); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__constant__ = __webpack_require__(20); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__curve_linear__ = __webpack_require__(56); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__point__ = __webpack_require__(105); + + + + + +/* harmony default export */ __webpack_exports__["a"] = (function() { + var x = __WEBPACK_IMPORTED_MODULE_3__point__["a" /* x */], + y = __WEBPACK_IMPORTED_MODULE_3__point__["b" /* y */], + defined = Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(true), + context = null, + curve = __WEBPACK_IMPORTED_MODULE_2__curve_linear__["a" /* default */], + output = null; + + function line(data) { + var i, + n = data.length, + d, + defined0 = false, + buffer; + + if (context == null) output = curve(buffer = Object(__WEBPACK_IMPORTED_MODULE_0_d3_path__["a" /* path */])()); + + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) output.lineStart(); + else output.lineEnd(); + } + if (defined0) output.point(+x(d, i, data), +y(d, i, data)); + } + + if (buffer) return output = null, buffer + "" || null; + } + + line.x = function(_) { + return arguments.length ? (x = typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(+_), line) : x; + }; + + line.y = function(_) { + return arguments.length ? (y = typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(+_), line) : y; + }; + + line.defined = function(_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(!!_), line) : defined; + }; + + line.curve = function(_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve; + }; + + line.context = function(_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; + }; + + return line; +}); + + +/***/ }), +/* 105 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = x; +/* harmony export (immutable) */ __webpack_exports__["b"] = y; +function x(p) { + return p[0]; +} + +function y(p) { + return p[1]; +} + + +/***/ }), +/* 106 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = point; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(37); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__cardinal__ = __webpack_require__(59); + + + +function point(that, x, y) { + var x1 = that._x1, + y1 = that._y1, + x2 = that._x2, + y2 = that._y2; + + if (that._l01_a > __WEBPACK_IMPORTED_MODULE_0__math__["f" /* epsilon */]) { + var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, + n = 3 * that._l01_a * (that._l01_a + that._l12_a); + x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; + y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; + } + + if (that._l23_a > __WEBPACK_IMPORTED_MODULE_0__math__["f" /* epsilon */]) { + var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, + m = 3 * that._l23_a * (that._l23_a + that._l12_a); + x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; + y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; + } + + that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); +} + +function CatmullRom(context, alpha) { + this._context = context; + this._alpha = alpha; +} + +CatmullRom.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x2, this._y2); break; + case 3: this.point(this._x2, this._y2); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; // proceed + default: point(this, x, y); break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +/* harmony default export */ __webpack_exports__["a"] = ((function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRom(context, alpha) : new __WEBPACK_IMPORTED_MODULE_1__cardinal__["a" /* Cardinal */](context, 0); + } + + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; + + return catmullRom; +})(0.5)); + + +/***/ }), +/* 107 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = sum; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__none__ = __webpack_require__(39); + + +/* harmony default export */ __webpack_exports__["a"] = (function(series) { + var sums = series.map(sum); + return Object(__WEBPACK_IMPORTED_MODULE_0__none__["a" /* default */])(series).sort(function(a, b) { return sums[a] - sums[b]; }); +}); + +function sum(series) { + var s = 0, i = -1, n = series.length, v; + while (++i < n) if (v = +series[i][1]) s += v; + return s; +} + + +/***/ }), +/* 108 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = RedBlackNode; +function RedBlackTree() { + this._ = null; // root node +} + +function RedBlackNode(node) { + node.U = // parent node + node.C = // color - true for red, false for black + node.L = // left node + node.R = // right node + node.P = // previous node + node.N = null; // next node +} + +RedBlackTree.prototype = { + constructor: RedBlackTree, + + insert: function(after, node) { + var parent, grandpa, uncle; + + if (after) { + node.P = after; + node.N = after.N; + if (after.N) after.N.P = node; + after.N = node; + if (after.R) { + after = after.R; + while (after.L) after = after.L; + after.L = node; + } else { + after.R = node; + } + parent = after; + } else if (this._) { + after = RedBlackFirst(this._); + node.P = null; + node.N = after; + after.P = after.L = node; + parent = after; + } else { + node.P = node.N = null; + this._ = node; + parent = null; + } + node.L = node.R = null; + node.U = parent; + node.C = true; + + after = node; + while (parent && parent.C) { + grandpa = parent.U; + if (parent === grandpa.L) { + uncle = grandpa.R; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.R) { + RedBlackRotateLeft(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateRight(this, grandpa); + } + } else { + uncle = grandpa.L; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.L) { + RedBlackRotateRight(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateLeft(this, grandpa); + } + } + parent = after.U; + } + this._.C = false; + }, + + remove: function(node) { + if (node.N) node.N.P = node.P; + if (node.P) node.P.N = node.N; + node.N = node.P = null; + + var parent = node.U, + sibling, + left = node.L, + right = node.R, + next, + red; + + if (!left) next = right; + else if (!right) next = left; + else next = RedBlackFirst(right); + + if (parent) { + if (parent.L === node) parent.L = next; + else parent.R = next; + } else { + this._ = next; + } + + if (left && right) { + red = next.C; + next.C = node.C; + next.L = left; + left.U = next; + if (next !== right) { + parent = next.U; + next.U = node.U; + node = next.R; + parent.L = node; + next.R = right; + right.U = next; + } else { + next.U = parent; + parent = next; + node = next.R; + } + } else { + red = node.C; + node = next; + } + + if (node) node.U = parent; + if (red) return; + if (node && node.C) { node.C = false; return; } + + do { + if (node === this._) break; + if (node === parent.L) { + sibling = parent.R; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateLeft(this, parent); + sibling = parent.R; + } + if ((sibling.L && sibling.L.C) + || (sibling.R && sibling.R.C)) { + if (!sibling.R || !sibling.R.C) { + sibling.L.C = false; + sibling.C = true; + RedBlackRotateRight(this, sibling); + sibling = parent.R; + } + sibling.C = parent.C; + parent.C = sibling.R.C = false; + RedBlackRotateLeft(this, parent); + node = this._; + break; + } + } else { + sibling = parent.L; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateRight(this, parent); + sibling = parent.L; + } + if ((sibling.L && sibling.L.C) + || (sibling.R && sibling.R.C)) { + if (!sibling.L || !sibling.L.C) { + sibling.R.C = false; + sibling.C = true; + RedBlackRotateLeft(this, sibling); + sibling = parent.L; + } + sibling.C = parent.C; + parent.C = sibling.L.C = false; + RedBlackRotateRight(this, parent); + node = this._; + break; + } + } + sibling.C = true; + node = parent; + parent = parent.U; + } while (!node.C); + + if (node) node.C = false; + } +}; + +function RedBlackRotateLeft(tree, node) { + var p = node, + q = node.R, + parent = p.U; + + if (parent) { + if (parent.L === p) parent.L = q; + else parent.R = q; + } else { + tree._ = q; + } + + q.U = parent; + p.U = q; + p.R = q.L; + if (p.R) p.R.U = p; + q.L = p; +} + +function RedBlackRotateRight(tree, node) { + var p = node, + q = node.L, + parent = p.U; + + if (parent) { + if (parent.L === p) parent.L = q; + else parent.R = q; + } else { + tree._ = q; + } + + q.U = parent; + p.U = q; + p.L = q.R; + if (p.L) p.L.U = p; + q.R = p; +} + +function RedBlackFirst(node) { + while (node.L) node = node.L; + return node; +} + +/* harmony default export */ __webpack_exports__["b"] = (RedBlackTree); + + +/***/ }), +/* 109 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["c"] = createEdge; +/* harmony export (immutable) */ __webpack_exports__["b"] = createBorderEdge; +/* harmony export (immutable) */ __webpack_exports__["d"] = setEdgeEnd; +/* harmony export (immutable) */ __webpack_exports__["a"] = clipEdges; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Diagram__ = __webpack_require__(40); + + +function createEdge(left, right, v0, v1) { + var edge = [null, null], + index = __WEBPACK_IMPORTED_MODULE_0__Diagram__["e" /* edges */].push(edge) - 1; + edge.left = left; + edge.right = right; + if (v0) setEdgeEnd(edge, left, right, v0); + if (v1) setEdgeEnd(edge, right, left, v1); + __WEBPACK_IMPORTED_MODULE_0__Diagram__["b" /* cells */][left.index].halfedges.push(index); + __WEBPACK_IMPORTED_MODULE_0__Diagram__["b" /* cells */][right.index].halfedges.push(index); + return edge; +} + +function createBorderEdge(left, v0, v1) { + var edge = [v0, v1]; + edge.left = left; + return edge; +} + +function setEdgeEnd(edge, left, right, vertex) { + if (!edge[0] && !edge[1]) { + edge[0] = vertex; + edge.left = left; + edge.right = right; + } else if (edge.left === right) { + edge[1] = vertex; + } else { + edge[0] = vertex; + } +} + +// Liang–Barsky line clipping. +function clipEdge(edge, x0, y0, x1, y1) { + var a = edge[0], + b = edge[1], + ax = a[0], + ay = a[1], + bx = b[0], + by = b[1], + t0 = 0, + t1 = 1, + dx = bx - ax, + dy = by - ay, + r; + + r = x0 - ax; + if (!dx && r > 0) return; + r /= dx; + if (dx < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dx > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + + r = x1 - ax; + if (!dx && r < 0) return; + r /= dx; + if (dx < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dx > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + + r = y0 - ay; + if (!dy && r > 0) return; + r /= dy; + if (dy < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dy > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + + r = y1 - ay; + if (!dy && r < 0) return; + r /= dy; + if (dy < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dy > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + + if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check? + + if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy]; + if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy]; + return true; +} + +function connectEdge(edge, x0, y0, x1, y1) { + var v1 = edge[1]; + if (v1) return true; + + var v0 = edge[0], + left = edge.left, + right = edge.right, + lx = left[0], + ly = left[1], + rx = right[0], + ry = right[1], + fx = (lx + rx) / 2, + fy = (ly + ry) / 2, + fm, + fb; + + if (ry === ly) { + if (fx < x0 || fx >= x1) return; + if (lx > rx) { + if (!v0) v0 = [fx, y0]; + else if (v0[1] >= y1) return; + v1 = [fx, y1]; + } else { + if (!v0) v0 = [fx, y1]; + else if (v0[1] < y0) return; + v1 = [fx, y0]; + } + } else { + fm = (lx - rx) / (ry - ly); + fb = fy - fm * fx; + if (fm < -1 || fm > 1) { + if (lx > rx) { + if (!v0) v0 = [(y0 - fb) / fm, y0]; + else if (v0[1] >= y1) return; + v1 = [(y1 - fb) / fm, y1]; + } else { + if (!v0) v0 = [(y1 - fb) / fm, y1]; + else if (v0[1] < y0) return; + v1 = [(y0 - fb) / fm, y0]; + } + } else { + if (ly < ry) { + if (!v0) v0 = [x0, fm * x0 + fb]; + else if (v0[0] >= x1) return; + v1 = [x1, fm * x1 + fb]; + } else { + if (!v0) v0 = [x1, fm * x1 + fb]; + else if (v0[0] < x0) return; + v1 = [x0, fm * x0 + fb]; + } + } + } + + edge[0] = v0; + edge[1] = v1; + return true; +} + +function clipEdges(x0, y0, x1, y1) { + var i = __WEBPACK_IMPORTED_MODULE_0__Diagram__["e" /* edges */].length, + edge; + + while (i--) { + if (!connectEdge(edge = __WEBPACK_IMPORTED_MODULE_0__Diagram__["e" /* edges */][i], x0, y0, x1, y1) + || !clipEdge(edge, x0, y0, x1, y1) + || !(Math.abs(edge[0][0] - edge[1][0]) > __WEBPACK_IMPORTED_MODULE_0__Diagram__["f" /* epsilon */] + || Math.abs(edge[0][1] - edge[1][1]) > __WEBPACK_IMPORTED_MODULE_0__Diagram__["f" /* epsilon */])) { + delete __WEBPACK_IMPORTED_MODULE_0__Diagram__["e" /* edges */][i]; + } + } +} + + +/***/ }), +/* 110 */ +/***/ (function(module, exports) { + +/* eslint no-constant-condition: 0 */ +/** + * Obliterator Take Function + * ========================== + * + * Function taking n or every value of the given iterator and returns them + * into an array. + */ + +/** + * Take. + * + * @param {Iterator} iterator - Target iterator. + * @param {number} [n] - Optional number of items to take. + * @return {array} + */ +module.exports = function take(iterator, n) { + var l = arguments.length > 1 ? n : Infinity, + array = l !== Infinity ? new Array(l) : [], + step, + i = 0; + + while (true) { + + if (i === l) + return array; + + step = iterator.next(); + + if (step.done) { + + if (i !== n) + return array.slice(0, i); + + return array; + } + + array[i++] = step.value; + } +}; + + +/***/ }), +/* 111 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.MixedNodeData = MixedNodeData; +exports.DirectedNodeData = DirectedNodeData; +exports.UndirectedNodeData = UndirectedNodeData; +exports.DirectedEdgeData = DirectedEdgeData; +exports.UndirectedEdgeData = UndirectedEdgeData; +/** + * Graphology Internal Data Classes + * ================================= + * + * Internal classes hopefully reduced to structs by engines & storing + * necessary information for nodes & edges. + * + * Note that those classes don't rely on the `class` keyword to avoid some + * cruft introduced by most of ES2015 transpilers. + */ + +/** + * MixedNodeData class. + * + * @constructor + * @param {object} attributes - Node's attributes. + */ +function MixedNodeData(attributes) { + + // Attributes + this.attributes = attributes; + + // Degrees + this.inDegree = 0; + this.outDegree = 0; + this.undirectedDegree = 0; + this.directedSelfLoops = 0; + this.undirectedSelfLoops = 0; + + // Indices + this.in = {}; + this.out = {}; + this.undirected = {}; +} + +/** + * DirectedNodeData class. + * + * @constructor + * @param {object} attributes - Node's attributes. + */ +function DirectedNodeData(attributes) { + + // Attributes + this.attributes = attributes || {}; + + // Degrees + this.inDegree = 0; + this.outDegree = 0; + this.directedSelfLoops = 0; + + // Indices + this.in = {}; + this.out = {}; +} + +DirectedNodeData.prototype.upgradeToMixed = function () { + + // Degrees + this.undirectedDegree = 0; + this.undirectedSelfLoops = 0; + + // Indices + this.undirected = {}; +}; + +/** + * UndirectedNodeData class. + * + * @constructor + * @param {object} attributes - Node's attributes. + */ +function UndirectedNodeData(attributes) { + + // Attributes + this.attributes = attributes || {}; + + // Degrees + this.undirectedDegree = 0; + this.undirectedSelfLoops = 0; + + // Indices + this.undirected = {}; +} + +UndirectedNodeData.prototype.upgradeToMixed = function () { + + // Degrees + this.inDegree = 0; + this.outDegree = 0; + this.directedSelfLoops = 0; + + // Indices + this.in = {}; + this.out = {}; +}; + +/** + * DirectedEdgeData class. + * + * @constructor + * @param {boolean} generatedKey - Was its key generated? + * @param {string} source - Source of the edge. + * @param {string} target - Target of the edge. + * @param {object} attributes - Edge's attributes. + */ +function DirectedEdgeData(generatedKey, source, target, attributes) { + + // Attributes + this.attributes = attributes; + + // Extremities + this.source = source; + this.target = target; + + // Was its key generated? + this.generatedKey = generatedKey; +} + +/** + * UndirectedEdgeData class. + * + * @constructor + * @param {boolean} generatedKey - Was its key generated? + * @param {string} source - Source of the edge. + * @param {string} target - Target of the edge. + * @param {object} attributes - Edge's attributes. + */ +function UndirectedEdgeData(generatedKey, source, target, attributes) { + + // Attributes + this.attributes = attributes; + + // Extremities + this.source = source; + this.target = target; + + // Was its key generated? + this.generatedKey = generatedKey; +} + +/***/ }), +/* 112 */ +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(21), + root = __webpack_require__(11); + +/* Built-in method references that are verified to be native. */ +var Map = getNative(root, 'Map'); + +module.exports = Map; + + +/***/ }), +/* 113 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseGetTag = __webpack_require__(28), + isObject = __webpack_require__(13); + +/** `Object#toString` result references. */ +var asyncTag = '[object AsyncFunction]', + funcTag = '[object Function]', + genTag = '[object GeneratorFunction]', + proxyTag = '[object Proxy]'; + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + if (!isObject(value)) { + return false; + } + // The use of `Object#toString` avoids issues with the `typeof` operator + // in Safari 9 which returns 'object' for typed arrays and other constructors. + var tag = baseGetTag(value); + return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; +} + +module.exports = isFunction; + + +/***/ }), +/* 114 */ +/***/ (function(module, exports, __webpack_require__) { + +var root = __webpack_require__(11); + +/** Built-in value references. */ +var Symbol = root.Symbol; + +module.exports = Symbol; + + +/***/ }), +/* 115 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(11), + stubFalse = __webpack_require__(608); + +/** Detect free variable `exports`. */ +var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; + +/** Detect free variable `module`. */ +var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; + +/** Detect the popular CommonJS extension `module.exports`. */ +var moduleExports = freeModule && freeModule.exports === freeExports; + +/** Built-in value references. */ +var Buffer = moduleExports ? root.Buffer : undefined; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined; + +/** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ +var isBuffer = nativeIsBuffer || stubFalse; + +module.exports = isBuffer; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(116)(module))) + +/***/ }), +/* 116 */ +/***/ (function(module, exports) { + +module.exports = function(module) { + if(!module.webpackPolyfill) { + module.deprecate = function() {}; + module.paths = []; + // module.parent = undefined by default + if(!module.children) module.children = []; + Object.defineProperty(module, "loaded", { + enumerable: true, + get: function() { + return module.l; + } + }); + Object.defineProperty(module, "id", { + enumerable: true, + get: function() { + return module.i; + } + }); + module.webpackPolyfill = 1; + } + return module; +}; + + +/***/ }), +/* 117 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIsTypedArray = __webpack_require__(609), + baseUnary = __webpack_require__(610), + nodeUtil = __webpack_require__(611); + +/* Node.js helper references. */ +var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; + +/** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ +var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; + +module.exports = isTypedArray; + + +/***/ }), +/* 118 */ +/***/ (function(module, exports) { + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Checks if `value` is likely a prototype object. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. + */ +function isPrototype(value) { + var Ctor = value && value.constructor, + proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; + + return value === proto; +} + +module.exports = isPrototype; + + +/***/ }), +/* 119 */ +/***/ (function(module, exports, __webpack_require__) { + +var identity = __webpack_require__(226), + overRest = __webpack_require__(621), + setToString = __webpack_require__(622); + +/** + * The base implementation of `_.rest` which doesn't validate or coerce arguments. + * + * @private + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + */ +function baseRest(func, start) { + return setToString(overRest(func, start, identity), func + ''); +} + +module.exports = baseRest; + + +/***/ }), +/* 120 */ +/***/ (function(module, exports, __webpack_require__) { + +var defineProperty = __webpack_require__(227); + +/** + * The base implementation of `assignValue` and `assignMergeValue` without + * value checks. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function baseAssignValue(object, key, value) { + if (key == '__proto__' && defineProperty) { + defineProperty(object, key, { + 'configurable': true, + 'enumerable': true, + 'value': value, + 'writable': true + }); + } else { + object[key] = value; + } +} + +module.exports = baseAssignValue; + + +/***/ }), +/* 121 */ +/***/ (function(module, exports, __webpack_require__) { + +var arrayLikeKeys = __webpack_require__(220), + baseKeysIn = __webpack_require__(641), + isArrayLike = __webpack_require__(68); + +/** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @since 3.0.0 + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ +function keysIn(object) { + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); +} + +module.exports = keysIn; + + +/***/ }), +/* 122 */ +/***/ (function(module, exports, __webpack_require__) { + +var eq = __webpack_require__(27), + isArrayLike = __webpack_require__(68), + isIndex = __webpack_require__(222), + isObject = __webpack_require__(13); + +/** + * Checks if the given arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, + * else `false`. + */ +function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object) + ) { + return eq(object[index], value); + } + return false; +} + +module.exports = isIterateeCall; + + +/***/ }), +/* 123 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Graphology Empty Graph Generator + * ================================= + * + * Function generating empty graphs. + */ +var isGraphConstructor = __webpack_require__(5); + +/** + * Generates an empty graph with n nodes and 0 edges. + * + * @param {Class} GraphClass - The Graph Class to instantiate. + * @param {number} order - Number of nodes of the graph. + * @return {Graph} + */ +module.exports = function empty(GraphClass, order) { + if (!isGraphConstructor(GraphClass)) + throw new Error('graphology-generators/classic/empty: invalid Graph constructor.'); + + var graph = new GraphClass(); + + var i; + + for (i = 0; i < order; i++) + graph.addNode(i); + + return graph; +}; + + +/***/ }), +/* 124 */ +/***/ (function(module, exports) { + +/** + * Graphology mergePath + * ===================== + * + * Function merging the given path to the graph. + */ + +/** + * Merging the given path to the graph. + * + * @param {Graph} graph - Target graph. + * @param {array} nodes - Nodes representing the path to merge. + */ +module.exports = function mergePath(graph, nodes) { + if (nodes.length === 0) + return; + + var previousNode, node, i, l; + + graph.mergeNode(nodes[0]); + + for (i = 1, l = nodes.length; i < l; i++) { + previousNode = nodes[i - 1]; + node = nodes[i]; + + graph.mergeEdge(previousNode, node); + } +}; + + +/***/ }), +/* 125 */ +/***/ (function(module, exports) { + +/** + * Obliterator ForEach Function + * ============================= + * + * Helper function used to easily iterate over mixed values. + */ + +/** + * Constants. + */ +var ARRAY_BUFFER_SUPPORT = typeof ArrayBuffer !== 'undefined', + SYMBOL_SUPPORT = typeof Symbol !== 'undefined'; + +/** + * Function able to iterate over almost any iterable JS value. + * + * @param {any} iterable - Iterable value. + * @param {function} callback - Callback function. + */ +function forEach(iterable, callback) { + var iterator, k, i, l, s; + + if (!iterable) + throw new Error('obliterator/forEach: invalid iterable.'); + + if (typeof callback !== 'function') + throw new Error('obliterator/forEach: expecting a callback.'); + + // The target is an array or a string or function arguments + if ( + Array.isArray(iterable) || + (ARRAY_BUFFER_SUPPORT && ArrayBuffer.isView(iterable)) || + typeof iterable === 'string' || + iterable.toString() === '[object Arguments]' + ) { + for (i = 0, l = iterable.length; i < l; i++) + callback(iterable[i], i); + return; + } + + // The target has a #.forEach method + if (typeof iterable.forEach === 'function') { + iterable.forEach(callback); + return; + } + + // The target is iterable + if ( + SYMBOL_SUPPORT && + Symbol.iterator in iterable && + typeof iterable.next !== 'function' + ) { + iterable = iterable[Symbol.iterator](); + } + + // The target is an iterator + if (typeof iterable.next === 'function') { + iterator = iterable; + i = 0; + + while ((s = iterator.next(), s.done !== true)) { + callback(s.value, i); + i++; + } + + return; + } + + // The target is a plain object + for (k in iterable) { + if (iterable.hasOwnProperty(k)) { + callback(iterable[k], k); + } + } + + return; +} + +/** + * Same function as the above `forEach` but will yield `null` when the target + * does not have keys. + * + * @param {any} iterable - Iterable value. + * @param {function} callback - Callback function. + */ +forEach.forEachWithNullKeys = function(iterable, callback) { + var iterator, k, i, l, s; + + if (!iterable) + throw new Error('obliterator/forEachWithNullKeys: invalid iterable.'); + + if (typeof callback !== 'function') + throw new Error('obliterator/forEachWithNullKeys: expecting a callback.'); + + // The target is an array or a string or function arguments + if ( + Array.isArray(iterable) || + (ARRAY_BUFFER_SUPPORT && ArrayBuffer.isView(iterable)) || + typeof iterable === 'string' || + iterable.toString() === '[object Arguments]' + ) { + for (i = 0, l = iterable.length; i < l; i++) + callback(iterable[i], null); + return; + } + + // The target is a Set + if (iterable instanceof Set) { + iterable.forEach(function(value) { + callback(value, null); + }); + return; + } + + // The target has a #.forEach method + if (typeof iterable.forEach === 'function') { + iterable.forEach(callback); + return; + } + + // The target is iterable + if ( + SYMBOL_SUPPORT && + Symbol.iterator in iterable && + typeof iterable.next !== 'function' + ) { + iterable = iterable[Symbol.iterator](); + } + + // The target is an iterator + if (typeof iterable.next === 'function') { + iterator = iterable; + i = 0; + + while ((s = iterator.next(), s.done !== true)) { + callback(s.value, null); + i++; + } + + return; + } + + // The target is a plain object + for (k in iterable) { + if (iterable.hasOwnProperty(k)) { + callback(iterable[k], k); + } + } + + return; +}; + +/** + * Exporting. + */ +module.exports = forEach; + + +/***/ }), +/* 126 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _events = __webpack_require__(62); + +var easings = _interopRequireWildcard(__webpack_require__(719)); + +var _utils = __webpack_require__(239); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } + +function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +/** + * Defaults. + */ +var ANIMATE_DEFAULTS = { + easing: 'quadraticInOut', + duration: 150 +}; +var DEFAULT_ZOOMING_RATIO = 1.5; // TODO: animate options = number polymorphism? +// TODO: pan, zoom, unzoom, reset, rotate, zoomTo +// TODO: add width / height to camera and add #.resize +// TODO: bind camera to renderer rather than sigma +// TODO: add #.graphToDisplay, #.displayToGraph, batch methods later + +/** + * Camera class + * + * @constructor + */ + +var Camera = +/*#__PURE__*/ +function (_EventEmitter) { + _inherits(Camera, _EventEmitter); + + function Camera() { + var _this; + + _classCallCheck(this, Camera); + + _this = _possibleConstructorReturn(this, _getPrototypeOf(Camera).call(this)); // Properties + + _this.x = 0.5; + _this.y = 0.5; + _this.angle = 0; + _this.ratio = 1; // State + + _this.nextFrame = null; + _this.previousState = _this.getState(); + _this.enabled = true; + return _this; + } + /** + * Method used to enable the camera. + * + * @return {Camera} + */ + + + _createClass(Camera, [{ + key: "enable", + value: function enable() { + this.enabled = true; + return this; + } + /** + * Method used to disable the camera. + * + * @return {Camera} + */ + + }, { + key: "disable", + value: function disable() { + this.enabled = false; + return this; + } + /** + * Method used to retrieve the camera's current state. + * + * @return {object} + */ + + }, { + key: "getState", + value: function getState() { + return { + x: this.x, + y: this.y, + angle: this.angle, + ratio: this.ratio + }; + } + /** + * Method used to retrieve the camera's previous state. + * + * @return {object} + */ + + }, { + key: "getPreviousState", + value: function getPreviousState() { + var state = this.previousState; + return { + x: state.x, + y: state.y, + angle: state.angle, + ratio: state.ratio + }; + } + /** + * Method used to check whether the camera is currently being animated. + * + * @return {boolean} + */ + + }, { + key: "isAnimated", + value: function isAnimated() { + return !!this.nextFrame; + } + /** + * Method returning the coordinates of a point from the graph frame to the + * viewport. + * + * @param {object} dimensions - Dimensions of the viewport. + * @param {number} x - The X coordinate. + * @param {number} y - The Y coordinate. + * @return {object} - The point coordinates in the viewport. + */ + // TODO: assign to gain one object + // TODO: angles + + }, { + key: "graphToViewport", + value: function graphToViewport(dimensions, x, y) { + var smallestDimension = Math.min(dimensions.width, dimensions.height); + var dx = smallestDimension / dimensions.width, + dy = smallestDimension / dimensions.height; // TODO: we keep on the upper left corner! + // TODO: how to normalize sizes? + + return { + x: (x - this.x + this.ratio / 2 / dx) * (smallestDimension / this.ratio), + y: (this.y - y + this.ratio / 2 / dy) * (smallestDimension / this.ratio) + }; + } + /** + * Method returning the coordinates of a point from the viewport frame to the + * graph frame. + * + * @param {object} dimensions - Dimensions of the viewport. + * @param {number} x - The X coordinate. + * @param {number} y - The Y coordinate. + * @return {object} - The point coordinates in the graph frame. + */ + // TODO: angles + + }, { + key: "viewportToGraph", + value: function viewportToGraph(dimensions, x, y) { + var smallestDimension = Math.min(dimensions.width, dimensions.height); + var dx = smallestDimension / dimensions.width, + dy = smallestDimension / dimensions.height; + return { + x: this.ratio / smallestDimension * x + this.x - this.ratio / 2 / dx, + y: -(this.ratio / smallestDimension * y - this.y - this.ratio / 2 / dy) + }; + } + /** + * Method returning the abstract rectangle containing the graph according + * to the camera's state. + * + * @return {object} - The view's rectangle. + */ + // TODO: angle + + }, { + key: "viewRectangle", + value: function viewRectangle(dimensions) { + // TODO: reduce relative margin? + var marginX = 0 * dimensions.width / 8, + marginY = 0 * dimensions.height / 8; + var p1 = this.viewportToGraph(dimensions, 0 - marginX, 0 - marginY), + p2 = this.viewportToGraph(dimensions, dimensions.width + marginX, 0 - marginY), + h = this.viewportToGraph(dimensions, 0, dimensions.height + marginY); + return { + x1: p1.x, + y1: p1.y, + x2: p2.x, + y2: p2.y, + height: p2.y - h.y + }; + } + /** + * Method used to set the camera's state. + * + * @param {object} state - New state. + * @return {Camera} + */ + + }, { + key: "setState", + value: function setState(state) { + if (!this.enabled) return this; // TODO: validations + // TODO: update by function + // Keeping track of last state + + this.previousState = this.getState(); + if ('x' in state) this.x = state.x; + if ('y' in state) this.y = state.y; + if ('angle' in state) this.angle = state.angle; + if ('ratio' in state) this.ratio = state.ratio; // Emitting + // TODO: don't emit if nothing changed? + + this.emit('updated', this.getState()); + return this; + } + /** + * Method used to animate the camera. + * + * @param {object} state - State to reach eventually. + * @param {object} options - Options: + * @param {number} duration - Duration of the animation. + * @param {function} callback - Callback + * @return {function} - Return a function to cancel the animation. + */ + + }, { + key: "animate", + value: function animate(state, options, callback) { + var _this2 = this; + + if (!this.enabled) return this; // TODO: validation + + options = (0, _utils.assign)({}, ANIMATE_DEFAULTS, options); + var easing = typeof options.easing === 'function' ? options.easing : easings[options.easing]; // Canceling previous animation if needed + + if (this.nextFrame) cancelAnimationFrame(this.nextFrame); // State + + var start = Date.now(), + initialState = this.getState(); // Function performing the animation + + var fn = function fn() { + var t = (Date.now() - start) / options.duration; // The animation is over: + + if (t >= 1) { + _this2.nextFrame = null; + + _this2.setState(state); + + if (typeof callback === 'function') callback(); + return; + } + + var coefficient = easing(t); + var newState = {}; + if ('x' in state) newState.x = initialState.x + (state.x - initialState.x) * coefficient; + if ('y' in state) newState.y = initialState.y + (state.y - initialState.y) * coefficient; + if ('angle' in state) newState.angle = initialState.angle + (state.angle - initialState.angle) * coefficient; + if ('ratio' in state) newState.ratio = initialState.ratio + (state.ratio - initialState.ratio) * coefficient; + + _this2.setState(newState); + + _this2.nextFrame = requestAnimationFrame(fn); + }; + + if (this.nextFrame) { + cancelAnimationFrame(this.nextFrame); + this.nextFrame = requestAnimationFrame(fn); + } else { + fn(); + } + } + /** + * Method used to zoom the camera. + * + * @param {number|object} factorOrOptions - Factor or options. + * @return {function} + */ + + }, { + key: "animatedZoom", + value: function animatedZoom(factorOrOptions) { + if (!factorOrOptions) { + return this.animate({ + ratio: this.ratio / DEFAULT_ZOOMING_RATIO + }); + } else { + if (typeof factorOrOptions === 'number') return this.animate({ + ratio: this.ratio / factorOrOptions + });else return this.animate({ + ratio: this.ratio / (factorOrOptions.factor || DEFAULT_ZOOMING_RATIO) + }, factorOrOptions); + } + } + /** + * Method used to unzoom the camera. + * + * @param {number|object} factorOrOptions - Factor or options. + * @return {function} + */ + + }, { + key: "animatedUnzoom", + value: function animatedUnzoom(factorOrOptions) { + if (!factorOrOptions) { + return this.animate({ + ratio: this.ratio * DEFAULT_ZOOMING_RATIO + }); + } else { + if (typeof factorOrOptions === 'number') return this.animate({ + ratio: this.ratio * factorOrOptions + });else return this.animate({ + ratio: this.ratio * (factorOrOptions.factor || DEFAULT_ZOOMING_RATIO) + }, factorOrOptions); + } + } + /** + * Method used to reset the camera. + * + * @param {object} options - Options. + * @return {function} + */ + + }, { + key: "animatedReset", + value: function animatedReset(options) { + return this.animate({ + x: 0.5, + y: 0.5, + ratio: 1, + angle: 0 + }, options); + } + }]); + + return Camera; +}(_events.EventEmitter); + +exports.default = Camera; + +/***/ }), +/* 127 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.floatColor = floatColor; +exports.matrixFromCamera = matrixFromCamera; +exports.extractPixel = extractPixel; +exports.canUse32BitsIndices = canUse32BitsIndices; + +var _matrices = __webpack_require__(731); + +/** + * Sigma.js WebGL Renderer Utils + * ============================== + * + * Miscelleanous helper functions used by sigma's WebGL renderer. + */ + +/** + * Memoized function returning a float-encoded color from various string + * formats describing colors. + */ +var FLOAT_COLOR_CACHE = {}; +var INT8 = new Int8Array(4); +var INT32 = new Int32Array(INT8.buffer, 0, 1); +var FLOAT32 = new Float32Array(INT8.buffer, 0, 1); +var RGBA_TEST_REGEX = /^\s*rgba?\s*\(/; +var RGBA_EXTRACT_REGEX = /^\s*rgba?\s*\(\s*([0-9]*)\s*,\s*([0-9]*)\s*,\s*([0-9]*)(?:\s*,\s*(.*)?)?\)\s*$/; + +function floatColor(val) { + // If the color is already computed, we yield it + if (typeof FLOAT_COLOR_CACHE[val] !== 'undefined') return FLOAT_COLOR_CACHE[val]; + var r = 0, + g = 0, + b = 0, + a = 1; // Handling hexadecimal notation + + if (val[0] === '#') { + if (val.length === 4) { + r = parseInt(val.charAt(1) + val.charAt(1), 16); + g = parseInt(val.charAt(2) + val.charAt(2), 16); + b = parseInt(val.charAt(3) + val.charAt(3), 16); + } else { + r = parseInt(val.charAt(1) + val.charAt(2), 16); + g = parseInt(val.charAt(3) + val.charAt(4), 16); + b = parseInt(val.charAt(5) + val.charAt(6), 16); + } + } // Handling rgb notation + else if (RGBA_TEST_REGEX.test(val)) { + var match = val.match(RGBA_EXTRACT_REGEX); + r = +match[1]; + g = +match[2]; + b = +match[3]; + if (match[4]) a = +match[4]; + } + + a = a * 255 | 0; + var bits = (a << 24 | b << 16 | g << 8 | r) & 0xfeffffff; + INT32[0] = bits; + var color = FLOAT32[0]; + FLOAT_COLOR_CACHE[val] = color; + return color; +} +/** + * Function returning a matrix from the current state of the camera. + */ +// TODO: it's possible to optimize this drastically! + + +function matrixFromCamera(state, dimensions) { + var angle = state.angle, + ratio = state.ratio, + x = state.x, + y = state.y; + var width = dimensions.width, + height = dimensions.height; + var matrix = (0, _matrices.identity)(); + var smallestDimension = Math.min(width, height); + var cameraCentering = (0, _matrices.translate)((0, _matrices.identity)(), -x, -y), + cameraScaling = (0, _matrices.scale)((0, _matrices.identity)(), 1 / ratio), + cameraRotation = (0, _matrices.rotate)((0, _matrices.identity)(), -angle), + viewportScaling = (0, _matrices.scale)((0, _matrices.identity)(), 2 * (smallestDimension / width), 2 * (smallestDimension / height)); // Logical order is reversed + + (0, _matrices.multiply)(matrix, viewportScaling); + (0, _matrices.multiply)(matrix, cameraRotation); + (0, _matrices.multiply)(matrix, cameraScaling); + (0, _matrices.multiply)(matrix, cameraCentering); + return matrix; +} +/** + * Function extracting the color at the given pixel. + */ + + +function extractPixel(gl, x, y, array) { + var data = array || new Uint8Array(4); + gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, data); + return data; +} +/** + * Function used to know whether given webgl context can use 32 bits indices. + */ + + +function canUse32BitsIndices(gl) { + var webgl2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext; + return webgl2 || !!gl.getExtension('OES_element_index_uint'); +} + +/***/ }), +/* 128 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(249); +module.exports = angular; + + +/***/ }), +/* 129 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(250); +module.exports = 'ngAnimate'; + + +/***/ }), +/* 130 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(251); +module.exports = 'ngAria'; + + +/***/ }), +/* 131 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return bisectRight; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return bisectLeft; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__ascending__ = __webpack_require__(23); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__bisector__ = __webpack_require__(132); + + + +var ascendingBisect = Object(__WEBPACK_IMPORTED_MODULE_1__bisector__["a" /* default */])(__WEBPACK_IMPORTED_MODULE_0__ascending__["a" /* default */]); +var bisectRight = ascendingBisect.right; +var bisectLeft = ascendingBisect.left; +/* harmony default export */ __webpack_exports__["c"] = (bisectRight); + + +/***/ }), +/* 132 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__ascending__ = __webpack_require__(23); + + +/* harmony default export */ __webpack_exports__["a"] = (function(compare) { + if (compare.length === 1) compare = ascendingComparator(compare); + return { + left: function(a, x, lo, hi) { + if (lo == null) lo = 0; + if (hi == null) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) < 0) lo = mid + 1; + else hi = mid; + } + return lo; + }, + right: function(a, x, lo, hi) { + if (lo == null) lo = 0; + if (hi == null) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) > 0) hi = mid; + else lo = mid + 1; + } + return lo; + } + }; +}); + +function ascendingComparator(f) { + return function(d, x) { + return Object(__WEBPACK_IMPORTED_MODULE_0__ascending__["a" /* default */])(f(d), x); + }; +} + + +/***/ }), +/* 133 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = pair; +/* harmony default export */ __webpack_exports__["a"] = (function(array, f) { + if (f == null) f = pair; + var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); + while (i < n) pairs[i] = f(p, p = array[++i]); + return pairs; +}); + +function pair(a, b) { + return [a, b]; +} + + +/***/ }), +/* 134 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__variance__ = __webpack_require__(135); + + +/* harmony default export */ __webpack_exports__["a"] = (function(array, f) { + var v = Object(__WEBPACK_IMPORTED_MODULE_0__variance__["a" /* default */])(array, f); + return v ? Math.sqrt(v) : v; +}); + + +/***/ }), +/* 135 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__number__ = __webpack_require__(29); + + +/* harmony default export */ __webpack_exports__["a"] = (function(values, valueof) { + var n = values.length, + m = 0, + i = -1, + mean = 0, + value, + delta, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = Object(__WEBPACK_IMPORTED_MODULE_0__number__["a" /* default */])(values[i]))) { + delta = value - mean; + mean += delta / ++m; + sum += delta * (value - mean); + } + } + } + + else { + while (++i < n) { + if (!isNaN(value = Object(__WEBPACK_IMPORTED_MODULE_0__number__["a" /* default */])(valueof(values[i], i, values)))) { + delta = value - mean; + mean += delta / ++m; + sum += delta * (value - mean); + } + } + } + + if (m > 1) return sum / (m - 1); +}); + + +/***/ }), +/* 136 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(values, valueof) { + var n = values.length, + i = -1, + value, + min, + max; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + min = max = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null) { + if (min > value) min = value; + if (max < value) max = value; + } + } + } + } + } + + else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + min = max = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null) { + if (min > value) min = value; + if (max < value) max = value; + } + } + } + } + } + + return [min, max]; +}); + + +/***/ }), +/* 137 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return slice; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return map; }); +var array = Array.prototype; + +var slice = array.slice; +var map = array.map; + + +/***/ }), +/* 138 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(start, stop, step) { + start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; + + var i = -1, + n = Math.max(0, Math.ceil((stop - start) / step)) | 0, + range = new Array(n); + + while (++i < n) { + range[i] = start + i * step; + } + + return range; +}); + + +/***/ }), +/* 139 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = tickIncrement; +/* harmony export (immutable) */ __webpack_exports__["c"] = tickStep; +var e10 = Math.sqrt(50), + e5 = Math.sqrt(10), + e2 = Math.sqrt(2); + +/* harmony default export */ __webpack_exports__["a"] = (function(start, stop, count) { + var reverse, + i = -1, + n, + ticks, + step; + + stop = +stop, start = +start, count = +count; + if (start === stop && count > 0) return [start]; + if (reverse = stop < start) n = start, start = stop, stop = n; + if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return []; + + if (step > 0) { + start = Math.ceil(start / step); + stop = Math.floor(stop / step); + ticks = new Array(n = Math.ceil(stop - start + 1)); + while (++i < n) ticks[i] = (start + i) * step; + } else { + start = Math.floor(start * step); + stop = Math.ceil(stop * step); + ticks = new Array(n = Math.ceil(start - stop + 1)); + while (++i < n) ticks[i] = (start - i) / step; + } + + if (reverse) ticks.reverse(); + + return ticks; +}); + +function tickIncrement(start, stop, count) { + var step = (stop - start) / Math.max(0, count), + power = Math.floor(Math.log(step) / Math.LN10), + error = step / Math.pow(10, power); + return power >= 0 + ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) + : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); +} + +function tickStep(start, stop, count) { + var step0 = Math.abs(stop - start) / Math.max(0, count), + step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), + error = step0 / step1; + if (error >= e10) step1 *= 10; + else if (error >= e5) step1 *= 5; + else if (error >= e2) step1 *= 2; + return stop < start ? -step1 : step1; +} + + +/***/ }), +/* 140 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(values) { + return Math.ceil(Math.log(values.length) / Math.LN2) + 1; +}); + + +/***/ }), +/* 141 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(values, valueof) { + var n = values.length, + i = -1, + value, + min; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + min = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null && min > value) { + min = value; + } + } + } + } + } + + else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + min = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null && min > value) { + min = value; + } + } + } + } + } + + return min; +}); + + +/***/ }), +/* 142 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__min__ = __webpack_require__(141); + + +/* harmony default export */ __webpack_exports__["a"] = (function(matrix) { + if (!(n = matrix.length)) return []; + for (var i = -1, m = Object(__WEBPACK_IMPORTED_MODULE_0__min__["a" /* default */])(matrix, length), transpose = new Array(m); ++i < m;) { + for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) { + row[j] = matrix[j][i]; + } + } + return transpose; +}); + +function length(d) { + return d.length; +} + + +/***/ }), +/* 143 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__selection_index__ = __webpack_require__(6); + + +/* harmony default export */ __webpack_exports__["a"] = (function(selector) { + return typeof selector === "string" + ? new __WEBPACK_IMPORTED_MODULE_0__selection_index__["a" /* Selection */]([[document.querySelector(selector)]], [document.documentElement]) + : new __WEBPACK_IMPORTED_MODULE_0__selection_index__["a" /* Selection */]([[selector]], __WEBPACK_IMPORTED_MODULE_0__selection_index__["c" /* root */]); +}); + + +/***/ }), +/* 144 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +function empty() { + return []; +} + +/* harmony default export */ __webpack_exports__["a"] = (function(selector) { + return selector == null ? empty : function() { + return this.querySelectorAll(selector); + }; +}); + + +/***/ }), +/* 145 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var matcher = function(selector) { + return function() { + return this.matches(selector); + }; +}; + +if (typeof document !== "undefined") { + var element = document.documentElement; + if (!element.matches) { + var vendorMatches = element.webkitMatchesSelector + || element.msMatchesSelector + || element.mozMatchesSelector + || element.oMatchesSelector; + matcher = function(selector) { + return function() { + return vendorMatches.call(this, selector); + }; + }; + } +} + +/* harmony default export */ __webpack_exports__["a"] = (matcher); + + +/***/ }), +/* 146 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = EnterNode; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__sparse__ = __webpack_require__(147); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__index__ = __webpack_require__(6); + + + +/* harmony default export */ __webpack_exports__["b"] = (function() { + return new __WEBPACK_IMPORTED_MODULE_1__index__["a" /* Selection */](this._enter || this._groups.map(__WEBPACK_IMPORTED_MODULE_0__sparse__["a" /* default */]), this._parents); +}); + +function EnterNode(parent, datum) { + this.ownerDocument = parent.ownerDocument; + this.namespaceURI = parent.namespaceURI; + this._next = null; + this._parent = parent; + this.__data__ = datum; +} + +EnterNode.prototype = { + constructor: EnterNode, + appendChild: function(child) { return this._parent.insertBefore(child, this._next); }, + insertBefore: function(child, next) { return this._parent.insertBefore(child, next); }, + querySelector: function(selector) { return this._parent.querySelector(selector); }, + querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); } +}; + + +/***/ }), +/* 147 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(update) { + return new Array(update.length); +}); + + +/***/ }), +/* 148 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = styleValue; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__window__ = __webpack_require__(75); + + +function styleRemove(name) { + return function() { + this.style.removeProperty(name); + }; +} + +function styleConstant(name, value, priority) { + return function() { + this.style.setProperty(name, value, priority); + }; +} + +function styleFunction(name, value, priority) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.style.removeProperty(name); + else this.style.setProperty(name, v, priority); + }; +} + +/* harmony default export */ __webpack_exports__["a"] = (function(name, value, priority) { + return arguments.length > 1 + ? this.each((value == null + ? styleRemove : typeof value === "function" + ? styleFunction + : styleConstant)(name, value, priority == null ? "" : priority)) + : styleValue(this.node(), name); +}); + +function styleValue(node, name) { + return node.style.getPropertyValue(name) + || Object(__WEBPACK_IMPORTED_MODULE_0__window__["a" /* default */])(node).getComputedStyle(node, null).getPropertyValue(name); +} + + +/***/ }), +/* 149 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = yesdrag; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_selection__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__noevent__ = __webpack_require__(150); + + + +/* harmony default export */ __webpack_exports__["a"] = (function(view) { + var root = view.document.documentElement, + selection = Object(__WEBPACK_IMPORTED_MODULE_0_d3_selection__["k" /* select */])(view).on("dragstart.drag", __WEBPACK_IMPORTED_MODULE_1__noevent__["a" /* default */], true); + if ("onselectstart" in root) { + selection.on("selectstart.drag", __WEBPACK_IMPORTED_MODULE_1__noevent__["a" /* default */], true); + } else { + root.__noselect = root.style.MozUserSelect; + root.style.MozUserSelect = "none"; + } +}); + +function yesdrag(view, noclick) { + var root = view.document.documentElement, + selection = Object(__WEBPACK_IMPORTED_MODULE_0_d3_selection__["k" /* select */])(view).on("dragstart.drag", null); + if (noclick) { + selection.on("click.drag", __WEBPACK_IMPORTED_MODULE_1__noevent__["a" /* default */], true); + setTimeout(function() { selection.on("click.drag", null); }, 0); + } + if ("onselectstart" in root) { + selection.on("selectstart.drag", null); + } else { + root.style.MozUserSelect = root.__noselect; + delete root.__noselect; + } +} + + +/***/ }), +/* 150 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = nopropagation; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_selection__ = __webpack_require__(2); + + +function nopropagation() { + __WEBPACK_IMPORTED_MODULE_0_d3_selection__["e" /* event */].stopImmediatePropagation(); +} + +/* harmony default export */ __webpack_exports__["a"] = (function() { + __WEBPACK_IMPORTED_MODULE_0_d3_selection__["e" /* event */].preventDefault(); + __WEBPACK_IMPORTED_MODULE_0_d3_selection__["e" /* event */].stopImmediatePropagation(); +}); + + +/***/ }), +/* 151 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return deg2rad; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return rad2deg; }); +var deg2rad = Math.PI / 180; +var rad2deg = 180 / Math.PI; + + +/***/ }), +/* 152 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return rgbBasis; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return rgbBasisClosed; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__basis__ = __webpack_require__(81); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__basisClosed__ = __webpack_require__(153); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__color__ = __webpack_require__(30); + + + + + +/* harmony default export */ __webpack_exports__["a"] = ((function rgbGamma(y) { + var color = Object(__WEBPACK_IMPORTED_MODULE_3__color__["b" /* gamma */])(y); + + function rgb(start, end) { + var r = color((start = Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__["f" /* rgb */])(start)).r, (end = Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__["f" /* rgb */])(end)).r), + g = color(start.g, end.g), + b = color(start.b, end.b), + opacity = Object(__WEBPACK_IMPORTED_MODULE_3__color__["a" /* default */])(start.opacity, end.opacity); + return function(t) { + start.r = r(t); + start.g = g(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; + } + + rgb.gamma = rgbGamma; + + return rgb; +})(1)); + +function rgbSpline(spline) { + return function(colors) { + var n = colors.length, + r = new Array(n), + g = new Array(n), + b = new Array(n), + i, color; + for (i = 0; i < n; ++i) { + color = Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__["f" /* rgb */])(colors[i]); + r[i] = color.r || 0; + g[i] = color.g || 0; + b[i] = color.b || 0; + } + r = spline(r); + g = spline(g); + b = spline(b); + color.opacity = 1; + return function(t) { + color.r = r(t); + color.g = g(t); + color.b = b(t); + return color + ""; + }; + }; +} + +var rgbBasis = rgbSpline(__WEBPACK_IMPORTED_MODULE_1__basis__["b" /* default */]); +var rgbBasisClosed = rgbSpline(__WEBPACK_IMPORTED_MODULE_2__basisClosed__["a" /* default */]); + + +/***/ }), +/* 153 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__basis__ = __webpack_require__(81); + + +/* harmony default export */ __webpack_exports__["a"] = (function(values) { + var n = values.length; + return function(t) { + var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), + v0 = values[(i + n - 1) % n], + v1 = values[i % n], + v2 = values[(i + 1) % n], + v3 = values[(i + 2) % n]; + return Object(__WEBPACK_IMPORTED_MODULE_0__basis__["a" /* basis */])((t - i / n) * n, v0, v1, v2, v3); + }; +}); + + +/***/ }), +/* 154 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(x) { + return function() { + return x; + }; +}); + + +/***/ }), +/* 155 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__value__ = __webpack_require__(78); + + +/* harmony default export */ __webpack_exports__["a"] = (function(a, b) { + var nb = b ? b.length : 0, + na = a ? Math.min(nb, a.length) : 0, + x = new Array(na), + c = new Array(nb), + i; + + for (i = 0; i < na; ++i) x[i] = Object(__WEBPACK_IMPORTED_MODULE_0__value__["a" /* default */])(a[i], b[i]); + for (; i < nb; ++i) c[i] = b[i]; + + return function(t) { + for (i = 0; i < na; ++i) c[i] = x[i](t); + return c; + }; +}); + + +/***/ }), +/* 156 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(a, b) { + var d = new Date; + return a = +a, b -= a, function(t) { + return d.setTime(a + b * t), d; + }; +}); + + +/***/ }), +/* 157 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__value__ = __webpack_require__(78); + + +/* harmony default export */ __webpack_exports__["a"] = (function(a, b) { + var i = {}, + c = {}, + k; + + if (a === null || typeof a !== "object") a = {}; + if (b === null || typeof b !== "object") b = {}; + + for (k in b) { + if (k in a) { + i[k] = Object(__WEBPACK_IMPORTED_MODULE_0__value__["a" /* default */])(a[k], b[k]); + } else { + c[k] = b[k]; + } + } + + return function(t) { + for (k in i) c[k] = i[k](t); + return c; + }; +}); + + +/***/ }), +/* 158 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__number__ = __webpack_require__(45); + + +var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, + reB = new RegExp(reA.source, "g"); + +function zero(b) { + return function() { + return b; + }; +} + +function one(b) { + return function(t) { + return b(t) + ""; + }; +} + +/* harmony default export */ __webpack_exports__["a"] = (function(a, b) { + var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b + am, // current match in a + bm, // current match in b + bs, // string preceding current number in b, if any + i = -1, // index in s + s = [], // string constants and placeholders + q = []; // number interpolators + + // Coerce inputs to strings. + a = a + "", b = b + ""; + + // Interpolate pairs of numbers in a & b. + while ((am = reA.exec(a)) + && (bm = reB.exec(b))) { + if ((bs = bm.index) > bi) { // a string precedes the next number in b + bs = b.slice(bi, bs); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match + if (s[i]) s[i] += bm; // coalesce with previous string + else s[++i] = bm; + } else { // interpolate non-matching numbers + s[++i] = null; + q.push({i: i, x: Object(__WEBPACK_IMPORTED_MODULE_0__number__["a" /* default */])(am, bm)}); + } + bi = reB.lastIndex; + } + + // Add remains of b. + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + + // Special optimization for only a single match. + // Otherwise, interpolate each of the numbers and rejoin the string. + return s.length < 2 ? (q[0] + ? one(q[0].x) + : zero(b)) + : (b = q.length, function(t) { + for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }); +}); + + +/***/ }), +/* 159 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__transition_schedule__ = __webpack_require__(8); + + +/* harmony default export */ __webpack_exports__["a"] = (function(node, name) { + var schedules = node.__transition, + schedule, + active, + empty = true, + i; + + if (!schedules) return; + + name = name == null ? null : name + ""; + + for (i in schedules) { + if ((schedule = schedules[i]).name !== name) { empty = false; continue; } + active = schedule.state > __WEBPACK_IMPORTED_MODULE_0__transition_schedule__["d" /* STARTING */] && schedule.state < __WEBPACK_IMPORTED_MODULE_0__transition_schedule__["b" /* ENDING */]; + schedule.state = __WEBPACK_IMPORTED_MODULE_0__transition_schedule__["a" /* ENDED */]; + schedule.timer.stop(); + if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group); + delete schedules[i]; + } + + if (empty) delete node.__transition; +}); + + +/***/ }), +/* 160 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_color__ = __webpack_require__(9); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(7); + + + +/* harmony default export */ __webpack_exports__["a"] = (function(a, b) { + var c; + return (typeof b === "number" ? __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__["m" /* interpolateNumber */] + : b instanceof __WEBPACK_IMPORTED_MODULE_0_d3_color__["a" /* color */] ? __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__["o" /* interpolateRgb */] + : (c = Object(__WEBPACK_IMPORTED_MODULE_0_d3_color__["a" /* color */])(b)) ? (b = c, __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__["o" /* interpolateRgb */]) + : __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__["s" /* interpolateString */])(a, b); +}); + + +/***/ }), +/* 161 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__src_linear__ = __webpack_require__(351); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "y", function() { return __WEBPACK_IMPORTED_MODULE_0__src_linear__["a"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__src_quad__ = __webpack_require__(352); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "D", function() { return __WEBPACK_IMPORTED_MODULE_1__src_quad__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "E", function() { return __WEBPACK_IMPORTED_MODULE_1__src_quad__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "G", function() { return __WEBPACK_IMPORTED_MODULE_1__src_quad__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "F", function() { return __WEBPACK_IMPORTED_MODULE_1__src_quad__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__src_cubic__ = __webpack_require__(353); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "m", function() { return __WEBPACK_IMPORTED_MODULE_2__src_cubic__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "n", function() { return __WEBPACK_IMPORTED_MODULE_2__src_cubic__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "p", function() { return __WEBPACK_IMPORTED_MODULE_2__src_cubic__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "o", function() { return __WEBPACK_IMPORTED_MODULE_2__src_cubic__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__src_poly__ = __webpack_require__(354); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "z", function() { return __WEBPACK_IMPORTED_MODULE_3__src_poly__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "A", function() { return __WEBPACK_IMPORTED_MODULE_3__src_poly__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "C", function() { return __WEBPACK_IMPORTED_MODULE_3__src_poly__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "B", function() { return __WEBPACK_IMPORTED_MODULE_3__src_poly__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__src_sin__ = __webpack_require__(355); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "H", function() { return __WEBPACK_IMPORTED_MODULE_4__src_sin__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "I", function() { return __WEBPACK_IMPORTED_MODULE_4__src_sin__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "K", function() { return __WEBPACK_IMPORTED_MODULE_4__src_sin__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "J", function() { return __WEBPACK_IMPORTED_MODULE_4__src_sin__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__src_exp__ = __webpack_require__(356); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "u", function() { return __WEBPACK_IMPORTED_MODULE_5__src_exp__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "v", function() { return __WEBPACK_IMPORTED_MODULE_5__src_exp__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "x", function() { return __WEBPACK_IMPORTED_MODULE_5__src_exp__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "w", function() { return __WEBPACK_IMPORTED_MODULE_5__src_exp__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__src_circle__ = __webpack_require__(357); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "i", function() { return __WEBPACK_IMPORTED_MODULE_6__src_circle__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "j", function() { return __WEBPACK_IMPORTED_MODULE_6__src_circle__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "l", function() { return __WEBPACK_IMPORTED_MODULE_6__src_circle__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "k", function() { return __WEBPACK_IMPORTED_MODULE_6__src_circle__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7__src_bounce__ = __webpack_require__(358); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return __WEBPACK_IMPORTED_MODULE_7__src_bounce__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "f", function() { return __WEBPACK_IMPORTED_MODULE_7__src_bounce__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "h", function() { return __WEBPACK_IMPORTED_MODULE_7__src_bounce__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "g", function() { return __WEBPACK_IMPORTED_MODULE_7__src_bounce__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__src_back__ = __webpack_require__(359); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return __WEBPACK_IMPORTED_MODULE_8__src_back__["b"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return __WEBPACK_IMPORTED_MODULE_8__src_back__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return __WEBPACK_IMPORTED_MODULE_8__src_back__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return __WEBPACK_IMPORTED_MODULE_8__src_back__["b"]; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__src_elastic__ = __webpack_require__(360); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "q", function() { return __WEBPACK_IMPORTED_MODULE_9__src_elastic__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "r", function() { return __WEBPACK_IMPORTED_MODULE_9__src_elastic__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "t", function() { return __WEBPACK_IMPORTED_MODULE_9__src_elastic__["c"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "s", function() { return __WEBPACK_IMPORTED_MODULE_9__src_elastic__["b"]; }); + + + + + + + + + + + + + + + + + + + + + +/***/ }), +/* 162 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return cos; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "d", function() { return sin; }); +/* unused harmony export pi */ +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return halfPi; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "e", function() { return tau; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return max; }); +var cos = Math.cos; +var sin = Math.sin; +var pi = Math.PI; +var halfPi = pi / 2; +var tau = pi * 2; +var max = Math.max; + + +/***/ }), +/* 163 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = x; +/* harmony export (immutable) */ __webpack_exports__["c"] = y; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_dispatch__ = __webpack_require__(16); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_d3_collection__ = __webpack_require__(31); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_d3_timer__ = __webpack_require__(46); + + + + +function x(d) { + return d.x; +} + +function y(d) { + return d.y; +} + +var initialRadius = 10, + initialAngle = Math.PI * (3 - Math.sqrt(5)); + +/* harmony default export */ __webpack_exports__["a"] = (function(nodes) { + var simulation, + alpha = 1, + alphaMin = 0.001, + alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), + alphaTarget = 0, + velocityDecay = 0.6, + forces = Object(__WEBPACK_IMPORTED_MODULE_1_d3_collection__["c" /* map */])(), + stepper = Object(__WEBPACK_IMPORTED_MODULE_2_d3_timer__["d" /* timer */])(step), + event = Object(__WEBPACK_IMPORTED_MODULE_0_d3_dispatch__["a" /* dispatch */])("tick", "end"); + + if (nodes == null) nodes = []; + + function step() { + tick(); + event.call("tick", simulation); + if (alpha < alphaMin) { + stepper.stop(); + event.call("end", simulation); + } + } + + function tick() { + var i, n = nodes.length, node; + + alpha += (alphaTarget - alpha) * alphaDecay; + + forces.each(function(force) { + force(alpha); + }); + + for (i = 0; i < n; ++i) { + node = nodes[i]; + if (node.fx == null) node.x += node.vx *= velocityDecay; + else node.x = node.fx, node.vx = 0; + if (node.fy == null) node.y += node.vy *= velocityDecay; + else node.y = node.fy, node.vy = 0; + } + } + + function initializeNodes() { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.index = i; + if (isNaN(node.x) || isNaN(node.y)) { + var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle; + node.x = radius * Math.cos(angle); + node.y = radius * Math.sin(angle); + } + if (isNaN(node.vx) || isNaN(node.vy)) { + node.vx = node.vy = 0; + } + } + } + + function initializeForce(force) { + if (force.initialize) force.initialize(nodes); + return force; + } + + initializeNodes(); + + return simulation = { + tick: tick, + + restart: function() { + return stepper.restart(step), simulation; + }, + + stop: function() { + return stepper.stop(), simulation; + }, + + nodes: function(_) { + return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes; + }, + + alpha: function(_) { + return arguments.length ? (alpha = +_, simulation) : alpha; + }, + + alphaMin: function(_) { + return arguments.length ? (alphaMin = +_, simulation) : alphaMin; + }, + + alphaDecay: function(_) { + return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; + }, + + alphaTarget: function(_) { + return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; + }, + + velocityDecay: function(_) { + return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; + }, + + force: function(name, _) { + return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); + }, + + find: function(x, y, radius) { + var i = 0, + n = nodes.length, + dx, + dy, + d2, + node, + closest; + + if (radius == null) radius = Infinity; + else radius *= radius; + + for (i = 0; i < n; ++i) { + node = nodes[i]; + dx = x - node.x; + dy = y - node.y; + d2 = dx * dx + dy * dy; + if (d2 < radius) closest = node, radius = d2; + } + + return closest; + }, + + on: function(name, _) { + return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); + } + }; +}); + + +/***/ }), +/* 164 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__exponent__ = __webpack_require__(48); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__formatGroup__ = __webpack_require__(400); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__formatNumerals__ = __webpack_require__(401); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__formatSpecifier__ = __webpack_require__(165); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__formatTypes__ = __webpack_require__(166); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__formatPrefixAuto__ = __webpack_require__(167); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__identity__ = __webpack_require__(404); + + + + + + + + +var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"]; + +/* harmony default export */ __webpack_exports__["a"] = (function(locale) { + var group = locale.grouping && locale.thousands ? Object(__WEBPACK_IMPORTED_MODULE_1__formatGroup__["a" /* default */])(locale.grouping, locale.thousands) : __WEBPACK_IMPORTED_MODULE_6__identity__["a" /* default */], + currency = locale.currency, + decimal = locale.decimal, + numerals = locale.numerals ? Object(__WEBPACK_IMPORTED_MODULE_2__formatNumerals__["a" /* default */])(locale.numerals) : __WEBPACK_IMPORTED_MODULE_6__identity__["a" /* default */], + percent = locale.percent || "%"; + + function newFormat(specifier) { + specifier = Object(__WEBPACK_IMPORTED_MODULE_3__formatSpecifier__["a" /* default */])(specifier); + + var fill = specifier.fill, + align = specifier.align, + sign = specifier.sign, + symbol = specifier.symbol, + zero = specifier.zero, + width = specifier.width, + comma = specifier.comma, + precision = specifier.precision, + type = specifier.type; + + // Compute the prefix and suffix. + // For SI-prefix, the suffix is lazily computed. + var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", + suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? percent : ""; + + // What format function should we use? + // Is this an integer type? + // Can this type generate exponential notation? + var formatType = __WEBPACK_IMPORTED_MODULE_4__formatTypes__["a" /* default */][type], + maybeSuffix = !type || /[defgprs%]/.test(type); + + // Set the default precision if not specified, + // or clamp the specified precision to the supported range. + // For significant precision, it must be in [1, 21]. + // For fixed precision, it must be in [0, 20]. + precision = precision == null ? (type ? 6 : 12) + : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) + : Math.max(0, Math.min(20, precision)); + + function format(value) { + var valuePrefix = prefix, + valueSuffix = suffix, + i, n, c; + + if (type === "c") { + valueSuffix = formatType(value) + valueSuffix; + value = ""; + } else { + value = +value; + + // Perform the initial formatting. + var valueNegative = value < 0; + value = formatType(Math.abs(value), precision); + + // If a negative value rounds to zero during formatting, treat as positive. + if (valueNegative && +value === 0) valueNegative = false; + + // Compute the prefix and suffix. + valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; + valueSuffix = (type === "s" ? prefixes[8 + __WEBPACK_IMPORTED_MODULE_5__formatPrefixAuto__["b" /* prefixExponent */] / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); + + // Break the formatted value into the integer “value” part that can be + // grouped, and fractional or exponential “suffix” part that is not. + if (maybeSuffix) { + i = -1, n = value.length; + while (++i < n) { + if (c = value.charCodeAt(i), 48 > c || c > 57) { + valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; + value = value.slice(0, i); + break; + } + } + } + } + + // If the fill character is not "0", grouping is applied before padding. + if (comma && !zero) value = group(value, Infinity); + + // Compute the padding. + var length = valuePrefix.length + value.length + valueSuffix.length, + padding = length < width ? new Array(width - length + 1).join(fill) : ""; + + // If the fill character is "0", grouping is applied after padding. + if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; + + // Reconstruct the final output based on the desired alignment. + switch (align) { + case "<": value = valuePrefix + value + valueSuffix + padding; break; + case "=": value = valuePrefix + padding + value + valueSuffix; break; + case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break; + default: value = padding + valuePrefix + value + valueSuffix; break; + } + + return numerals(value); + } + + format.toString = function() { + return specifier + ""; + }; + + return format; + } + + function formatPrefix(specifier, value) { + var f = newFormat((specifier = Object(__WEBPACK_IMPORTED_MODULE_3__formatSpecifier__["a" /* default */])(specifier), specifier.type = "f", specifier)), + e = Math.max(-8, Math.min(8, Math.floor(Object(__WEBPACK_IMPORTED_MODULE_0__exponent__["a" /* default */])(value) / 3))) * 3, + k = Math.pow(10, -e), + prefix = prefixes[8 + e / 3]; + return function(value) { + return f(k * value) + prefix; + }; + } + + return { + format: newFormat, + formatPrefix: formatPrefix + }; +}); + + +/***/ }), +/* 165 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = formatSpecifier; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__formatTypes__ = __webpack_require__(166); + + +// [[fill]align][sign][symbol][0][width][,][.precision][type] +var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i; + +function formatSpecifier(specifier) { + return new FormatSpecifier(specifier); +} + +formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof + +function FormatSpecifier(specifier) { + if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); + + var match, + fill = match[1] || " ", + align = match[2] || ">", + sign = match[3] || "-", + symbol = match[4] || "", + zero = !!match[5], + width = match[6] && +match[6], + comma = !!match[7], + precision = match[8] && +match[8].slice(1), + type = match[9] || ""; + + // The "n" type is an alias for ",g". + if (type === "n") comma = true, type = "g"; + + // Map invalid types to the default format. + else if (!__WEBPACK_IMPORTED_MODULE_0__formatTypes__["a" /* default */][type]) type = ""; + + // If zero fill is specified, padding goes after sign and before digits. + if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; + + this.fill = fill; + this.align = align; + this.sign = sign; + this.symbol = symbol; + this.zero = zero; + this.width = width; + this.comma = comma; + this.precision = precision; + this.type = type; +} + +FormatSpecifier.prototype.toString = function() { + return this.fill + + this.align + + this.sign + + this.symbol + + (this.zero ? "0" : "") + + (this.width == null ? "" : Math.max(1, this.width | 0)) + + (this.comma ? "," : "") + + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) + + this.type; +}; + + +/***/ }), +/* 166 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__formatDefault__ = __webpack_require__(402); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__formatPrefixAuto__ = __webpack_require__(167); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__formatRounded__ = __webpack_require__(403); + + + + +/* harmony default export */ __webpack_exports__["a"] = ({ + "": __WEBPACK_IMPORTED_MODULE_0__formatDefault__["a" /* default */], + "%": function(x, p) { return (x * 100).toFixed(p); }, + "b": function(x) { return Math.round(x).toString(2); }, + "c": function(x) { return x + ""; }, + "d": function(x) { return Math.round(x).toString(10); }, + "e": function(x, p) { return x.toExponential(p); }, + "f": function(x, p) { return x.toFixed(p); }, + "g": function(x, p) { return x.toPrecision(p); }, + "o": function(x) { return Math.round(x).toString(8); }, + "p": function(x, p) { return Object(__WEBPACK_IMPORTED_MODULE_2__formatRounded__["a" /* default */])(x * 100, p); }, + "r": __WEBPACK_IMPORTED_MODULE_2__formatRounded__["a" /* default */], + "s": __WEBPACK_IMPORTED_MODULE_1__formatPrefixAuto__["a" /* default */], + "X": function(x) { return Math.round(x).toString(16).toUpperCase(); }, + "x": function(x) { return Math.round(x).toString(16); } +}); + + +/***/ }), +/* 167 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return prefixExponent; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__formatDecimal__ = __webpack_require__(91); + + +var prefixExponent; + +/* harmony default export */ __webpack_exports__["a"] = (function(x, p) { + var d = Object(__WEBPACK_IMPORTED_MODULE_0__formatDecimal__["a" /* default */])(x, p); + if (!d) return x + ""; + var coefficient = d[0], + exponent = d[1], + i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, + n = coefficient.length; + return i === n ? coefficient + : i > n ? coefficient + new Array(i - n + 1).join("0") + : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) + : "0." + new Array(1 - i).join("0") + Object(__WEBPACK_IMPORTED_MODULE_0__formatDecimal__["a" /* default */])(x, Math.max(0, p + i - 1))[0]; // less than 1y! +}); + + +/***/ }), +/* 168 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return areaRingSum; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return areaStream; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__adder__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__noop__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__stream__ = __webpack_require__(18); + + + + + +var areaRingSum = Object(__WEBPACK_IMPORTED_MODULE_0__adder__["a" /* default */])(); + +var areaSum = Object(__WEBPACK_IMPORTED_MODULE_0__adder__["a" /* default */])(), + lambda00, + phi00, + lambda0, + cosPhi0, + sinPhi0; + +var areaStream = { + point: __WEBPACK_IMPORTED_MODULE_2__noop__["a" /* default */], + lineStart: __WEBPACK_IMPORTED_MODULE_2__noop__["a" /* default */], + lineEnd: __WEBPACK_IMPORTED_MODULE_2__noop__["a" /* default */], + polygonStart: function() { + areaRingSum.reset(); + areaStream.lineStart = areaRingStart; + areaStream.lineEnd = areaRingEnd; + }, + polygonEnd: function() { + var areaRing = +areaRingSum; + areaSum.add(areaRing < 0 ? __WEBPACK_IMPORTED_MODULE_1__math__["w" /* tau */] + areaRing : areaRing); + this.lineStart = this.lineEnd = this.point = __WEBPACK_IMPORTED_MODULE_2__noop__["a" /* default */]; + }, + sphere: function() { + areaSum.add(__WEBPACK_IMPORTED_MODULE_1__math__["w" /* tau */]); + } +}; + +function areaRingStart() { + areaStream.point = areaPointFirst; +} + +function areaRingEnd() { + areaPoint(lambda00, phi00); +} + +function areaPointFirst(lambda, phi) { + areaStream.point = areaPoint; + lambda00 = lambda, phi00 = phi; + lambda *= __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */], phi *= __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */]; + lambda0 = lambda, cosPhi0 = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(phi = phi / 2 + __WEBPACK_IMPORTED_MODULE_1__math__["q" /* quarterPi */]), sinPhi0 = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(phi); +} + +function areaPoint(lambda, phi) { + lambda *= __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */], phi *= __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */]; + phi = phi / 2 + __WEBPACK_IMPORTED_MODULE_1__math__["q" /* quarterPi */]; // half the angular distance from south pole + + // Spherical excess E for a spherical triangle with vertices: south pole, + // previous point, current point. Uses a formula derived from Cagnoli’s + // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2). + var dLambda = lambda - lambda0, + sdLambda = dLambda >= 0 ? 1 : -1, + adLambda = sdLambda * dLambda, + cosPhi = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(phi), + sinPhi = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(phi), + k = sinPhi0 * sinPhi, + u = cosPhi0 * cosPhi + k * Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(adLambda), + v = k * sdLambda * Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(adLambda); + areaRingSum.add(Object(__WEBPACK_IMPORTED_MODULE_1__math__["e" /* atan2 */])(v, u)); + + // Advance the previous points. + lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi; +} + +/* harmony default export */ __webpack_exports__["c"] = (function(object) { + areaSum.reset(); + Object(__WEBPACK_IMPORTED_MODULE_3__stream__["a" /* default */])(object, areaStream); + return areaSum * 2; +}); + + +/***/ }), +/* 169 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = circleStream; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__cartesian__ = __webpack_require__(32); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__constant__ = __webpack_require__(411); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__math__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__rotation__ = __webpack_require__(49); + + + + + +// Generates a circle centered at [0°, 0°], with a given radius and precision. +function circleStream(stream, radius, delta, direction, t0, t1) { + if (!delta) return; + var cosRadius = Object(__WEBPACK_IMPORTED_MODULE_2__math__["g" /* cos */])(radius), + sinRadius = Object(__WEBPACK_IMPORTED_MODULE_2__math__["t" /* sin */])(radius), + step = direction * delta; + if (t0 == null) { + t0 = radius + direction * __WEBPACK_IMPORTED_MODULE_2__math__["w" /* tau */]; + t1 = radius - step / 2; + } else { + t0 = circleRadius(cosRadius, t0); + t1 = circleRadius(cosRadius, t1); + if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * __WEBPACK_IMPORTED_MODULE_2__math__["w" /* tau */]; + } + for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { + point = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["g" /* spherical */])([cosRadius, -sinRadius * Object(__WEBPACK_IMPORTED_MODULE_2__math__["g" /* cos */])(t), -sinRadius * Object(__WEBPACK_IMPORTED_MODULE_2__math__["t" /* sin */])(t)]); + stream.point(point[0], point[1]); + } +} + +// Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0]. +function circleRadius(cosRadius, point) { + point = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["a" /* cartesian */])(point), point[0] -= cosRadius; + Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["e" /* cartesianNormalizeInPlace */])(point); + var radius = Object(__WEBPACK_IMPORTED_MODULE_2__math__["b" /* acos */])(-point[1]); + return ((-point[2] < 0 ? -radius : radius) + __WEBPACK_IMPORTED_MODULE_2__math__["w" /* tau */] - __WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */]) % __WEBPACK_IMPORTED_MODULE_2__math__["w" /* tau */]; +} + +/* harmony default export */ __webpack_exports__["b"] = (function() { + var center = Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])([0, 0]), + radius = Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(90), + precision = Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(6), + ring, + rotate, + stream = {point: point}; + + function point(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= __WEBPACK_IMPORTED_MODULE_2__math__["h" /* degrees */], x[1] *= __WEBPACK_IMPORTED_MODULE_2__math__["h" /* degrees */]; + } + + function circle() { + var c = center.apply(this, arguments), + r = radius.apply(this, arguments) * __WEBPACK_IMPORTED_MODULE_2__math__["r" /* radians */], + p = precision.apply(this, arguments) * __WEBPACK_IMPORTED_MODULE_2__math__["r" /* radians */]; + ring = []; + rotate = Object(__WEBPACK_IMPORTED_MODULE_3__rotation__["b" /* rotateRadians */])(-c[0] * __WEBPACK_IMPORTED_MODULE_2__math__["r" /* radians */], -c[1] * __WEBPACK_IMPORTED_MODULE_2__math__["r" /* radians */], 0).invert; + circleStream(stream, r, p, 1); + c = {type: "Polygon", coordinates: [ring]}; + ring = rotate = null; + return c; + } + + circle.center = function(_) { + return arguments.length ? (center = typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])([+_[0], +_[1]]), circle) : center; + }; + + circle.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(+_), circle) : radius; + }; + + circle.precision = function(_) { + return arguments.length ? (precision = typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(+_), circle) : precision; + }; + + return circle; +}); + + +/***/ }), +/* 170 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(a, b) { + + function compose(x, y) { + return x = a(x, y), b(x[0], x[1]); + } + + if (a.invert && b.invert) compose.invert = function(x, y) { + return x = b.invert(x, y), x && a.invert(x[0], x[1]); + }; + + return compose; +}); + + +/***/ }), +/* 171 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__index__ = __webpack_require__(172); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math__ = __webpack_require__(0); + + + +/* harmony default export */ __webpack_exports__["a"] = (Object(__WEBPACK_IMPORTED_MODULE_0__index__["a" /* default */])( + function() { return true; }, + clipAntimeridianLine, + clipAntimeridianInterpolate, + [-__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */], -__WEBPACK_IMPORTED_MODULE_1__math__["l" /* halfPi */]] +)); + +// Takes a line and cuts into visible segments. Return values: 0 - there were +// intersections or the line was empty; 1 - no intersections; 2 - there were +// intersections, and the first and last segments should be rejoined. +function clipAntimeridianLine(stream) { + var lambda0 = NaN, + phi0 = NaN, + sign0 = NaN, + clean; // no intersections + + return { + lineStart: function() { + stream.lineStart(); + clean = 1; + }, + point: function(lambda1, phi1) { + var sign1 = lambda1 > 0 ? __WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */] : -__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */], + delta = Object(__WEBPACK_IMPORTED_MODULE_1__math__["a" /* abs */])(lambda1 - lambda0); + if (Object(__WEBPACK_IMPORTED_MODULE_1__math__["a" /* abs */])(delta - __WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */]) < __WEBPACK_IMPORTED_MODULE_1__math__["i" /* epsilon */]) { // line crosses a pole + stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? __WEBPACK_IMPORTED_MODULE_1__math__["l" /* halfPi */] : -__WEBPACK_IMPORTED_MODULE_1__math__["l" /* halfPi */]); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + stream.point(lambda1, phi0); + clean = 0; + } else if (sign0 !== sign1 && delta >= __WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */]) { // line crosses antimeridian + if (Object(__WEBPACK_IMPORTED_MODULE_1__math__["a" /* abs */])(lambda0 - sign0) < __WEBPACK_IMPORTED_MODULE_1__math__["i" /* epsilon */]) lambda0 -= sign0 * __WEBPACK_IMPORTED_MODULE_1__math__["i" /* epsilon */]; // handle degeneracies + if (Object(__WEBPACK_IMPORTED_MODULE_1__math__["a" /* abs */])(lambda1 - sign1) < __WEBPACK_IMPORTED_MODULE_1__math__["i" /* epsilon */]) lambda1 -= sign1 * __WEBPACK_IMPORTED_MODULE_1__math__["i" /* epsilon */]; + phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + clean = 0; + } + stream.point(lambda0 = lambda1, phi0 = phi1); + sign0 = sign1; + }, + lineEnd: function() { + stream.lineEnd(); + lambda0 = phi0 = NaN; + }, + clean: function() { + return 2 - clean; // if intersections, rejoin first and last segments + } + }; +} + +function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) { + var cosPhi0, + cosPhi1, + sinLambda0Lambda1 = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(lambda0 - lambda1); + return Object(__WEBPACK_IMPORTED_MODULE_1__math__["a" /* abs */])(sinLambda0Lambda1) > __WEBPACK_IMPORTED_MODULE_1__math__["i" /* epsilon */] + ? Object(__WEBPACK_IMPORTED_MODULE_1__math__["d" /* atan */])((Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(phi0) * (cosPhi1 = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(phi1)) * Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(lambda1) + - Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(phi1) * (cosPhi0 = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(phi0)) * Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(lambda0)) + / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) + : (phi0 + phi1) / 2; +} + +function clipAntimeridianInterpolate(from, to, direction, stream) { + var phi; + if (from == null) { + phi = direction * __WEBPACK_IMPORTED_MODULE_1__math__["l" /* halfPi */]; + stream.point(-__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */], phi); + stream.point(0, phi); + stream.point(__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */], phi); + stream.point(__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */], 0); + stream.point(__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */], -phi); + stream.point(0, -phi); + stream.point(-__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */], -phi); + stream.point(-__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */], 0); + stream.point(-__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */], phi); + } else if (Object(__WEBPACK_IMPORTED_MODULE_1__math__["a" /* abs */])(from[0] - to[0]) > __WEBPACK_IMPORTED_MODULE_1__math__["i" /* epsilon */]) { + var lambda = from[0] < to[0] ? __WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */] : -__WEBPACK_IMPORTED_MODULE_1__math__["o" /* pi */]; + phi = direction * lambda / 2; + stream.point(-lambda, phi); + stream.point(0, phi); + stream.point(lambda, phi); + } else { + stream.point(to[0], to[1]); + } +} + + +/***/ }), +/* 172 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__buffer__ = __webpack_require__(173); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__rejoin__ = __webpack_require__(174); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__math__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__polygonContains__ = __webpack_require__(176); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_d3_array__ = __webpack_require__(4); + + + + + + +/* harmony default export */ __webpack_exports__["a"] = (function(pointVisible, clipLine, interpolate, start) { + return function(sink) { + var line = clipLine(sink), + ringBuffer = Object(__WEBPACK_IMPORTED_MODULE_0__buffer__["a" /* default */])(), + ringSink = clipLine(ringBuffer), + polygonStarted = false, + polygon, + segments, + ring; + + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + clip.point = pointRing; + clip.lineStart = ringStart; + clip.lineEnd = ringEnd; + segments = []; + polygon = []; + }, + polygonEnd: function() { + clip.point = point; + clip.lineStart = lineStart; + clip.lineEnd = lineEnd; + segments = Object(__WEBPACK_IMPORTED_MODULE_4_d3_array__["n" /* merge */])(segments); + var startInside = Object(__WEBPACK_IMPORTED_MODULE_3__polygonContains__["a" /* default */])(polygon, start); + if (segments.length) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + Object(__WEBPACK_IMPORTED_MODULE_1__rejoin__["a" /* default */])(segments, compareIntersection, startInside, interpolate, sink); + } else if (startInside) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + } + if (polygonStarted) sink.polygonEnd(), polygonStarted = false; + segments = polygon = null; + }, + sphere: function() { + sink.polygonStart(); + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + sink.polygonEnd(); + } + }; + + function point(lambda, phi) { + if (pointVisible(lambda, phi)) sink.point(lambda, phi); + } + + function pointLine(lambda, phi) { + line.point(lambda, phi); + } + + function lineStart() { + clip.point = pointLine; + line.lineStart(); + } + + function lineEnd() { + clip.point = point; + line.lineEnd(); + } + + function pointRing(lambda, phi) { + ring.push([lambda, phi]); + ringSink.point(lambda, phi); + } + + function ringStart() { + ringSink.lineStart(); + ring = []; + } + + function ringEnd() { + pointRing(ring[0][0], ring[0][1]); + ringSink.lineEnd(); + + var clean = ringSink.clean(), + ringSegments = ringBuffer.result(), + i, n = ringSegments.length, m, + segment, + point; + + ring.pop(); + polygon.push(ring); + ring = null; + + if (!n) return; + + // No intersections. + if (clean & 1) { + segment = ringSegments[0]; + if ((m = segment.length - 1) > 0) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]); + sink.lineEnd(); + } + return; + } + + // Rejoin connected segments. + // TODO reuse ringBuffer.rejoin()? + if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + + segments.push(ringSegments.filter(validSegment)); + } + + return clip; + }; +}); + +function validSegment(segment) { + return segment.length > 1; +} + +// Intersections are sorted along the clip edge. For both antimeridian cutting +// and circle clipping, the same comparison is used. +function compareIntersection(a, b) { + return ((a = a.x)[0] < 0 ? a[1] - __WEBPACK_IMPORTED_MODULE_2__math__["l" /* halfPi */] - __WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */] : __WEBPACK_IMPORTED_MODULE_2__math__["l" /* halfPi */] - a[1]) + - ((b = b.x)[0] < 0 ? b[1] - __WEBPACK_IMPORTED_MODULE_2__math__["l" /* halfPi */] - __WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */] : __WEBPACK_IMPORTED_MODULE_2__math__["l" /* halfPi */] - b[1]); +} + + +/***/ }), +/* 173 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__noop__ = __webpack_require__(15); + + +/* harmony default export */ __webpack_exports__["a"] = (function() { + var lines = [], + line; + return { + point: function(x, y) { + line.push([x, y]); + }, + lineStart: function() { + lines.push(line = []); + }, + lineEnd: __WEBPACK_IMPORTED_MODULE_0__noop__["a" /* default */], + rejoin: function() { + if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); + }, + result: function() { + var result = lines; + lines = []; + line = null; + return result; + } + }; +}); + + +/***/ }), +/* 174 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__pointEqual__ = __webpack_require__(175); + + +function Intersection(point, points, other, entry) { + this.x = point; + this.z = points; + this.o = other; // another intersection + this.e = entry; // is an entry? + this.v = false; // visited + this.n = this.p = null; // next & previous +} + +// A generalized polygon clipping algorithm: given a polygon that has been cut +// into its visible line segments, and rejoins the segments by interpolating +// along the clip edge. +/* harmony default export */ __webpack_exports__["a"] = (function(segments, compareIntersection, startInside, interpolate, stream) { + var subject = [], + clip = [], + i, + n; + + segments.forEach(function(segment) { + if ((n = segment.length - 1) <= 0) return; + var n, p0 = segment[0], p1 = segment[n], x; + + // If the first and last points of a segment are coincident, then treat as a + // closed ring. TODO if all rings are closed, then the winding order of the + // exterior ring should be checked. + if (Object(__WEBPACK_IMPORTED_MODULE_0__pointEqual__["a" /* default */])(p0, p1)) { + stream.lineStart(); + for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]); + stream.lineEnd(); + return; + } + + subject.push(x = new Intersection(p0, segment, null, true)); + clip.push(x.o = new Intersection(p0, null, x, false)); + subject.push(x = new Intersection(p1, segment, null, false)); + clip.push(x.o = new Intersection(p1, null, x, true)); + }); + + if (!subject.length) return; + + clip.sort(compareIntersection); + link(subject); + link(clip); + + for (i = 0, n = clip.length; i < n; ++i) { + clip[i].e = startInside = !startInside; + } + + var start = subject[0], + points, + point; + + while (1) { + // Find first unvisited intersection. + var current = start, + isSubject = true; + while (current.v) if ((current = current.n) === start) return; + points = current.z; + stream.lineStart(); + do { + current.v = current.o.v = true; + if (current.e) { + if (isSubject) { + for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.n.x, 1, stream); + } + current = current.n; + } else { + if (isSubject) { + points = current.p.z; + for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.p.x, -1, stream); + } + current = current.p; + } + current = current.o; + points = current.z; + isSubject = !isSubject; + } while (!current.v); + stream.lineEnd(); + } +}); + +function link(array) { + if (!(n = array.length)) return; + var n, + i = 0, + a = array[0], + b; + while (++i < n) { + a.n = b = array[i]; + b.p = a; + a = b; + } + a.n = b = array[0]; + b.p = a; +} + + +/***/ }), +/* 175 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(0); + + +/* harmony default export */ __webpack_exports__["a"] = (function(a, b) { + return Object(__WEBPACK_IMPORTED_MODULE_0__math__["a" /* abs */])(a[0] - b[0]) < __WEBPACK_IMPORTED_MODULE_0__math__["i" /* epsilon */] && Object(__WEBPACK_IMPORTED_MODULE_0__math__["a" /* abs */])(a[1] - b[1]) < __WEBPACK_IMPORTED_MODULE_0__math__["i" /* epsilon */]; +}); + + +/***/ }), +/* 176 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__adder__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__cartesian__ = __webpack_require__(32); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__math__ = __webpack_require__(0); + + + + +var sum = Object(__WEBPACK_IMPORTED_MODULE_0__adder__["a" /* default */])(); + +/* harmony default export */ __webpack_exports__["a"] = (function(polygon, point) { + var lambda = point[0], + phi = point[1], + normal = [Object(__WEBPACK_IMPORTED_MODULE_2__math__["t" /* sin */])(lambda), -Object(__WEBPACK_IMPORTED_MODULE_2__math__["g" /* cos */])(lambda), 0], + angle = 0, + winding = 0; + + sum.reset(); + + for (var i = 0, n = polygon.length; i < n; ++i) { + if (!(m = (ring = polygon[i]).length)) continue; + var ring, + m, + point0 = ring[m - 1], + lambda0 = point0[0], + phi0 = point0[1] / 2 + __WEBPACK_IMPORTED_MODULE_2__math__["q" /* quarterPi */], + sinPhi0 = Object(__WEBPACK_IMPORTED_MODULE_2__math__["t" /* sin */])(phi0), + cosPhi0 = Object(__WEBPACK_IMPORTED_MODULE_2__math__["g" /* cos */])(phi0); + + for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) { + var point1 = ring[j], + lambda1 = point1[0], + phi1 = point1[1] / 2 + __WEBPACK_IMPORTED_MODULE_2__math__["q" /* quarterPi */], + sinPhi1 = Object(__WEBPACK_IMPORTED_MODULE_2__math__["t" /* sin */])(phi1), + cosPhi1 = Object(__WEBPACK_IMPORTED_MODULE_2__math__["g" /* cos */])(phi1), + delta = lambda1 - lambda0, + sign = delta >= 0 ? 1 : -1, + absDelta = sign * delta, + antimeridian = absDelta > __WEBPACK_IMPORTED_MODULE_2__math__["o" /* pi */], + k = sinPhi0 * sinPhi1; + + sum.add(Object(__WEBPACK_IMPORTED_MODULE_2__math__["e" /* atan2 */])(k * sign * Object(__WEBPACK_IMPORTED_MODULE_2__math__["t" /* sin */])(absDelta), cosPhi0 * cosPhi1 + k * Object(__WEBPACK_IMPORTED_MODULE_2__math__["g" /* cos */])(absDelta))); + angle += antimeridian ? delta + sign * __WEBPACK_IMPORTED_MODULE_2__math__["w" /* tau */] : delta; + + // Are the longitudes either side of the point’s meridian (lambda), + // and are the latitudes smaller than the parallel (phi)? + if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) { + var arc = Object(__WEBPACK_IMPORTED_MODULE_1__cartesian__["c" /* cartesianCross */])(Object(__WEBPACK_IMPORTED_MODULE_1__cartesian__["a" /* cartesian */])(point0), Object(__WEBPACK_IMPORTED_MODULE_1__cartesian__["a" /* cartesian */])(point1)); + Object(__WEBPACK_IMPORTED_MODULE_1__cartesian__["e" /* cartesianNormalizeInPlace */])(arc); + var intersection = Object(__WEBPACK_IMPORTED_MODULE_1__cartesian__["c" /* cartesianCross */])(normal, arc); + Object(__WEBPACK_IMPORTED_MODULE_1__cartesian__["e" /* cartesianNormalizeInPlace */])(intersection); + var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * Object(__WEBPACK_IMPORTED_MODULE_2__math__["c" /* asin */])(intersection[2]); + if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) { + winding += antimeridian ^ delta >= 0 ? 1 : -1; + } + } + } + } + + // First, determine whether the South pole is inside or outside: + // + // It is inside if: + // * the polygon winds around it in a clockwise direction. + // * the polygon does not (cumulatively) wind around it, but has a negative + // (counter-clockwise) area. + // + // Second, count the (signed) number of times a segment crosses a lambda + // from the point to the South pole. If it is zero, then the point is the + // same side as the South pole. + + return (angle < -__WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */] || angle < __WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */] && sum < -__WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */]) ^ (winding & 1); +}); + + +/***/ }), +/* 177 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__cartesian__ = __webpack_require__(32); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__circle__ = __webpack_require__(169); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__math__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__pointEqual__ = __webpack_require__(175); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__index__ = __webpack_require__(172); + + + + + + +/* harmony default export */ __webpack_exports__["a"] = (function(radius) { + var cr = Object(__WEBPACK_IMPORTED_MODULE_2__math__["g" /* cos */])(radius), + delta = 6 * __WEBPACK_IMPORTED_MODULE_2__math__["r" /* radians */], + smallRadius = cr > 0, + notHemisphere = Object(__WEBPACK_IMPORTED_MODULE_2__math__["a" /* abs */])(cr) > __WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */]; // TODO optimise for this common case + + function interpolate(from, to, direction, stream) { + Object(__WEBPACK_IMPORTED_MODULE_1__circle__["a" /* circleStream */])(stream, radius, delta, direction, from, to); + } + + function visible(lambda, phi) { + return Object(__WEBPACK_IMPORTED_MODULE_2__math__["g" /* cos */])(lambda) * Object(__WEBPACK_IMPORTED_MODULE_2__math__["g" /* cos */])(phi) > cr; + } + + // Takes a line and cuts into visible segments. Return values used for polygon + // clipping: 0 - there were intersections or the line was empty; 1 - no + // intersections 2 - there were intersections, and the first and last segments + // should be rejoined. + function clipLine(stream) { + var point0, // previous point + c0, // code for previous point + v0, // visibility of previous point + v00, // visibility of first point + clean; // no intersections + return { + lineStart: function() { + v00 = v0 = false; + clean = 1; + }, + point: function(lambda, phi) { + var point1 = [lambda, phi], + point2, + v = visible(lambda, phi), + c = smallRadius + ? v ? 0 : code(lambda, phi) + : v ? code(lambda + (lambda < 0 ? __WEBPACK_IMPORTED_MODULE_2__math__["o" /* pi */] : -__WEBPACK_IMPORTED_MODULE_2__math__["o" /* pi */]), phi) : 0; + if (!point0 && (v00 = v0 = v)) stream.lineStart(); + // Handle degeneracies. + // TODO ignore if not clipping polygons. + if (v !== v0) { + point2 = intersect(point0, point1); + if (!point2 || Object(__WEBPACK_IMPORTED_MODULE_3__pointEqual__["a" /* default */])(point0, point2) || Object(__WEBPACK_IMPORTED_MODULE_3__pointEqual__["a" /* default */])(point1, point2)) { + point1[0] += __WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */]; + point1[1] += __WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */]; + v = visible(point1[0], point1[1]); + } + } + if (v !== v0) { + clean = 0; + if (v) { + // outside going in + stream.lineStart(); + point2 = intersect(point1, point0); + stream.point(point2[0], point2[1]); + } else { + // inside going out + point2 = intersect(point0, point1); + stream.point(point2[0], point2[1]); + stream.lineEnd(); + } + point0 = point2; + } else if (notHemisphere && point0 && smallRadius ^ v) { + var t; + // If the codes for two points are different, or are both zero, + // and there this segment intersects with the small circle. + if (!(c & c0) && (t = intersect(point1, point0, true))) { + clean = 0; + if (smallRadius) { + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + } else { + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + } + } + } + if (v && (!point0 || !Object(__WEBPACK_IMPORTED_MODULE_3__pointEqual__["a" /* default */])(point0, point1))) { + stream.point(point1[0], point1[1]); + } + point0 = point1, v0 = v, c0 = c; + }, + lineEnd: function() { + if (v0) stream.lineEnd(); + point0 = null; + }, + // Rejoin first and last segments if there were intersections and the first + // and last points were visible. + clean: function() { + return clean | ((v00 && v0) << 1); + } + }; + } + + // Intersects the great circle between a and b with the clip circle. + function intersect(a, b, two) { + var pa = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["a" /* cartesian */])(a), + pb = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["a" /* cartesian */])(b); + + // We have two planes, n1.p = d1 and n2.p = d2. + // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2). + var n1 = [1, 0, 0], // normal + n2 = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["c" /* cartesianCross */])(pa, pb), + n2n2 = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["d" /* cartesianDot */])(n2, n2), + n1n2 = n2[0], // cartesianDot(n1, n2), + determinant = n2n2 - n1n2 * n1n2; + + // Two polar points. + if (!determinant) return !two && a; + + var c1 = cr * n2n2 / determinant, + c2 = -cr * n1n2 / determinant, + n1xn2 = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["c" /* cartesianCross */])(n1, n2), + A = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["f" /* cartesianScale */])(n1, c1), + B = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["f" /* cartesianScale */])(n2, c2); + Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["b" /* cartesianAddInPlace */])(A, B); + + // Solve |p(t)|^2 = 1. + var u = n1xn2, + w = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["d" /* cartesianDot */])(A, u), + uu = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["d" /* cartesianDot */])(u, u), + t2 = w * w - uu * (Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["d" /* cartesianDot */])(A, A) - 1); + + if (t2 < 0) return; + + var t = Object(__WEBPACK_IMPORTED_MODULE_2__math__["u" /* sqrt */])(t2), + q = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["f" /* cartesianScale */])(u, (-w - t) / uu); + Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["b" /* cartesianAddInPlace */])(q, A); + q = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["g" /* spherical */])(q); + + if (!two) return q; + + // Two intersection points. + var lambda0 = a[0], + lambda1 = b[0], + phi0 = a[1], + phi1 = b[1], + z; + + if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z; + + var delta = lambda1 - lambda0, + polar = Object(__WEBPACK_IMPORTED_MODULE_2__math__["a" /* abs */])(delta - __WEBPACK_IMPORTED_MODULE_2__math__["o" /* pi */]) < __WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */], + meridian = polar || delta < __WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */]; + + if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z; + + // Check that the first point is between a and b. + if (meridian + ? polar + ? phi0 + phi1 > 0 ^ q[1] < (Object(__WEBPACK_IMPORTED_MODULE_2__math__["a" /* abs */])(q[0] - lambda0) < __WEBPACK_IMPORTED_MODULE_2__math__["i" /* epsilon */] ? phi0 : phi1) + : phi0 <= q[1] && q[1] <= phi1 + : delta > __WEBPACK_IMPORTED_MODULE_2__math__["o" /* pi */] ^ (lambda0 <= q[0] && q[0] <= lambda1)) { + var q1 = Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["f" /* cartesianScale */])(u, (-w + t) / uu); + Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["b" /* cartesianAddInPlace */])(q1, A); + return [q, Object(__WEBPACK_IMPORTED_MODULE_0__cartesian__["g" /* spherical */])(q1)]; + } + } + + // Generates a 4-bit vector representing the location of a point relative to + // the small circle's bounding box. + function code(lambda, phi) { + var r = smallRadius ? radius : __WEBPACK_IMPORTED_MODULE_2__math__["o" /* pi */] - radius, + code = 0; + if (lambda < -r) code |= 1; // left + else if (lambda > r) code |= 2; // right + if (phi < -r) code |= 4; // below + else if (phi > r) code |= 8; // above + return code; + } + + return Object(__WEBPACK_IMPORTED_MODULE_4__index__["a" /* default */])(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-__WEBPACK_IMPORTED_MODULE_2__math__["o" /* pi */], radius - __WEBPACK_IMPORTED_MODULE_2__math__["o" /* pi */]]); +}); + + +/***/ }), +/* 178 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__length__ = __webpack_require__(179); + + +var coordinates = [null, null], + object = {type: "LineString", coordinates: coordinates}; + +/* harmony default export */ __webpack_exports__["a"] = (function(a, b) { + coordinates[0] = a; + coordinates[1] = b; + return Object(__WEBPACK_IMPORTED_MODULE_0__length__["a" /* default */])(object); +}); + + +/***/ }), +/* 179 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__adder__ = __webpack_require__(25); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__math__ = __webpack_require__(0); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__noop__ = __webpack_require__(15); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__stream__ = __webpack_require__(18); + + + + + +var lengthSum = Object(__WEBPACK_IMPORTED_MODULE_0__adder__["a" /* default */])(), + lambda0, + sinPhi0, + cosPhi0; + +var lengthStream = { + sphere: __WEBPACK_IMPORTED_MODULE_2__noop__["a" /* default */], + point: __WEBPACK_IMPORTED_MODULE_2__noop__["a" /* default */], + lineStart: lengthLineStart, + lineEnd: __WEBPACK_IMPORTED_MODULE_2__noop__["a" /* default */], + polygonStart: __WEBPACK_IMPORTED_MODULE_2__noop__["a" /* default */], + polygonEnd: __WEBPACK_IMPORTED_MODULE_2__noop__["a" /* default */] +}; + +function lengthLineStart() { + lengthStream.point = lengthPointFirst; + lengthStream.lineEnd = lengthLineEnd; +} + +function lengthLineEnd() { + lengthStream.point = lengthStream.lineEnd = __WEBPACK_IMPORTED_MODULE_2__noop__["a" /* default */]; +} + +function lengthPointFirst(lambda, phi) { + lambda *= __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */], phi *= __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */]; + lambda0 = lambda, sinPhi0 = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(phi), cosPhi0 = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(phi); + lengthStream.point = lengthPoint; +} + +function lengthPoint(lambda, phi) { + lambda *= __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */], phi *= __WEBPACK_IMPORTED_MODULE_1__math__["r" /* radians */]; + var sinPhi = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(phi), + cosPhi = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(phi), + delta = Object(__WEBPACK_IMPORTED_MODULE_1__math__["a" /* abs */])(lambda - lambda0), + cosDelta = Object(__WEBPACK_IMPORTED_MODULE_1__math__["g" /* cos */])(delta), + sinDelta = Object(__WEBPACK_IMPORTED_MODULE_1__math__["t" /* sin */])(delta), + x = cosPhi * sinDelta, + y = cosPhi0 * sinPhi - sinPhi0 * cosPhi * cosDelta, + z = sinPhi0 * sinPhi + cosPhi0 * cosPhi * cosDelta; + lengthSum.add(Object(__WEBPACK_IMPORTED_MODULE_1__math__["e" /* atan2 */])(Object(__WEBPACK_IMPORTED_MODULE_1__math__["u" /* sqrt */])(x * x + y * y), z)); + lambda0 = lambda, sinPhi0 = sinPhi, cosPhi0 = cosPhi; +} + +/* harmony default export */ __webpack_exports__["a"] = (function(object) { + lengthSum.reset(); + Object(__WEBPACK_IMPORTED_MODULE_3__stream__["a" /* default */])(object, lengthStream); + return +lengthSum; +}); + + +/***/ }), +/* 180 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__noop__ = __webpack_require__(15); + + +var x0 = Infinity, + y0 = x0, + x1 = -x0, + y1 = x1; + +var boundsStream = { + point: boundsPoint, + lineStart: __WEBPACK_IMPORTED_MODULE_0__noop__["a" /* default */], + lineEnd: __WEBPACK_IMPORTED_MODULE_0__noop__["a" /* default */], + polygonStart: __WEBPACK_IMPORTED_MODULE_0__noop__["a" /* default */], + polygonEnd: __WEBPACK_IMPORTED_MODULE_0__noop__["a" /* default */], + result: function() { + var bounds = [[x0, y0], [x1, y1]]; + x1 = y1 = -(y0 = x0 = Infinity); + return bounds; + } +}; + +function boundsPoint(x, y) { + if (x < x0) x0 = x; + if (x > x1) x1 = x; + if (y < y0) y0 = y; + if (y > y1) y1 = y; +} + +/* harmony default export */ __webpack_exports__["a"] = (boundsStream); + + +/***/ }), +/* 181 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__conicEqualArea__ = __webpack_require__(93); + + +/* harmony default export */ __webpack_exports__["a"] = (function() { + return Object(__WEBPACK_IMPORTED_MODULE_0__conicEqualArea__["b" /* default */])() + .parallels([29.5, 45.5]) + .scale(1070) + .translate([480, 250]) + .rotate([96, 0]) + .center([-0.6, 38.7]); +}); + + +/***/ }), +/* 182 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = equirectangularRaw; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__index__ = __webpack_require__(10); + + +function equirectangularRaw(lambda, phi) { + return [lambda, phi]; +} + +equirectangularRaw.invert = equirectangularRaw; + +/* harmony default export */ __webpack_exports__["a"] = (function() { + return Object(__WEBPACK_IMPORTED_MODULE_0__index__["a" /* default */])(equirectangularRaw) + .scale(152.63); +}); + + +/***/ }), +/* 183 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = packEnclose; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__enclose__ = __webpack_require__(184); + + +function place(a, b, c) { + var ax = a.x, + ay = a.y, + da = b.r + c.r, + db = a.r + c.r, + dx = b.x - ax, + dy = b.y - ay, + dc = dx * dx + dy * dy; + if (dc) { + var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc), + y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); + c.x = ax + x * dx + y * dy; + c.y = ay + x * dy - y * dx; + } else { + c.x = ax + db; + c.y = ay; + } +} + +function intersects(a, b) { + var dx = b.x - a.x, + dy = b.y - a.y, + dr = a.r + b.r; + return dr * dr - 1e-6 > dx * dx + dy * dy; +} + +function score(node) { + var a = node._, + b = node.next._, + ab = a.r + b.r, + dx = (a.x * b.r + b.x * a.r) / ab, + dy = (a.y * b.r + b.y * a.r) / ab; + return dx * dx + dy * dy; +} + +function Node(circle) { + this._ = circle; + this.next = null; + this.previous = null; +} + +function packEnclose(circles) { + if (!(n = circles.length)) return 0; + + var a, b, c, n, aa, ca, i, j, k, sj, sk; + + // Place the first circle. + a = circles[0], a.x = 0, a.y = 0; + if (!(n > 1)) return a.r; + + // Place the second circle. + b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0; + if (!(n > 2)) return a.r + b.r; + + // Place the third circle. + place(b, a, c = circles[2]); + + // Initialize the front-chain using the first three circles a, b and c. + a = new Node(a), b = new Node(b), c = new Node(c); + a.next = c.previous = b; + b.next = a.previous = c; + c.next = b.previous = a; + + // Attempt to place each remaining circle… + pack: for (i = 3; i < n; ++i) { + place(a._, b._, c = circles[i]), c = new Node(c); + + // Find the closest intersecting circle on the front-chain, if any. + // “Closeness” is determined by linear distance along the front-chain. + // “Ahead” or “behind” is likewise determined by linear distance. + j = b.next, k = a.previous, sj = b._.r, sk = a._.r; + do { + if (sj <= sk) { + if (intersects(j._, c._)) { + b = j, a.next = b, b.previous = a, --i; + continue pack; + } + sj += j._.r, j = j.next; + } else { + if (intersects(k._, c._)) { + a = k, a.next = b, b.previous = a, --i; + continue pack; + } + sk += k._.r, k = k.previous; + } + } while (j !== k.next); + + // Success! Insert the new circle c between a and b. + c.previous = a, c.next = b, a.next = b.previous = b = c; + + // Compute the new closest circle pair to the centroid. + aa = score(a); + while ((c = c.next) !== b) { + if ((ca = score(c)) < aa) { + a = c, aa = ca; + } + } + b = a.next; + } + + // Compute the enclosing circle of the front chain. + a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = Object(__WEBPACK_IMPORTED_MODULE_0__enclose__["a" /* default */])(a); + + // Translate the circles to put the enclosing circle around the origin. + for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y; + + return c.r; +} + +/* harmony default export */ __webpack_exports__["a"] = (function(circles) { + packEnclose(circles); + return circles; +}); + + +/***/ }), +/* 184 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__array__ = __webpack_require__(450); + + +/* harmony default export */ __webpack_exports__["a"] = (function(circles) { + var i = 0, n = (circles = Object(__WEBPACK_IMPORTED_MODULE_0__array__["a" /* shuffle */])(__WEBPACK_IMPORTED_MODULE_0__array__["b" /* slice */].call(circles))).length, B = [], p, e; + + while (i < n) { + p = circles[i]; + if (e && enclosesWeak(e, p)) ++i; + else e = encloseBasis(B = extendBasis(B, p)), i = 0; + } + + return e; +}); + +function extendBasis(B, p) { + var i, j; + + if (enclosesWeakAll(p, B)) return [p]; + + // If we get here then B must have at least one element. + for (i = 0; i < B.length; ++i) { + if (enclosesNot(p, B[i]) + && enclosesWeakAll(encloseBasis2(B[i], p), B)) { + return [B[i], p]; + } + } + + // If we get here then B must have at least two elements. + for (i = 0; i < B.length - 1; ++i) { + for (j = i + 1; j < B.length; ++j) { + if (enclosesNot(encloseBasis2(B[i], B[j]), p) + && enclosesNot(encloseBasis2(B[i], p), B[j]) + && enclosesNot(encloseBasis2(B[j], p), B[i]) + && enclosesWeakAll(encloseBasis3(B[i], B[j], p), B)) { + return [B[i], B[j], p]; + } + } + } + + // If we get here then something is very wrong. + throw new Error; +} + +function enclosesNot(a, b) { + var dr = a.r - b.r, dx = b.x - a.x, dy = b.y - a.y; + return dr < 0 || dr * dr < dx * dx + dy * dy; +} + +function enclosesWeak(a, b) { + var dr = a.r - b.r + 1e-6, dx = b.x - a.x, dy = b.y - a.y; + return dr > 0 && dr * dr > dx * dx + dy * dy; +} + +function enclosesWeakAll(a, B) { + for (var i = 0; i < B.length; ++i) { + if (!enclosesWeak(a, B[i])) { + return false; + } + } + return true; +} + +function encloseBasis(B) { + switch (B.length) { + case 1: return encloseBasis1(B[0]); + case 2: return encloseBasis2(B[0], B[1]); + case 3: return encloseBasis3(B[0], B[1], B[2]); + } +} + +function encloseBasis1(a) { + return { + x: a.x, + y: a.y, + r: a.r + }; +} + +function encloseBasis2(a, b) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1, + l = Math.sqrt(x21 * x21 + y21 * y21); + return { + x: (x1 + x2 + x21 / l * r21) / 2, + y: (y1 + y2 + y21 / l * r21) / 2, + r: (l + r1 + r2) / 2 + }; +} + +function encloseBasis3(a, b, c) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x3 = c.x, y3 = c.y, r3 = c.r, + a2 = x1 - x2, + a3 = x1 - x3, + b2 = y1 - y2, + b3 = y1 - y3, + c2 = r2 - r1, + c3 = r3 - r1, + d1 = x1 * x1 + y1 * y1 - r1 * r1, + d2 = d1 - x2 * x2 - y2 * y2 + r2 * r2, + d3 = d1 - x3 * x3 - y3 * y3 + r3 * r3, + ab = a3 * b2 - a2 * b3, + xa = (b2 * d3 - b3 * d2) / (ab * 2) - x1, + xb = (b3 * c2 - b2 * c3) / ab, + ya = (a3 * d2 - a2 * d3) / (ab * 2) - y1, + yb = (a2 * c3 - a3 * c2) / ab, + A = xb * xb + yb * yb - 1, + B = 2 * (r1 + xa * xb + ya * yb), + C = xa * xa + ya * ya - r1 * r1, + r = -(A ? (B + Math.sqrt(B * B - 4 * A * C)) / (2 * A) : C / B); + return { + x: x1 + xa + xb * r, + y: y1 + ya + yb * r, + r: r + }; +} + + +/***/ }), +/* 185 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = constantZero; +function constantZero() { + return 0; +} + +/* harmony default export */ __webpack_exports__["b"] = (function(x) { + return function() { + return x; + }; +}); + + +/***/ }), +/* 186 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(node) { + node.x0 = Math.round(node.x0); + node.y0 = Math.round(node.y0); + node.x1 = Math.round(node.x1); + node.y1 = Math.round(node.y1); +}); + + +/***/ }), +/* 187 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__defaultSource__ = __webpack_require__(26); + + +/* harmony default export */ __webpack_exports__["a"] = ((function sourceRandomNormal(source) { + function randomNormal(mu, sigma) { + var x, r; + mu = mu == null ? 0 : +mu; + sigma = sigma == null ? 1 : +sigma; + return function() { + var y; + + // If available, use the second previously-generated uniform random. + if (x != null) y = x, x = null; + + // Otherwise, generate a new x and y. + else do { + x = source() * 2 - 1; + y = source() * 2 - 1; + r = x * x + y * y; + } while (!r || r > 1); + + return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r); + }; + } + + randomNormal.source = sourceRandomNormal; + + return randomNormal; +})(__WEBPACK_IMPORTED_MODULE_0__defaultSource__["a" /* default */])); + + +/***/ }), +/* 188 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__defaultSource__ = __webpack_require__(26); + + +/* harmony default export */ __webpack_exports__["a"] = ((function sourceRandomIrwinHall(source) { + function randomIrwinHall(n) { + return function() { + for (var sum = 0, i = 0; i < n; ++i) sum += source(); + return sum; + }; + } + + randomIrwinHall.source = sourceRandomIrwinHall; + + return randomIrwinHall; +})(__WEBPACK_IMPORTED_MODULE_0__defaultSource__["a" /* default */])); + + +/***/ }), +/* 189 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__request__ = __webpack_require__(100); + + +/* harmony default export */ __webpack_exports__["a"] = (function(defaultMimeType, parse) { + return function(url, row, callback) { + if (arguments.length < 3) callback = row, row = null; + var r = Object(__WEBPACK_IMPORTED_MODULE_0__request__["a" /* default */])(url).mimeType(defaultMimeType); + r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; }; + r.row(row); + return callback ? r.get(callback) : r; + }; +}); + +function responseOf(parse, row) { + return function(request) { + return parse(request.responseText, row); + }; +} + + +/***/ }), +/* 190 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return implicit; }); +/* harmony export (immutable) */ __webpack_exports__["a"] = ordinal; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_collection__ = __webpack_require__(31); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__array__ = __webpack_require__(19); + + + +var implicit = {name: "implicit"}; + +function ordinal(range) { + var index = Object(__WEBPACK_IMPORTED_MODULE_0_d3_collection__["c" /* map */])(), + domain = [], + unknown = implicit; + + range = range == null ? [] : __WEBPACK_IMPORTED_MODULE_1__array__["b" /* slice */].call(range); + + function scale(d) { + var key = d + "", i = index.get(key); + if (!i) { + if (unknown !== implicit) return unknown; + index.set(key, i = domain.push(d)); + } + return range[(i - 1) % range.length]; + } + + scale.domain = function(_) { + if (!arguments.length) return domain.slice(); + domain = [], index = Object(__WEBPACK_IMPORTED_MODULE_0_d3_collection__["c" /* map */])(); + var i = -1, n = _.length, d, key; + while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d)); + return scale; + }; + + scale.range = function(_) { + return arguments.length ? (range = __WEBPACK_IMPORTED_MODULE_1__array__["b" /* slice */].call(_), scale) : range.slice(); + }; + + scale.unknown = function(_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + scale.copy = function() { + return ordinal() + .domain(domain) + .range(range) + .unknown(unknown); + }; + + return scale; +} + + +/***/ }), +/* 191 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(x) { + return +x; +}); + + +/***/ }), +/* 192 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(domain, interval) { + domain = domain.slice(); + + var i0 = 0, + i1 = domain.length - 1, + x0 = domain[i0], + x1 = domain[i1], + t; + + if (x1 < x0) { + t = i0, i0 = i1, i1 = t; + t = x0, x0 = x1, x1 = t; + } + + domain[i0] = interval.floor(x0); + domain[i1] = interval.ceil(x1); + return domain; +}); + + +/***/ }), +/* 193 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = calendar; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_array__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__ = __webpack_require__(7); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_d3_time__ = __webpack_require__(55); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_d3_time_format__ = __webpack_require__(102); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__array__ = __webpack_require__(19); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__continuous__ = __webpack_require__(54); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__nice__ = __webpack_require__(192); + + + + + + + + +var durationSecond = 1000, + durationMinute = durationSecond * 60, + durationHour = durationMinute * 60, + durationDay = durationHour * 24, + durationWeek = durationDay * 7, + durationMonth = durationDay * 30, + durationYear = durationDay * 365; + +function date(t) { + return new Date(t); +} + +function number(t) { + return t instanceof Date ? +t : +new Date(+t); +} + +function calendar(year, month, week, day, hour, minute, second, millisecond, format) { + var scale = Object(__WEBPACK_IMPORTED_MODULE_5__continuous__["b" /* default */])(__WEBPACK_IMPORTED_MODULE_5__continuous__["c" /* deinterpolateLinear */], __WEBPACK_IMPORTED_MODULE_1_d3_interpolate__["m" /* interpolateNumber */]), + invert = scale.invert, + domain = scale.domain; + + var formatMillisecond = format(".%L"), + formatSecond = format(":%S"), + formatMinute = format("%I:%M"), + formatHour = format("%I %p"), + formatDay = format("%a %d"), + formatWeek = format("%b %d"), + formatMonth = format("%B"), + formatYear = format("%Y"); + + var tickIntervals = [ + [second, 1, durationSecond], + [second, 5, 5 * durationSecond], + [second, 15, 15 * durationSecond], + [second, 30, 30 * durationSecond], + [minute, 1, durationMinute], + [minute, 5, 5 * durationMinute], + [minute, 15, 15 * durationMinute], + [minute, 30, 30 * durationMinute], + [ hour, 1, durationHour ], + [ hour, 3, 3 * durationHour ], + [ hour, 6, 6 * durationHour ], + [ hour, 12, 12 * durationHour ], + [ day, 1, durationDay ], + [ day, 2, 2 * durationDay ], + [ week, 1, durationWeek ], + [ month, 1, durationMonth ], + [ month, 3, 3 * durationMonth ], + [ year, 1, durationYear ] + ]; + + function tickFormat(date) { + return (second(date) < date ? formatMillisecond + : minute(date) < date ? formatSecond + : hour(date) < date ? formatMinute + : day(date) < date ? formatHour + : month(date) < date ? (week(date) < date ? formatDay : formatWeek) + : year(date) < date ? formatMonth + : formatYear)(date); + } + + function tickInterval(interval, start, stop, step) { + if (interval == null) interval = 10; + + // If a desired tick count is specified, pick a reasonable tick interval + // based on the extent of the domain and a rough estimate of tick size. + // Otherwise, assume interval is already a time interval and use it. + if (typeof interval === "number") { + var target = Math.abs(stop - start) / interval, + i = Object(__WEBPACK_IMPORTED_MODULE_0_d3_array__["e" /* bisector */])(function(i) { return i[2]; }).right(tickIntervals, target); + if (i === tickIntervals.length) { + step = Object(__WEBPACK_IMPORTED_MODULE_0_d3_array__["A" /* tickStep */])(start / durationYear, stop / durationYear, interval); + interval = year; + } else if (i) { + i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i]; + step = i[1]; + interval = i[0]; + } else { + step = Math.max(Object(__WEBPACK_IMPORTED_MODULE_0_d3_array__["A" /* tickStep */])(start, stop, interval), 1); + interval = millisecond; + } + } + + return step == null ? interval : interval.every(step); + } + + scale.invert = function(y) { + return new Date(invert(y)); + }; + + scale.domain = function(_) { + return arguments.length ? domain(__WEBPACK_IMPORTED_MODULE_4__array__["a" /* map */].call(_, number)) : domain().map(date); + }; + + scale.ticks = function(interval, step) { + var d = domain(), + t0 = d[0], + t1 = d[d.length - 1], + r = t1 < t0, + t; + if (r) t = t0, t0 = t1, t1 = t; + t = tickInterval(interval, t0, t1, step); + t = t ? t.range(t0, t1 + 1) : []; // inclusive stop + return r ? t.reverse() : t; + }; + + scale.tickFormat = function(count, specifier) { + return specifier == null ? tickFormat : format(specifier); + }; + + scale.nice = function(interval, step) { + var d = domain(); + return (interval = tickInterval(interval, d[0], d[d.length - 1], step)) + ? domain(Object(__WEBPACK_IMPORTED_MODULE_6__nice__["a" /* default */])(d, interval)) + : scale; + }; + + scale.copy = function() { + return Object(__WEBPACK_IMPORTED_MODULE_5__continuous__["a" /* copy */])(scale, calendar(year, month, week, day, hour, minute, second, millisecond, format)); + }; + + return scale; +} + +/* harmony default export */ __webpack_exports__["b"] = (function() { + return calendar(__WEBPACK_IMPORTED_MODULE_2_d3_time__["D" /* timeYear */], __WEBPACK_IMPORTED_MODULE_2_d3_time__["n" /* timeMonth */], __WEBPACK_IMPORTED_MODULE_2_d3_time__["B" /* timeWeek */], __WEBPACK_IMPORTED_MODULE_2_d3_time__["a" /* timeDay */], __WEBPACK_IMPORTED_MODULE_2_d3_time__["e" /* timeHour */], __WEBPACK_IMPORTED_MODULE_2_d3_time__["j" /* timeMinute */], __WEBPACK_IMPORTED_MODULE_2_d3_time__["r" /* timeSecond */], __WEBPACK_IMPORTED_MODULE_2_d3_time__["h" /* timeMillisecond */], __WEBPACK_IMPORTED_MODULE_3_d3_time_format__["c" /* timeFormat */]).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]); +}); + + +/***/ }), +/* 194 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = formatLocale; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_time__ = __webpack_require__(55); + + +function localDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); + date.setFullYear(d.y); + return date; + } + return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); +} + +function utcDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); + date.setUTCFullYear(d.y); + return date; + } + return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); +} + +function newYear(y) { + return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0}; +} + +function formatLocale(locale) { + var locale_dateTime = locale.dateTime, + locale_date = locale.date, + locale_time = locale.time, + locale_periods = locale.periods, + locale_weekdays = locale.days, + locale_shortWeekdays = locale.shortDays, + locale_months = locale.months, + locale_shortMonths = locale.shortMonths; + + var periodRe = formatRe(locale_periods), + periodLookup = formatLookup(locale_periods), + weekdayRe = formatRe(locale_weekdays), + weekdayLookup = formatLookup(locale_weekdays), + shortWeekdayRe = formatRe(locale_shortWeekdays), + shortWeekdayLookup = formatLookup(locale_shortWeekdays), + monthRe = formatRe(locale_months), + monthLookup = formatLookup(locale_months), + shortMonthRe = formatRe(locale_shortMonths), + shortMonthLookup = formatLookup(locale_shortMonths); + + var formats = { + "a": formatShortWeekday, + "A": formatWeekday, + "b": formatShortMonth, + "B": formatMonth, + "c": null, + "d": formatDayOfMonth, + "e": formatDayOfMonth, + "f": formatMicroseconds, + "H": formatHour24, + "I": formatHour12, + "j": formatDayOfYear, + "L": formatMilliseconds, + "m": formatMonthNumber, + "M": formatMinutes, + "p": formatPeriod, + "Q": formatUnixTimestamp, + "s": formatUnixTimestampSeconds, + "S": formatSeconds, + "u": formatWeekdayNumberMonday, + "U": formatWeekNumberSunday, + "V": formatWeekNumberISO, + "w": formatWeekdayNumberSunday, + "W": formatWeekNumberMonday, + "x": null, + "X": null, + "y": formatYear, + "Y": formatFullYear, + "Z": formatZone, + "%": formatLiteralPercent + }; + + var utcFormats = { + "a": formatUTCShortWeekday, + "A": formatUTCWeekday, + "b": formatUTCShortMonth, + "B": formatUTCMonth, + "c": null, + "d": formatUTCDayOfMonth, + "e": formatUTCDayOfMonth, + "f": formatUTCMicroseconds, + "H": formatUTCHour24, + "I": formatUTCHour12, + "j": formatUTCDayOfYear, + "L": formatUTCMilliseconds, + "m": formatUTCMonthNumber, + "M": formatUTCMinutes, + "p": formatUTCPeriod, + "Q": formatUnixTimestamp, + "s": formatUnixTimestampSeconds, + "S": formatUTCSeconds, + "u": formatUTCWeekdayNumberMonday, + "U": formatUTCWeekNumberSunday, + "V": formatUTCWeekNumberISO, + "w": formatUTCWeekdayNumberSunday, + "W": formatUTCWeekNumberMonday, + "x": null, + "X": null, + "y": formatUTCYear, + "Y": formatUTCFullYear, + "Z": formatUTCZone, + "%": formatLiteralPercent + }; + + var parses = { + "a": parseShortWeekday, + "A": parseWeekday, + "b": parseShortMonth, + "B": parseMonth, + "c": parseLocaleDateTime, + "d": parseDayOfMonth, + "e": parseDayOfMonth, + "f": parseMicroseconds, + "H": parseHour24, + "I": parseHour24, + "j": parseDayOfYear, + "L": parseMilliseconds, + "m": parseMonthNumber, + "M": parseMinutes, + "p": parsePeriod, + "Q": parseUnixTimestamp, + "s": parseUnixTimestampSeconds, + "S": parseSeconds, + "u": parseWeekdayNumberMonday, + "U": parseWeekNumberSunday, + "V": parseWeekNumberISO, + "w": parseWeekdayNumberSunday, + "W": parseWeekNumberMonday, + "x": parseLocaleDate, + "X": parseLocaleTime, + "y": parseYear, + "Y": parseFullYear, + "Z": parseZone, + "%": parseLiteralPercent + }; + + // These recursive directive definitions must be deferred. + formats.x = newFormat(locale_date, formats); + formats.X = newFormat(locale_time, formats); + formats.c = newFormat(locale_dateTime, formats); + utcFormats.x = newFormat(locale_date, utcFormats); + utcFormats.X = newFormat(locale_time, utcFormats); + utcFormats.c = newFormat(locale_dateTime, utcFormats); + + function newFormat(specifier, formats) { + return function(date) { + var string = [], + i = -1, + j = 0, + n = specifier.length, + c, + pad, + format; + + if (!(date instanceof Date)) date = new Date(+date); + + while (++i < n) { + if (specifier.charCodeAt(i) === 37) { + string.push(specifier.slice(j, i)); + if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i); + else pad = c === "e" ? " " : "0"; + if (format = formats[c]) c = format(date, pad); + string.push(c); + j = i + 1; + } + } + + string.push(specifier.slice(j, i)); + return string.join(""); + }; + } + + function newParse(specifier, newDate) { + return function(string) { + var d = newYear(1900), + i = parseSpecifier(d, specifier, string += "", 0), + week, day; + if (i != string.length) return null; + + // If a UNIX timestamp is specified, return it. + if ("Q" in d) return new Date(d.Q); + + // The am-pm flag is 0 for AM, and 1 for PM. + if ("p" in d) d.H = d.H % 12 + d.p * 12; + + // Convert day-of-week and week-of-year to day-of-year. + if ("V" in d) { + if (d.V < 1 || d.V > 53) return null; + if (!("w" in d)) d.w = 1; + if ("Z" in d) { + week = utcDate(newYear(d.y)), day = week.getUTCDay(); + week = day > 4 || day === 0 ? __WEBPACK_IMPORTED_MODULE_0_d3_time__["P" /* utcMonday */].ceil(week) : Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["P" /* utcMonday */])(week); + week = __WEBPACK_IMPORTED_MODULE_0_d3_time__["F" /* utcDay */].offset(week, (d.V - 1) * 7); + d.y = week.getUTCFullYear(); + d.m = week.getUTCMonth(); + d.d = week.getUTCDate() + (d.w + 6) % 7; + } else { + week = newDate(newYear(d.y)), day = week.getDay(); + week = day > 4 || day === 0 ? __WEBPACK_IMPORTED_MODULE_0_d3_time__["l" /* timeMonday */].ceil(week) : Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["l" /* timeMonday */])(week); + week = __WEBPACK_IMPORTED_MODULE_0_d3_time__["a" /* timeDay */].offset(week, (d.V - 1) * 7); + d.y = week.getFullYear(); + d.m = week.getMonth(); + d.d = week.getDate() + (d.w + 6) % 7; + } + } else if ("W" in d || "U" in d) { + if (!("w" in d)) d.w = "u" in d ? d.u % 7 : "W" in d ? 1 : 0; + day = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay(); + d.m = 0; + d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7; + } + + // If a time zone is specified, all fields are interpreted as UTC and then + // offset according to the specified time zone. + if ("Z" in d) { + d.H += d.Z / 100 | 0; + d.M += d.Z % 100; + return utcDate(d); + } + + // Otherwise, all fields are in local time. + return newDate(d); + }; + } + + function parseSpecifier(d, specifier, string, j) { + var i = 0, + n = specifier.length, + m = string.length, + c, + parse; + + while (i < n) { + if (j >= m) return -1; + c = specifier.charCodeAt(i++); + if (c === 37) { + c = specifier.charAt(i++); + parse = parses[c in pads ? specifier.charAt(i++) : c]; + if (!parse || ((j = parse(d, string, j)) < 0)) return -1; + } else if (c != string.charCodeAt(j++)) { + return -1; + } + } + + return j; + } + + function parsePeriod(d, string, i) { + var n = periodRe.exec(string.slice(i)); + return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseShortWeekday(d, string, i) { + var n = shortWeekdayRe.exec(string.slice(i)); + return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseWeekday(d, string, i) { + var n = weekdayRe.exec(string.slice(i)); + return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseShortMonth(d, string, i) { + var n = shortMonthRe.exec(string.slice(i)); + return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseMonth(d, string, i) { + var n = monthRe.exec(string.slice(i)); + return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseLocaleDateTime(d, string, i) { + return parseSpecifier(d, locale_dateTime, string, i); + } + + function parseLocaleDate(d, string, i) { + return parseSpecifier(d, locale_date, string, i); + } + + function parseLocaleTime(d, string, i) { + return parseSpecifier(d, locale_time, string, i); + } + + function formatShortWeekday(d) { + return locale_shortWeekdays[d.getDay()]; + } + + function formatWeekday(d) { + return locale_weekdays[d.getDay()]; + } + + function formatShortMonth(d) { + return locale_shortMonths[d.getMonth()]; + } + + function formatMonth(d) { + return locale_months[d.getMonth()]; + } + + function formatPeriod(d) { + return locale_periods[+(d.getHours() >= 12)]; + } + + function formatUTCShortWeekday(d) { + return locale_shortWeekdays[d.getUTCDay()]; + } + + function formatUTCWeekday(d) { + return locale_weekdays[d.getUTCDay()]; + } + + function formatUTCShortMonth(d) { + return locale_shortMonths[d.getUTCMonth()]; + } + + function formatUTCMonth(d) { + return locale_months[d.getUTCMonth()]; + } + + function formatUTCPeriod(d) { + return locale_periods[+(d.getUTCHours() >= 12)]; + } + + return { + format: function(specifier) { + var f = newFormat(specifier += "", formats); + f.toString = function() { return specifier; }; + return f; + }, + parse: function(specifier) { + var p = newParse(specifier += "", localDate); + p.toString = function() { return specifier; }; + return p; + }, + utcFormat: function(specifier) { + var f = newFormat(specifier += "", utcFormats); + f.toString = function() { return specifier; }; + return f; + }, + utcParse: function(specifier) { + var p = newParse(specifier, utcDate); + p.toString = function() { return specifier; }; + return p; + } + }; +} + +var pads = {"-": "", "_": " ", "0": "0"}, + numberRe = /^\s*\d+/, // note: ignores next directive + percentRe = /^%/, + requoteRe = /[\\^$*+?|[\]().{}]/g; + +function pad(value, fill, width) { + var sign = value < 0 ? "-" : "", + string = (sign ? -value : value) + "", + length = string.length; + return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); +} + +function requote(s) { + return s.replace(requoteRe, "\\$&"); +} + +function formatRe(names) { + return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); +} + +function formatLookup(names) { + var map = {}, i = -1, n = names.length; + while (++i < n) map[names[i].toLowerCase()] = i; + return map; +} + +function parseWeekdayNumberSunday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 1)); + return n ? (d.w = +n[0], i + n[0].length) : -1; +} + +function parseWeekdayNumberMonday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 1)); + return n ? (d.u = +n[0], i + n[0].length) : -1; +} + +function parseWeekNumberSunday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.U = +n[0], i + n[0].length) : -1; +} + +function parseWeekNumberISO(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.V = +n[0], i + n[0].length) : -1; +} + +function parseWeekNumberMonday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.W = +n[0], i + n[0].length) : -1; +} + +function parseFullYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 4)); + return n ? (d.y = +n[0], i + n[0].length) : -1; +} + +function parseYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; +} + +function parseZone(d, string, i) { + var n = /^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(string.slice(i, i + 6)); + return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1; +} + +function parseMonthNumber(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.m = n[0] - 1, i + n[0].length) : -1; +} + +function parseDayOfMonth(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.d = +n[0], i + n[0].length) : -1; +} + +function parseDayOfYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; +} + +function parseHour24(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.H = +n[0], i + n[0].length) : -1; +} + +function parseMinutes(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.M = +n[0], i + n[0].length) : -1; +} + +function parseSeconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.S = +n[0], i + n[0].length) : -1; +} + +function parseMilliseconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.L = +n[0], i + n[0].length) : -1; +} + +function parseMicroseconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 6)); + return n ? (d.L = Math.floor(n[0] / 1000), i + n[0].length) : -1; +} + +function parseLiteralPercent(d, string, i) { + var n = percentRe.exec(string.slice(i, i + 1)); + return n ? i + n[0].length : -1; +} + +function parseUnixTimestamp(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.Q = +n[0], i + n[0].length) : -1; +} + +function parseUnixTimestampSeconds(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.Q = (+n[0]) * 1000, i + n[0].length) : -1; +} + +function formatDayOfMonth(d, p) { + return pad(d.getDate(), p, 2); +} + +function formatHour24(d, p) { + return pad(d.getHours(), p, 2); +} + +function formatHour12(d, p) { + return pad(d.getHours() % 12 || 12, p, 2); +} + +function formatDayOfYear(d, p) { + return pad(1 + __WEBPACK_IMPORTED_MODULE_0_d3_time__["a" /* timeDay */].count(Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["D" /* timeYear */])(d), d), p, 3); +} + +function formatMilliseconds(d, p) { + return pad(d.getMilliseconds(), p, 3); +} + +function formatMicroseconds(d, p) { + return formatMilliseconds(d, p) + "000"; +} + +function formatMonthNumber(d, p) { + return pad(d.getMonth() + 1, p, 2); +} + +function formatMinutes(d, p) { + return pad(d.getMinutes(), p, 2); +} + +function formatSeconds(d, p) { + return pad(d.getSeconds(), p, 2); +} + +function formatWeekdayNumberMonday(d) { + var day = d.getDay(); + return day === 0 ? 7 : day; +} + +function formatWeekNumberSunday(d, p) { + return pad(__WEBPACK_IMPORTED_MODULE_0_d3_time__["t" /* timeSunday */].count(Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["D" /* timeYear */])(d), d), p, 2); +} + +function formatWeekNumberISO(d, p) { + var day = d.getDay(); + d = (day >= 4 || day === 0) ? Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["v" /* timeThursday */])(d) : __WEBPACK_IMPORTED_MODULE_0_d3_time__["v" /* timeThursday */].ceil(d); + return pad(__WEBPACK_IMPORTED_MODULE_0_d3_time__["v" /* timeThursday */].count(Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["D" /* timeYear */])(d), d) + (Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["D" /* timeYear */])(d).getDay() === 4), p, 2); +} + +function formatWeekdayNumberSunday(d) { + return d.getDay(); +} + +function formatWeekNumberMonday(d, p) { + return pad(__WEBPACK_IMPORTED_MODULE_0_d3_time__["l" /* timeMonday */].count(Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["D" /* timeYear */])(d), d), p, 2); +} + +function formatYear(d, p) { + return pad(d.getFullYear() % 100, p, 2); +} + +function formatFullYear(d, p) { + return pad(d.getFullYear() % 10000, p, 4); +} + +function formatZone(d) { + var z = d.getTimezoneOffset(); + return (z > 0 ? "-" : (z *= -1, "+")) + + pad(z / 60 | 0, "0", 2) + + pad(z % 60, "0", 2); +} + +function formatUTCDayOfMonth(d, p) { + return pad(d.getUTCDate(), p, 2); +} + +function formatUTCHour24(d, p) { + return pad(d.getUTCHours(), p, 2); +} + +function formatUTCHour12(d, p) { + return pad(d.getUTCHours() % 12 || 12, p, 2); +} + +function formatUTCDayOfYear(d, p) { + return pad(1 + __WEBPACK_IMPORTED_MODULE_0_d3_time__["F" /* utcDay */].count(Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["_7" /* utcYear */])(d), d), p, 3); +} + +function formatUTCMilliseconds(d, p) { + return pad(d.getUTCMilliseconds(), p, 3); +} + +function formatUTCMicroseconds(d, p) { + return formatUTCMilliseconds(d, p) + "000"; +} + +function formatUTCMonthNumber(d, p) { + return pad(d.getUTCMonth() + 1, p, 2); +} + +function formatUTCMinutes(d, p) { + return pad(d.getUTCMinutes(), p, 2); +} + +function formatUTCSeconds(d, p) { + return pad(d.getUTCSeconds(), p, 2); +} + +function formatUTCWeekdayNumberMonday(d) { + var dow = d.getUTCDay(); + return dow === 0 ? 7 : dow; +} + +function formatUTCWeekNumberSunday(d, p) { + return pad(__WEBPACK_IMPORTED_MODULE_0_d3_time__["X" /* utcSunday */].count(Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["_7" /* utcYear */])(d), d), p, 2); +} + +function formatUTCWeekNumberISO(d, p) { + var day = d.getUTCDay(); + d = (day >= 4 || day === 0) ? Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["Z" /* utcThursday */])(d) : __WEBPACK_IMPORTED_MODULE_0_d3_time__["Z" /* utcThursday */].ceil(d); + return pad(__WEBPACK_IMPORTED_MODULE_0_d3_time__["Z" /* utcThursday */].count(Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["_7" /* utcYear */])(d), d) + (Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["_7" /* utcYear */])(d).getUTCDay() === 4), p, 2); +} + +function formatUTCWeekdayNumberSunday(d) { + return d.getUTCDay(); +} + +function formatUTCWeekNumberMonday(d, p) { + return pad(__WEBPACK_IMPORTED_MODULE_0_d3_time__["P" /* utcMonday */].count(Object(__WEBPACK_IMPORTED_MODULE_0_d3_time__["_7" /* utcYear */])(d), d), p, 2); +} + +function formatUTCYear(d, p) { + return pad(d.getUTCFullYear() % 100, p, 2); +} + +function formatUTCFullYear(d, p) { + return pad(d.getUTCFullYear() % 10000, p, 4); +} + +function formatUTCZone() { + return "+0000"; +} + +function formatLiteralPercent() { + return "%"; +} + +function formatUnixTimestamp(d) { + return +d; +} + +function formatUnixTimestampSeconds(d) { + return Math.floor(+d / 1000); +} + + +/***/ }), +/* 195 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return isoSpecifier; }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__defaultLocale__ = __webpack_require__(103); + + +var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; + +function formatIsoNative(date) { + return date.toISOString(); +} + +var formatIso = Date.prototype.toISOString + ? formatIsoNative + : Object(__WEBPACK_IMPORTED_MODULE_0__defaultLocale__["d" /* utcFormat */])(isoSpecifier); + +/* harmony default export */ __webpack_exports__["a"] = (formatIso); + + +/***/ }), +/* 196 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_d3_path__ = __webpack_require__(17); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__constant__ = __webpack_require__(20); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__curve_linear__ = __webpack_require__(56); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__line__ = __webpack_require__(104); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__point__ = __webpack_require__(105); + + + + + + +/* harmony default export */ __webpack_exports__["a"] = (function() { + var x0 = __WEBPACK_IMPORTED_MODULE_4__point__["a" /* x */], + x1 = null, + y0 = Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(0), + y1 = __WEBPACK_IMPORTED_MODULE_4__point__["b" /* y */], + defined = Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(true), + context = null, + curve = __WEBPACK_IMPORTED_MODULE_2__curve_linear__["a" /* default */], + output = null; + + function area(data) { + var i, + j, + k, + n = data.length, + d, + defined0 = false, + buffer, + x0z = new Array(n), + y0z = new Array(n); + + if (context == null) output = curve(buffer = Object(__WEBPACK_IMPORTED_MODULE_0_d3_path__["a" /* path */])()); + + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) { + j = i; + output.areaStart(); + output.lineStart(); + } else { + output.lineEnd(); + output.lineStart(); + for (k = i - 1; k >= j; --k) { + output.point(x0z[k], y0z[k]); + } + output.lineEnd(); + output.areaEnd(); + } + } + if (defined0) { + x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); + output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); + } + } + + if (buffer) return output = null, buffer + "" || null; + } + + function arealine() { + return Object(__WEBPACK_IMPORTED_MODULE_3__line__["a" /* default */])().defined(defined).curve(curve).context(context); + } + + area.x = function(_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(+_), x1 = null, area) : x0; + }; + + area.x0 = function(_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(+_), area) : x0; + }; + + area.x1 = function(_) { + return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(+_), area) : x1; + }; + + area.y = function(_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(+_), y1 = null, area) : y0; + }; + + area.y0 = function(_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(+_), area) : y0; + }; + + area.y1 = function(_) { + return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(+_), area) : y1; + }; + + area.lineX0 = + area.lineY0 = function() { + return arealine().x(x0).y(y0); + }; + + area.lineY1 = function() { + return arealine().x(x0).y(y1); + }; + + area.lineX1 = function() { + return arealine().x(x1).y(y0); + }; + + area.defined = function(_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : Object(__WEBPACK_IMPORTED_MODULE_1__constant__["a" /* default */])(!!_), area) : defined; + }; + + area.curve = function(_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve; + }; + + area.context = function(_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; + }; + + return area; +}); + + +/***/ }), +/* 197 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return curveRadialLinear; }); +/* harmony export (immutable) */ __webpack_exports__["b"] = curveRadial; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__linear__ = __webpack_require__(56); + + +var curveRadialLinear = curveRadial(__WEBPACK_IMPORTED_MODULE_0__linear__["a" /* default */]); + +function Radial(curve) { + this._curve = curve; +} + +Radial.prototype = { + areaStart: function() { + this._curve.areaStart(); + }, + areaEnd: function() { + this._curve.areaEnd(); + }, + lineStart: function() { + this._curve.lineStart(); + }, + lineEnd: function() { + this._curve.lineEnd(); + }, + point: function(a, r) { + this._curve.point(r * Math.sin(a), r * -Math.cos(a)); + } +}; + +function curveRadial(curve) { + + function radial(context) { + return new Radial(curve(context)); + } + + radial._curve = curve; + + return radial; +} + + +/***/ }), +/* 198 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["b"] = lineRadial; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__curve_radial__ = __webpack_require__(197); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__line__ = __webpack_require__(104); + + + +function lineRadial(l) { + var c = l.curve; + + l.angle = l.x, delete l.x; + l.radius = l.y, delete l.y; + + l.curve = function(_) { + return arguments.length ? c(Object(__WEBPACK_IMPORTED_MODULE_0__curve_radial__["b" /* default */])(_)) : c()._curve; + }; + + return l; +} + +/* harmony default export */ __webpack_exports__["a"] = (function() { + return lineRadial(Object(__WEBPACK_IMPORTED_MODULE_1__line__["a" /* default */])().curve(__WEBPACK_IMPORTED_MODULE_0__curve_radial__["a" /* curveRadialLinear */])); +}); + + +/***/ }), +/* 199 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = (function(x, y) { + return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)]; +}); + + +/***/ }), +/* 200 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return slice; }); +var slice = Array.prototype.slice; + + +/***/ }), +/* 201 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(37); + + +/* harmony default export */ __webpack_exports__["a"] = ({ + draw: function(context, size) { + var r = Math.sqrt(size / __WEBPACK_IMPORTED_MODULE_0__math__["j" /* pi */]); + context.moveTo(r, 0); + context.arc(0, 0, r, 0, __WEBPACK_IMPORTED_MODULE_0__math__["m" /* tau */]); + } +}); + + +/***/ }), +/* 202 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ({ + draw: function(context, size) { + var r = Math.sqrt(size / 5) / 2; + context.moveTo(-3 * r, -r); + context.lineTo(-r, -r); + context.lineTo(-r, -3 * r); + context.lineTo(r, -3 * r); + context.lineTo(r, -r); + context.lineTo(3 * r, -r); + context.lineTo(3 * r, r); + context.lineTo(r, r); + context.lineTo(r, 3 * r); + context.lineTo(-r, 3 * r); + context.lineTo(-r, r); + context.lineTo(-3 * r, r); + context.closePath(); + } +}); + + +/***/ }), +/* 203 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var tan30 = Math.sqrt(1 / 3), + tan30_2 = tan30 * 2; + +/* harmony default export */ __webpack_exports__["a"] = ({ + draw: function(context, size) { + var y = Math.sqrt(size / tan30_2), + x = y * tan30; + context.moveTo(0, -y); + context.lineTo(x, 0); + context.lineTo(0, y); + context.lineTo(-x, 0); + context.closePath(); + } +}); + + +/***/ }), +/* 204 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__math__ = __webpack_require__(37); + + +var ka = 0.89081309152928522810, + kr = Math.sin(__WEBPACK_IMPORTED_MODULE_0__math__["j" /* pi */] / 10) / Math.sin(7 * __WEBPACK_IMPORTED_MODULE_0__math__["j" /* pi */] / 10), + kx = Math.sin(__WEBPACK_IMPORTED_MODULE_0__math__["m" /* tau */] / 10) * kr, + ky = -Math.cos(__WEBPACK_IMPORTED_MODULE_0__math__["m" /* tau */] / 10) * kr; + +/* harmony default export */ __webpack_exports__["a"] = ({ + draw: function(context, size) { + var r = Math.sqrt(size * ka), + x = kx * r, + y = ky * r; + context.moveTo(0, -r); + context.lineTo(x, y); + for (var i = 1; i < 5; ++i) { + var a = __WEBPACK_IMPORTED_MODULE_0__math__["m" /* tau */] * i / 5, + c = Math.cos(a), + s = Math.sin(a); + context.lineTo(s * r, -c * r); + context.lineTo(c * x - s * y, s * x + c * y); + } + context.closePath(); + } +}); + + +/***/ }), +/* 205 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony default export */ __webpack_exports__["a"] = ({ + draw: function(context, size) { + var w = Math.sqrt(size), + x = -w / 2; + context.rect(x, x, w, w); + } +}); + + +/***/ }), +/* 206 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var sqrt3 = Math.sqrt(3); + +/* harmony default export */ __webpack_exports__["a"] = ({ + draw: function(context, size) { + var y = -Math.sqrt(size / (sqrt3 * 3)); + context.moveTo(0, y * 2); + context.lineTo(-sqrt3 * y, -y); + context.lineTo(sqrt3 * y, -y); + context.closePath(); + } +}); + + +/***/ }), +/* 207 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +var c = -0.5, + s = Math.sqrt(3) / 2, + k = 1 / Math.sqrt(12), + a = (k / 2 + 1) * 3; + +/* harmony default export */ __webpack_exports__["a"] = ({ + draw: function(context, size) { + var r = Math.sqrt(size / a), + x0 = r / 2, + y0 = r * k, + x1 = x0, + y1 = r * k + r, + x2 = -x1, + y2 = y1; + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + context.lineTo(c * x0 - s * y0, s * x0 + c * y0); + context.lineTo(c * x1 - s * y1, s * x1 + c * y1); + context.lineTo(c * x2 - s * y2, s * x2 + c * y2); + context.lineTo(c * x0 + s * y0, c * y0 - s * x0); + context.lineTo(c * x1 + s * y1, c * y1 - s * x1); + context.lineTo(c * x2 + s * y2, c * y2 - s * x2); + context.closePath(); + } +}); + + +/***/ }), +/* 208 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = CardinalClosed; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__noop__ = __webpack_require__(57); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__cardinal__ = __webpack_require__(59); + + + +function CardinalClosed(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +CardinalClosed.prototype = { + areaStart: __WEBPACK_IMPORTED_MODULE_0__noop__["a" /* default */], + areaEnd: __WEBPACK_IMPORTED_MODULE_0__noop__["a" /* default */], + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 2: { + this._context.lineTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + this.point(this._x5, this._y5); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._x3 = x, this._y3 = y; break; + case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; + case 2: this._point = 3; this._x5 = x, this._y5 = y; break; + default: Object(__WEBPACK_IMPORTED_MODULE_1__cardinal__["c" /* point */])(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +/* harmony default export */ __webpack_exports__["b"] = ((function custom(tension) { + + function cardinal(context) { + return new CardinalClosed(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +})(0)); + + +/***/ }), +/* 209 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = CardinalOpen; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__cardinal__ = __webpack_require__(59); + + +function CardinalOpen(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +CardinalOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; + case 3: this._point = 4; // proceed + default: Object(__WEBPACK_IMPORTED_MODULE_0__cardinal__["c" /* point */])(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +/* harmony default export */ __webpack_exports__["b"] = ((function custom(tension) { + + function cardinal(context) { + return new CardinalOpen(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +})(0)); + + +/***/ }), +/* 210 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["c"] = createCell; +/* harmony export (immutable) */ __webpack_exports__["a"] = cellHalfedgeStart; +/* unused harmony export cellHalfedgeEnd */ +/* harmony export (immutable) */ __webpack_exports__["d"] = sortCellHalfedges; +/* harmony export (immutable) */ __webpack_exports__["b"] = clipCells; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Edge__ = __webpack_require__(109); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Diagram__ = __webpack_require__(40); + + + +function createCell(site) { + return __WEBPACK_IMPORTED_MODULE_1__Diagram__["b" /* cells */][site.index] = { + site: site, + halfedges: [] + }; +} + +function cellHalfedgeAngle(cell, edge) { + var site = cell.site, + va = edge.left, + vb = edge.right; + if (site === vb) vb = va, va = site; + if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]); + if (site === va) va = edge[1], vb = edge[0]; + else va = edge[0], vb = edge[1]; + return Math.atan2(va[0] - vb[0], vb[1] - va[1]); +} + +function cellHalfedgeStart(cell, edge) { + return edge[+(edge.left !== cell.site)]; +} + +function cellHalfedgeEnd(cell, edge) { + return edge[+(edge.left === cell.site)]; +} + +function sortCellHalfedges() { + for (var i = 0, n = __WEBPACK_IMPORTED_MODULE_1__Diagram__["b" /* cells */].length, cell, halfedges, j, m; i < n; ++i) { + if ((cell = __WEBPACK_IMPORTED_MODULE_1__Diagram__["b" /* cells */][i]) && (m = (halfedges = cell.halfedges).length)) { + var index = new Array(m), + array = new Array(m); + for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, __WEBPACK_IMPORTED_MODULE_1__Diagram__["e" /* edges */][halfedges[j]]); + index.sort(function(i, j) { return array[j] - array[i]; }); + for (j = 0; j < m; ++j) array[j] = halfedges[index[j]]; + for (j = 0; j < m; ++j) halfedges[j] = array[j]; + } + } +} + +function clipCells(x0, y0, x1, y1) { + var nCells = __WEBPACK_IMPORTED_MODULE_1__Diagram__["b" /* cells */].length, + iCell, + cell, + site, + iHalfedge, + halfedges, + nHalfedges, + start, + startX, + startY, + end, + endX, + endY, + cover = true; + + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = __WEBPACK_IMPORTED_MODULE_1__Diagram__["b" /* cells */][iCell]) { + site = cell.site; + halfedges = cell.halfedges; + iHalfedge = halfedges.length; + + // Remove any dangling clipped edges. + while (iHalfedge--) { + if (!__WEBPACK_IMPORTED_MODULE_1__Diagram__["e" /* edges */][halfedges[iHalfedge]]) { + halfedges.splice(iHalfedge, 1); + } + } + + // Insert any border edges as necessary. + iHalfedge = 0, nHalfedges = halfedges.length; + while (iHalfedge < nHalfedges) { + end = cellHalfedgeEnd(cell, __WEBPACK_IMPORTED_MODULE_1__Diagram__["e" /* edges */][halfedges[iHalfedge]]), endX = end[0], endY = end[1]; + start = cellHalfedgeStart(cell, __WEBPACK_IMPORTED_MODULE_1__Diagram__["e" /* edges */][halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1]; + if (Math.abs(endX - startX) > __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] || Math.abs(endY - startY) > __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */]) { + halfedges.splice(iHalfedge, 0, __WEBPACK_IMPORTED_MODULE_1__Diagram__["e" /* edges */].push(Object(__WEBPACK_IMPORTED_MODULE_0__Edge__["b" /* createBorderEdge */])(site, end, + Math.abs(endX - x0) < __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] && y1 - endY > __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] ? [x0, Math.abs(startX - x0) < __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] ? startY : y1] + : Math.abs(endY - y1) < __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] && x1 - endX > __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] ? [Math.abs(startY - y1) < __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] ? startX : x1, y1] + : Math.abs(endX - x1) < __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] && endY - y0 > __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] ? [x1, Math.abs(startX - x1) < __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] ? startY : y0] + : Math.abs(endY - y0) < __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] && endX - x0 > __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] ? [Math.abs(startY - y0) < __WEBPACK_IMPORTED_MODULE_1__Diagram__["f" /* epsilon */] ? startX : x0, y0] + : null)) - 1); + ++nHalfedges; + } + } + + if (nHalfedges) cover = false; + } + } + + // If there weren’t any edges, have the closest site cover the extent. + // It doesn’t matter which corner of the extent we measure! + if (cover) { + var dx, dy, d2, dc = Infinity; + + for (iCell = 0, cover = null; iCell < nCells; ++iCell) { + if (cell = __WEBPACK_IMPORTED_MODULE_1__Diagram__["b" /* cells */][iCell]) { + site = cell.site; + dx = site[0] - x0; + dy = site[1] - y0; + d2 = dx * dx + dy * dy; + if (d2 < dc) dc = d2, cover = cell; + } + } + + if (cover) { + var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0]; + cover.halfedges.push( + __WEBPACK_IMPORTED_MODULE_1__Diagram__["e" /* edges */].push(Object(__WEBPACK_IMPORTED_MODULE_0__Edge__["b" /* createBorderEdge */])(site = cover.site, v00, v01)) - 1, + __WEBPACK_IMPORTED_MODULE_1__Diagram__["e" /* edges */].push(Object(__WEBPACK_IMPORTED_MODULE_0__Edge__["b" /* createBorderEdge */])(site, v01, v11)) - 1, + __WEBPACK_IMPORTED_MODULE_1__Diagram__["e" /* edges */].push(Object(__WEBPACK_IMPORTED_MODULE_0__Edge__["b" /* createBorderEdge */])(site, v11, v10)) - 1, + __WEBPACK_IMPORTED_MODULE_1__Diagram__["e" /* edges */].push(Object(__WEBPACK_IMPORTED_MODULE_0__Edge__["b" /* createBorderEdge */])(site, v10, v00)) - 1 + ); + } + } + + // Lastly delete any cells with no edges; these were entirely clipped. + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = __WEBPACK_IMPORTED_MODULE_1__Diagram__["b" /* cells */][iCell]) { + if (!cell.halfedges.length) { + delete __WEBPACK_IMPORTED_MODULE_1__Diagram__["b" /* cells */][iCell]; + } + } + } +} + + +/***/ }), +/* 211 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return firstCircle; }); +/* harmony export (immutable) */ __webpack_exports__["a"] = attachCircle; +/* harmony export (immutable) */ __webpack_exports__["b"] = detachCircle; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__RedBlackTree__ = __webpack_require__(108); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Diagram__ = __webpack_require__(40); + + + +var circlePool = []; + +var firstCircle; + +function Circle() { + Object(__WEBPACK_IMPORTED_MODULE_0__RedBlackTree__["a" /* RedBlackNode */])(this); + this.x = + this.y = + this.arc = + this.site = + this.cy = null; +} + +function attachCircle(arc) { + var lArc = arc.P, + rArc = arc.N; + + if (!lArc || !rArc) return; + + var lSite = lArc.site, + cSite = arc.site, + rSite = rArc.site; + + if (lSite === rSite) return; + + var bx = cSite[0], + by = cSite[1], + ax = lSite[0] - bx, + ay = lSite[1] - by, + cx = rSite[0] - bx, + cy = rSite[1] - by; + + var d = 2 * (ax * cy - ay * cx); + if (d >= -__WEBPACK_IMPORTED_MODULE_1__Diagram__["g" /* epsilon2 */]) return; + + var ha = ax * ax + ay * ay, + hc = cx * cx + cy * cy, + x = (cy * ha - ay * hc) / d, + y = (ax * hc - cx * ha) / d; + + var circle = circlePool.pop() || new Circle; + circle.arc = arc; + circle.site = cSite; + circle.x = x + bx; + circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom + + arc.circle = circle; + + var before = null, + node = __WEBPACK_IMPORTED_MODULE_1__Diagram__["c" /* circles */]._; + + while (node) { + if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) { + if (node.L) node = node.L; + else { before = node.P; break; } + } else { + if (node.R) node = node.R; + else { before = node; break; } + } + } + + __WEBPACK_IMPORTED_MODULE_1__Diagram__["c" /* circles */].insert(before, circle); + if (!before) firstCircle = circle; +} + +function detachCircle(arc) { + var circle = arc.circle; + if (circle) { + if (!circle.P) firstCircle = circle.N; + __WEBPACK_IMPORTED_MODULE_1__Diagram__["c" /* circles */].remove(circle); + circlePool.push(circle); + Object(__WEBPACK_IMPORTED_MODULE_0__RedBlackTree__["a" /* RedBlackNode */])(circle); + arc.circle = null; + } +} + + +/***/ }), +/* 212 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (immutable) */ __webpack_exports__["a"] = Transform; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return identity; }); +/* harmony export (immutable) */ __webpack_exports__["b"] = transform; +function Transform(k, x, y) { + this.k = k; + this.x = x; + this.y = y; +} + +Transform.prototype = { + constructor: Transform, + scale: function(k) { + return k === 1 ? this : new Transform(this.k * k, this.x, this.y); + }, + translate: function(x, y) { + return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y); + }, + apply: function(point) { + return [point[0] * this.k + this.x, point[1] * this.k + this.y]; + }, + applyX: function(x) { + return x * this.k + this.x; + }, + applyY: function(y) { + return y * this.k + this.y; + }, + invert: function(location) { + return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; + }, + invertX: function(x) { + return (x - this.x) / this.k; + }, + invertY: function(y) { + return (y - this.y) / this.k; + }, + rescaleX: function(x) { + return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x)); + }, + rescaleY: function(y) { + return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y)); + }, + toString: function() { + return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; + } +}; + +var identity = new Transform(1, 0, 0); + +transform.prototype = Transform.prototype; + +function transform(node) { + return node.__zoom || identity; +} + + +/***/ }), +/* 213 */ +/***/ (function(module, exports) { + +/** + * Obliterator Iterator Class + * =========================== + * + * Simple class representing the library's iterators. + */ + +/** + * Iterator class. + * + * @constructor + * @param {function} next - Next function. + */ +function Iterator(next) { + + // Hiding the given function + Object.defineProperty(this, '_next', { + writable: false, + enumerable: false, + value: next + }); + + // Is the iterator complete? + this.done = false; +} + +/** + * Next function. + * + * @return {object} + */ +// NOTE: maybe this should dropped for performance? +Iterator.prototype.next = function() { + if (this.done) + return {done: true}; + + var step = this._next(); + + if (step.done) + this.done = true; + + return step; +}; + +/** + * If symbols are supported, we add `next` to `Symbol.iterator`. + */ +if (typeof Symbol !== 'undefined') + Iterator.prototype[Symbol.iterator] = function() { + return this; + }; + +/** + * Returning an iterator of the given values. + * + * @param {any...} values - Values. + * @return {Iterator} + */ +Iterator.of = function() { + var args = arguments, + l = args.length, + i = 0; + + return new Iterator(function() { + if (i >= l) + return {done: true}; + + return {done: false, value: args[i++]}; + }); +}; + +/** + * Returning an empty iterator. + * + * @return {Iterator} + */ +Iterator.empty = function() { + var iterator = new Iterator(null); + iterator.done = true; + + return iterator; +}; + +/** + * Returning whether the given value is an iterator. + * + * @param {any} value - Value. + * @return {boolean} + */ +Iterator.is = function(value) { + if (value instanceof Iterator) + return true; + + return ( + typeof value === 'object' && + value !== null && + typeof value.next === 'function' + ); +}; + +/** + * Exporting. + */ +module.exports = Iterator; + + +/***/ }), +/* 214 */ +/***/ (function(module, exports, __webpack_require__) { + +var ListCache = __webpack_require__(63), + stackClear = __webpack_require__(567), + stackDelete = __webpack_require__(568), + stackGet = __webpack_require__(569), + stackHas = __webpack_require__(570), + stackSet = __webpack_require__(571); + +/** + * Creates a stack cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function Stack(entries) { + var data = this.__data__ = new ListCache(entries); + this.size = data.size; +} + +// Add methods to `Stack`. +Stack.prototype.clear = stackClear; +Stack.prototype['delete'] = stackDelete; +Stack.prototype.get = stackGet; +Stack.prototype.has = stackHas; +Stack.prototype.set = stackSet; + +module.exports = Stack; + + +/***/ }), +/* 215 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + +module.exports = freeGlobal; + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(60))) + +/***/ }), +/* 216 */ +/***/ (function(module, exports) { + +/** Used for built-in method references. */ +var funcProto = Function.prototype; + +/** Used to resolve the decompiled source of functions. */ +var funcToString = funcProto.toString; + +/** + * Converts `func` to its source code. + * + * @private + * @param {Function} func The function to convert. + * @returns {string} Returns the source code. + */ +function toSource(func) { + if (func != null) { + try { + return funcToString.call(func); + } catch (e) {} + try { + return (func + ''); + } catch (e) {} + } + return ''; +} + +module.exports = toSource; + + +/***/ }), +/* 217 */ +/***/ (function(module, exports, __webpack_require__) { + +var mapCacheClear = __webpack_require__(578), + mapCacheDelete = __webpack_require__(585), + mapCacheGet = __webpack_require__(587), + mapCacheHas = __webpack_require__(588), + mapCacheSet = __webpack_require__(589); + +/** + * Creates a map cache object to store key-value pairs. + * + * @private + * @constructor + * @param {Array} [entries] The key-value pairs to cache. + */ +function MapCache(entries) { + var index = -1, + length = entries == null ? 0 : entries.length; + + this.clear(); + while (++index < length) { + var entry = entries[index]; + this.set(entry[0], entry[1]); + } +} + +// Add methods to `MapCache`. +MapCache.prototype.clear = mapCacheClear; +MapCache.prototype['delete'] = mapCacheDelete; +MapCache.prototype.get = mapCacheGet; +MapCache.prototype.has = mapCacheHas; +MapCache.prototype.set = mapCacheSet; + +module.exports = MapCache; + + +/***/ }), +/* 218 */ +/***/ (function(module, exports, __webpack_require__) { + +var SetCache = __webpack_require__(590), + arraySome = __webpack_require__(593), + cacheHas = __webpack_require__(594); + +/** Used to compose bitmasks for value comparisons. */ +var COMPARE_PARTIAL_FLAG = 1, + COMPARE_UNORDERED_FLAG = 2; + +/** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. + * @param {Function} customizer The function to customize comparisons. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Object} stack Tracks traversed `array` and `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ +function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { + var isPartial = bitmask & COMPARE_PARTIAL_FLAG, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isPartial && othLength > arrLength)) { + return false; + } + // Assume cyclic values are equal. + var stacked = stack.get(array); + if (stacked && stack.get(other)) { + return stacked == other; + } + var index = -1, + result = true, + seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; + + stack.set(array, other); + stack.set(other, array); + + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index]; + + if (customizer) { + var compared = isPartial + ? customizer(othValue, arrValue, index, other, array, stack) + : customizer(arrValue, othValue, index, array, other, stack); + } + if (compared !== undefined) { + if (compared) { + continue; + } + result = false; + break; + } + // Recursively compare arrays (susceptible to call stack limits). + if (seen) { + if (!arraySome(other, function(othValue, othIndex) { + if (!cacheHas(seen, othIndex) && + (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { + return seen.push(othIndex); + } + })) { + result = false; + break; + } + } else if (!( + arrValue === othValue || + equalFunc(arrValue, othValue, bitmask, customizer, stack) + )) { + result = false; + break; + } + } + stack['delete'](array); + stack['delete'](other); + return result; +} + +module.exports = equalArrays; + + +/***/ }), +/* 219 */ +/***/ (function(module, exports, __webpack_require__) { + +var root = __webpack_require__(11); + +/** Built-in value references. */ +var Uint8Array = root.Uint8Array; + +module.exports = Uint8Array; + + +/***/ }), +/* 220 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseTimes = __webpack_require__(606), + isArguments = __webpack_require__(221), + isArray = __webpack_require__(67), + isBuffer = __webpack_require__(115), + isIndex = __webpack_require__(222), + isTypedArray = __webpack_require__(117); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ +function arrayLikeKeys(value, inherited) { + var isArr = isArray(value), + isArg = !isArr && isArguments(value), + isBuff = !isArr && !isArg && isBuffer(value), + isType = !isArr && !isArg && !isBuff && isTypedArray(value), + skipIndexes = isArr || isArg || isBuff || isType, + result = skipIndexes ? baseTimes(value.length, String) : [], + length = result.length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && ( + // Safari 9 has enumerable `arguments.length` in strict mode. + key == 'length' || + // Node.js 0.10 has enumerable non-index properties on buffers. + (isBuff && (key == 'offset' || key == 'parent')) || + // PhantomJS 2 has enumerable non-index properties on typed arrays. + (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || + // Skip index properties. + isIndex(key, length) + ))) { + result.push(key); + } + } + return result; +} + +module.exports = arrayLikeKeys; + + +/***/ }), +/* 221 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIsArguments = __webpack_require__(607), + isObjectLike = __webpack_require__(22); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Built-in value references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/** + * Checks if `value` is likely an `arguments` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an `arguments` object, + * else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { + return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && + !propertyIsEnumerable.call(value, 'callee'); +}; + +module.exports = isArguments; + + +/***/ }), +/* 222 */ +/***/ (function(module, exports) { + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** Used to detect unsigned integer values. */ +var reIsUint = /^(?:0|[1-9]\d*)$/; + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex(value, length) { + var type = typeof value; + length = length == null ? MAX_SAFE_INTEGER : length; + + return !!length && + (type == 'number' || + (type != 'symbol' && reIsUint.test(value))) && + (value > -1 && value % 1 == 0 && value < length); +} + +module.exports = isIndex; + + +/***/ }), +/* 223 */ +/***/ (function(module, exports) { + +/** Used as references for various `Number` constants. */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + * @example + * + * _.isLength(3); + * // => true + * + * _.isLength(Number.MIN_VALUE); + * // => false + * + * _.isLength(Infinity); + * // => false + * + * _.isLength('3'); + * // => false + */ +function isLength(value) { + return typeof value == 'number' && + value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +module.exports = isLength; + + +/***/ }), +/* 224 */ +/***/ (function(module, exports) { + +/** + * Creates a unary function that invokes `func` with its argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ +function overArg(func, transform) { + return function(arg) { + return func(transform(arg)); + }; +} + +module.exports = overArg; + + +/***/ }), +/* 225 */ +/***/ (function(module, exports) { + +/** + * A faster alternative to `Function#apply`, this function invokes `func` + * with the `this` binding of `thisArg` and the arguments of `args`. + * + * @private + * @param {Function} func The function to invoke. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} args The arguments to invoke `func` with. + * @returns {*} Returns the result of `func`. + */ +function apply(func, thisArg, args) { + switch (args.length) { + case 0: return func.call(thisArg); + case 1: return func.call(thisArg, args[0]); + case 2: return func.call(thisArg, args[0], args[1]); + case 3: return func.call(thisArg, args[0], args[1], args[2]); + } + return func.apply(thisArg, args); +} + +module.exports = apply; + + +/***/ }), +/* 226 */ +/***/ (function(module, exports) { + +/** + * This method returns the first argument it receives. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Util + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'a': 1 }; + * + * console.log(_.identity(object) === object); + * // => true + */ +function identity(value) { + return value; +} + +module.exports = identity; + + +/***/ }), +/* 227 */ +/***/ (function(module, exports, __webpack_require__) { + +var getNative = __webpack_require__(21); + +var defineProperty = (function() { + try { + var func = getNative(Object, 'defineProperty'); + func({}, '', {}); + return func; + } catch (e) {} +}()); + +module.exports = defineProperty; + + +/***/ }), +/* 228 */ +/***/ (function(module, exports, __webpack_require__) { + +var Stack = __webpack_require__(214), + assignMergeValue = __webpack_require__(229), + baseFor = __webpack_require__(627), + baseMergeDeep = __webpack_require__(629), + isObject = __webpack_require__(13), + keysIn = __webpack_require__(121), + safeGet = __webpack_require__(231); + +/** + * The base implementation of `_.merge` without support for multiple sources. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @param {number} srcIndex The index of `source`. + * @param {Function} [customizer] The function to customize merged values. + * @param {Object} [stack] Tracks traversed source values and their merged + * counterparts. + */ +function baseMerge(object, source, srcIndex, customizer, stack) { + if (object === source) { + return; + } + baseFor(source, function(srcValue, key) { + if (isObject(srcValue)) { + stack || (stack = new Stack); + baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); + } + else { + var newValue = customizer + ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) + : undefined; + + if (newValue === undefined) { + newValue = srcValue; + } + assignMergeValue(object, key, newValue); + } + }, keysIn); +} + +module.exports = baseMerge; + + +/***/ }), +/* 229 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseAssignValue = __webpack_require__(120), + eq = __webpack_require__(27); + +/** + * This function is like `assignValue` except that it doesn't assign + * `undefined` values. + * + * @private + * @param {Object} object The object to modify. + * @param {string} key The key of the property to assign. + * @param {*} value The value to assign. + */ +function assignMergeValue(object, key, value) { + if ((value !== undefined && !eq(object[key], value)) || + (value === undefined && !(key in object))) { + baseAssignValue(object, key, value); + } +} + +module.exports = assignMergeValue; + + +/***/ }), +/* 230 */ +/***/ (function(module, exports, __webpack_require__) { + +var overArg = __webpack_require__(224); + +/** Built-in value references. */ +var getPrototype = overArg(Object.getPrototypeOf, Object); + +module.exports = getPrototype; + + +/***/ }), +/* 231 */ +/***/ (function(module, exports) { + +/** + * Gets the value at `key`, unless `key` is "__proto__". + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the property to get. + * @returns {*} Returns the property value. + */ +function safeGet(object, key) { + if (key == '__proto__') { + return; + } + + return object[key]; +} + +module.exports = safeGet; + + +/***/ }), +/* 232 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Obliterator Combinations Function + * ================================== + * + * Iterator returning combinations of the given array. + */ +var Iterator = __webpack_require__(651); + +/** + * Helper mapping indices to items. + */ +function indicesToItems(target, items, indices, r) { + for (var i = 0; i < r; i++) + target[i] = items[indices[i]]; +} + +/** + * Combinations. + * + * @param {array} array - Target array. + * @param {number} r - Size of the subsequences. + * @return {Iterator} + */ +module.exports = function combinations(array, r) { + if (!Array.isArray(array)) + throw new Error('obliterator/combinations: first argument should be an array.'); + + var n = array.length; + + if (typeof r !== 'number') + throw new Error('obliterator/combinations: second argument should be omitted or a number.'); + + if (r > n) + throw new Error('obliterator/combinations: the size of the subsequences should not exceed the length of the array.'); + + if (r === n) + return Iterator.of(array.slice()); + + var indices = new Array(r), + subsequence = new Array(r), + first = true, + i; + + for (i = 0; i < r; i++) + indices[i] = i; + + return new Iterator(function next() { + if (first) { + first = false; + + indicesToItems(subsequence, array, indices, r); + return {value: subsequence}; + } + + if (indices[r - 1]++ < n - 1) { + indicesToItems(subsequence, array, indices, r); + return {value: subsequence}; + } + + i = r - 2; + + while (i >= 0 && indices[i] >= (n - (r - i))) + --i; + + if (i < 0) + return {done: true}; + + indices[i]++; + + while (++i < r) + indices[i] = indices[i - 1] + 1; + + indicesToItems(subsequence, array, indices, r); + return {value: subsequence}; + }); +}; + + +/***/ }), +/* 233 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Graphology Density + * =================== + * + * Functions used to compute the density of the given graph. + */ +var isGraph = __webpack_require__(1); + +/** + * Returns the undirected density. + * + * @param {number} order - Number of nodes in the graph. + * @param {number} size - Number of edges in the graph. + * @return {number} + */ +function undirectedDensity(order, size) { + return 2 * size / (order * (order - 1)); +} + +/** + * Returns the directed density. + * + * @param {number} order - Number of nodes in the graph. + * @param {number} size - Number of edges in the graph. + * @return {number} + */ +function directedDensity(order, size) { + return size / (order * (order - 1)); +} + +/** + * Returns the mixed density. + * + * @param {number} order - Number of nodes in the graph. + * @param {number} size - Number of edges in the graph. + * @return {number} + */ +function mixedDensity(order, size) { + var d = (order * (order - 1)); + + return ( + size / + (d + d / 2) + ); +} + +/** + * Returns the size a multi graph would have if it were a simple one. + * + * @param {Graph} graph - Target graph. + * @return {number} + */ +function simpleSizeForMultiGraphs(graph) { + var nodes = graph.nodes(), + size = 0, + i, + l; + + for (i = 0, l = nodes.length; i < l; i++) { + size += graph.outNeighbors(nodes[i]).length; + size += graph.undirectedNeighbors(nodes[i]).length / 2; + } + + return size; +} + +/** + * Returns the density for the given parameters. + * + * Arity 3: + * @param {boolean} type - Type of density. + * @param {boolean} multi - Compute multi density? + * @param {Graph} graph - Target graph. + * + * Arity 4: + * @param {boolean} type - Type of density. + * @param {boolean} multi - Compute multi density? + * @param {number} order - Number of nodes in the graph. + * @param {number} size - Number of edges in the graph. + * + * @return {number} + */ +function abstractDensity(type, multi, graph) { + var order, + size; + + // Retrieving order & size + if (arguments.length > 3) { + order = graph; + size = arguments[3]; + + if (typeof order !== 'number') + throw new Error('graphology-metrics/density: given order is not a number.'); + + if (typeof size !== 'number') + throw new Error('graphology-metrics/density: given size is not a number.'); + } + else { + + if (!isGraph(graph)) + throw new Error('graphology-metrics/density: given graph is not a valid graphology instance.'); + + order = graph.order; + size = graph.size; + + if (graph.multi && multi === false) + size = simpleSizeForMultiGraphs(graph); + } + + // Guessing type & multi + if (type === null) + type = graph.type; + if (multi === null) + multi = graph.multi; + + // Getting the correct function + var fn; + + if (type === 'undirected') + fn = undirectedDensity; + else if (type === 'directed') + fn = directedDensity; + else + fn = mixedDensity; + + // Applying the function + return fn(order, size); +} + +/** + * Creating the exported functions. + */ +var density = abstractDensity.bind(null, null, null); +density.directedDensity = abstractDensity.bind(null, 'directed', false); +density.undirectedDensity = abstractDensity.bind(null, 'undirected', false); +density.mixedDensity = abstractDensity.bind(null, 'mixed', false); +density.multiDirectedDensity = abstractDensity.bind(null, 'directed', true); +density.multiUndirectedDensity = abstractDensity.bind(null, 'undirected', true); +density.multiMixedDensity = abstractDensity.bind(null, 'mixed', true); + +/** + * Exporting. + */ +module.exports = density; + + +/***/ }), +/* 234 */ +/***/ (function(module, exports) { + +/** + * Graphology mergeStar + * ===================== + * + * Function merging the given star to the graph. + */ + +/** + * Merging the given star to the graph. + * + * @param {Graph} graph - Target graph. + * @param {array} nodes - Nodes to add, first one being the center of the star. + */ +module.exports = function mergeStar(graph, nodes) { + if (nodes.length === 0) + return; + + var node, i, l; + + var center = nodes[0]; + + graph.mergeNode(center); + + for (i = 1, l = nodes.length; i < l; i++) { + node = nodes[i]; + + graph.mergeEdge(center, node); + } +}; + + +/***/ }), +/* 235 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Graphology Unweighted Shortest Path + * ==================================== + * + * Basic algorithms to find the shortest paths between nodes in a graph + * whose edges are not weighted. + */ +var isGraph = __webpack_require__(1), + Queue = __webpack_require__(686); + +/** + * Function attempting to find the shortest path in a graph between + * given source & target or `null` if such a path does not exist. + * + * @param {Graph} graph - Target graph. + * @param {any} source - Source node. + * @param {any} target - Target node. + * @return {array|null} - Found path or `null`. + */ +function bidirectional(graph, source, target) { + if (!isGraph(graph)) + throw new Error('graphology-shortest-path: invalid graphology instance.'); + + if (arguments.length < 3) + throw new Error('graphology-shortest-path: invalid number of arguments. Expecting at least 3.'); + + if (!graph.hasNode(source)) + throw new Error('graphology-shortest-path: the "' + source + '" source node does not exist in the given graph.'); + + if (!graph.hasNode(target)) + throw new Error('graphology-shortest-path: the "' + target + '" target node does not exist in the given graph.'); + + source = '' + source; + target = '' + target; + + // TODO: do we need a self loop to go there? + if (source === target) { + return [source]; + } + + // Binding functions + var getPredecessors, + getSuccessors; + + // TODO: move outside this function + if (graph.type === 'mixed') { + getPredecessors = function(node) { + var result = graph.inNeighbors(node); + + result.push.apply(result, graph.undirectedNeighbors(node)); + return result; + }; + + getSuccessors = function(node) { + var result = graph.outNeighbors(node); + + result.push.apply(result, graph.undirectedNeighbors(node)); + return result; + }; + } + else if (graph.type === 'directed') { + getPredecessors = graph.inNeighbors.bind(graph); + getSuccessors = graph.outNeighbors.bind(graph); + } + else { + getPredecessors = getSuccessors = graph.undirectedNeighbors.bind(graph); + } + + var predecessor = {}, + successor = {}; + + // Predecessor & successor + predecessor[source] = null; + successor[target] = null; + + // Fringes + var forwardFringe = [source], + reverseFringe = [target], + currentFringe, + node, + neighbors, + neighbor, + i, + j, + l, + m; + + var found = false; + + outer: + while (forwardFringe.length && reverseFringe.length) { + if (forwardFringe.length <= reverseFringe.length) { + currentFringe = forwardFringe; + forwardFringe = []; + + for (i = 0, l = currentFringe.length; i < l; i++) { + node = currentFringe[i]; + neighbors = getSuccessors(node); + + for (j = 0, m = neighbors.length; j < m; j++) { + neighbor = neighbors[j]; + + if (!(neighbor in predecessor)) { + forwardFringe.push(neighbor); + predecessor[neighbor] = node; + } + + if (neighbor in successor) { + + // Path is found! + found = true; + break outer; + } + } + } + } + else { + currentFringe = reverseFringe; + reverseFringe = []; + + for (i = 0, l = currentFringe.length; i < l; i++) { + node = currentFringe[i]; + neighbors = getPredecessors(node); + + for (j = 0, m = neighbors.length; j < m; j++) { + neighbor = neighbors[j]; + + if (!(neighbor in successor)) { + reverseFringe.push(neighbor); + successor[neighbor] = node; + } + + if (neighbor in predecessor) { + + // Path is found! + found = true; + break outer; + } + } + } + } + } + + if (!found) + return null; + + var path = []; + + while (neighbor) { + path.unshift(neighbor); + neighbor = predecessor[neighbor]; + } + + neighbor = successor[path[path.length - 1]]; + + while (neighbor) { + path.push(neighbor); + neighbor = successor[neighbor]; + } + + return path.length ? path : null; +} + +/** + * Function attempting to find the shortest path in the graph between the + * given source node & all the other nodes. + * + * @param {Graph} graph - Target graph. + * @param {any} source - Source node. + * @return {object} - The map of found paths. + */ + +// TODO: cutoff option +function singleSource(graph, source) { + if (!isGraph(graph)) + throw new Error('graphology-shortest-path: invalid graphology instance.'); + + if (arguments.length < 2) + throw new Error('graphology-shortest-path: invalid number of arguments. Expecting at least 2.'); + + if (!graph.hasNode(source)) + throw new Error('graphology-shortest-path: the "' + source + '" source node does not exist in the given graph.'); + + source = '' + source; + + var nextLevel = {}, + paths = {}, + currentLevel, + neighbors, + v, + w, + i, + l; + + nextLevel[source] = true; + paths[source] = [source]; + + while (Object.keys(nextLevel).length) { + currentLevel = nextLevel; + nextLevel = {}; + + for (v in currentLevel) { + neighbors = graph.outNeighbors(v); + neighbors.push.apply(neighbors, graph.undirectedNeighbors(v)); + + for (i = 0, l = neighbors.length; i < l; i++) { + w = neighbors[i]; + + if (!paths[w]) { + paths[w] = paths[v].concat(w); + nextLevel[w] = true; + } + } + } + } + + return paths; +} + +/** + * Main polymorphic function taking either only a source or a + * source/target combo. + * + * @param {Graph} graph - Target graph. + * @param {any} source - Source node. + * @param {any} [target] - Target node. + * @return {array|object|null} - The map of found paths. + */ +function shortestPath(graph, source, target) { + if (arguments.length < 3) + return singleSource(graph, source); + + return bidirectional(graph, source, target); +} + +/** + * Function using Ulrik Brandes' method to map single source shortest paths + * from selected node. + * + * [Reference]: + * Ulrik Brandes: A Faster Algorithm for Betweenness Centrality. + * Journal of Mathematical Sociology 25(2):163-177, 2001. + * + * @param {Graph} graph - Target graph. + * @param {any} source - Source node. + * @return {array} - [Stack, Paths, Sigma] + */ +function brandes(graph, source) { + source = '' + source; + + var S = [], + P = {}, + sigma = {}; + + var nodes = graph.nodes(), + Dv, + sigmav, + neighbors, + v, + w, + i, + j, + l, + m; + + for (i = 0, l = nodes.length; i < l; i++) { + v = nodes[i]; + P[v] = []; + sigma[v] = 0; + } + + var D = {}; + + sigma[source] = 1; + D[source] = 0; + + var queue = Queue.of(source); + + while (queue.size) { + v = queue.dequeue(); + S.push(v); + + Dv = D[v]; + sigmav = sigma[v]; + + neighbors = graph + .undirectedNeighbors(v) + .concat(graph.outNeighbors(v)); + + for (j = 0, m = neighbors.length; j < m; j++) { + w = neighbors[j]; + + if (!(w in D)) { + queue.enqueue(w); + D[w] = Dv + 1; + } + + if (D[w] === Dv + 1) { + sigma[w] += sigmav; + P[w].push(v); + } + } + } + + return [S, P, sigma]; +} + +/** + * Exporting. + */ +shortestPath.bidirectional = bidirectional; +shortestPath.singleSource = singleSource; +shortestPath.brandes = brandes; + +module.exports = shortestPath; + + +/***/ }), +/* 236 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Graphology Dijkstra Shortest Path + * ================================== + * + * Graphology implementation of Dijkstra shortest path for weighted graphs. + */ +var isGraph = __webpack_require__(1), + Heap = __webpack_require__(688); + +/** + * Defaults & helpers. + */ +var DEFAULTS = { + weightAttribute: 'weight' +}; + +function DIJKSTRA_HEAP_COMPARATOR(a, b) { + if (a[0] > b[0]) + return 1; + if (a[0] < b[0]) + return -1; + + if (a[1] > b[1]) + return 1; + if (a[1] < b[1]) + return -1; + + if (a[2] > b[2]) + return 1; + if (a[2] < b[2]) + return -1; + + return 0; +} + +function BRANDES_DIJKSTRA_HEAP_COMPARATOR(a, b) { + if (a[0] > b[0]) + return 1; + if (a[0] < b[0]) + return -1; + + if (a[1] > b[1]) + return 1; + if (a[1] < b[1]) + return -1; + + if (a[2] > b[2]) + return 1; + if (a[2] < b[2]) + return -1; + + if (a[3] > b[3]) + return 1; + if (a[3] < b[3]) + return - 1; + + return 0; +} + +var GET_NEIGHBORS = [ + function(graph, node) { + return graph + .undirectedEdges(node) + .concat(graph.outEdges(node)); + }, + function(graph, node) { + return graph + .undirectedEdges(node) + .concat(graph.inEdges(node)); + } +]; + +/** + * Bidirectional Dijkstra shortest path between source & target node abstract. + * + * Note that this implementation was basically copied from networkx. + * + * @param {Graph} graph - The graphology instance. + * @param {string} source - Source node. + * @param {string} target - Target node. + * @param {string} weightAttribute - Name of the weight attribute. + * @param {array} - The found path if any and its cost. + */ +function abstractBidirectionalDijkstra(graph, source, target, weightAttribute) { + source = '' + source; + target = '' + target; + + // Sanity checks + if (!isGraph(graph)) + throw new Error('graphology-shortest-path/dijkstra: invalid graphology instance.'); + + if (source && !graph.hasNode(source)) + throw new Error('graphology-shortest-path/dijkstra: the "' + source + '" source node does not exist in the given graph.'); + + if (target && !graph.hasNode(target)) + throw new Error('graphology-shortest-path/dijkstra: the "' + target + '" target node does not exist in the given graph.'); + + weightAttribute = weightAttribute || DEFAULTS.weightAttribute; + + var getWeight = function(e) { + return graph.getEdgeAttribute(e, weightAttribute); + }; + + if (source === target) + return [0, [source]]; + + var distances = [{}, {}], + paths = [{}, {}], + fringe = [new Heap(DIJKSTRA_HEAP_COMPARATOR), new Heap(DIJKSTRA_HEAP_COMPARATOR)], + seen = [{}, {}]; + + paths[0][source] = [source]; + paths[1][target] = [target]; + + seen[0][source] = 0; + seen[1][target] = 0; + + var finalPath, + finalDistance = Infinity; + + var count = 0, + dir = 1, + item, + edges, + cost, + d, + v, + u, + e, + i, + l; + + fringe[0].push([0, count++, source]); + fringe[1].push([0, count++, target]); + + while (fringe[0].size && fringe[1].size) { + + // Swapping direction + dir = 1 - dir; + + item = fringe[dir].pop(); + d = item[0]; + v = item[2]; + + if (v in distances[dir]) + continue; + + distances[dir][v] = d; + + // Shortest path is found? + if (v in distances[1 - dir]) + return [finalDistance, finalPath]; + + edges = GET_NEIGHBORS[dir](graph, v); + + for (i = 0, l = edges.length; i < l; i++) { + e = edges[i]; + u = graph.opposite(v, e); + cost = distances[dir][v] + getWeight(e); + + if (u in distances[dir] && cost < distances[dir][u]) { + throw Error('graphology-shortest-path/dijkstra: contradictory paths found. Do some of your edges have a negative weight?'); + } + else if (!(u in seen[dir]) || cost < seen[dir][u]) { + seen[dir][u] = cost; + fringe[dir].push([cost, count++, u]); + paths[dir][u] = paths[dir][v].concat(u); + + if (u in seen[0] && u in seen[1]) { + d = seen[0][u] + seen[1][u]; + + if (!finalDistance || finalDistance > d) { + finalDistance = d; + finalPath = paths[0][u].concat(paths[1][u].slice(0, -1).reverse()); + } + } + } + } + } + + // No path was found + return [Infinity, null]; +} + +/** + * Multisource Dijkstra shortest path abstract function. This function is the + * basis of the algorithm that every other will use. + * + * Note that this implementation was basically copied from networkx. + * TODO: it might be more performant to use a dedicated objet for the heap's + * items. + * + * @param {Graph} graph - The graphology instance. + * @param {array} sources - A list of sources. + * @param {string} weightAttribute - Name of the weight attribute. + * @param {number} cutoff - Maximum depth of the search. + * @param {string} target - Optional target to reach. + * @param {object} paths - Optional paths object to maintain. + * @return {object} - Returns the paths. + */ +function abstractDijkstraMultisource( + graph, + sources, + weightAttribute, + cutoff, + target, + paths +) { + + if (!isGraph(graph)) + throw new Error('graphology-shortest-path/dijkstra: invalid graphology instance.'); + + if (target && !graph.hasNode(target)) + throw new Error('graphology-shortest-path/dijkstra: the "' + target + '" target node does not exist in the given graph.'); + + weightAttribute = weightAttribute || DEFAULTS.weightAttribute; + + // Building necessary functions + var getWeight = function(edge) { + return graph.getEdgeAttribute(edge, weightAttribute); + }; + + var distances = {}, + seen = {}, + fringe = new Heap(DIJKSTRA_HEAP_COMPARATOR); + + var count = 0, + edges, + item, + cost, + v, + u, + e, + d, + i, + j, + l, + m; + + for (i = 0, l = sources.length; i < l; i++) { + v = sources[i]; + seen[v] = 0; + fringe.push([0, count++, v]); + + if (paths) + paths[v] = [v]; + } + + while (fringe.size) { + item = fringe.pop(); + d = item[0]; + v = item[2]; + + if (v in distances) + continue; + + distances[v] = d; + + if (v === target) + break; + + edges = graph + .undirectedEdges(v) + .concat(graph.outEdges(v)); + + for (j = 0, m = edges.length; j < m; j++) { + e = edges[j]; + u = graph.opposite(v, e); + cost = getWeight(e) + distances[v]; + + if (cutoff && cost > cutoff) + continue; + + if (u in distances && cost < distances[u]) { + throw Error('graphology-shortest-path/dijkstra: contradictory paths found. Do some of your edges have a negative weight?'); + } + + else if (!(u in seen) || cost < seen[u]) { + seen[u] = cost; + fringe.push([cost, count++, u]); + + if (paths) + paths[u] = paths[v].concat(u); + } + } + } + + return distances; +} + +/** + * Single source Dijkstra shortest path between given node & other nodes in + * the graph. + * + * @param {Graph} graph - The graphology instance. + * @param {string} source - Source node. + * @param {string} weightAttribute - Name of the weight attribute. + * @return {object} - An object of found paths. + */ +function singleSourceDijkstra(graph, source, weightAttribute) { + var paths = {}; + + abstractDijkstraMultisource( + graph, + [source], + weightAttribute, + 0, + null, + paths + ); + + return paths; +} + +function bidirectionalDijkstra(graph, source, target, weightAttribute) { + return abstractBidirectionalDijkstra(graph, source, target, weightAttribute)[1]; +} + +/** + * Function using Ulrik Brandes' method to map single source shortest paths + * from selected node. + * + * [Reference]: + * Ulrik Brandes: A Faster Algorithm for Betweenness Centrality. + * Journal of Mathematical Sociology 25(2):163-177, 2001. + * + * @param {Graph} graph - Target graph. + * @param {any} source - Source node. + * @param {string} weightAttribute - Name of the weight attribute. + * @return {array} - [Stack, Paths, Sigma] + */ +function brandes(graph, source, weightAttribute) { + source = '' + source; + weightAttribute = weightAttribute || DEFAULTS.weightAttribute; + + var S = [], + P = {}, + sigma = {}; + + var nodes = graph.nodes(), + edges, + item, + pred, + dist, + cost, + v, + w, + e, + i, + l; + + for (i = 0, l = nodes.length; i < l; i++) { + v = nodes[i]; + P[v] = []; + sigma[v] = 0; + } + + var D = {}; + + sigma[source] = 1; + + var seen = {}; + seen[source] = 0; + + var count = 0; + + var Q = new Heap(BRANDES_DIJKSTRA_HEAP_COMPARATOR); + Q.push([0, count++, source, source]); + + while (Q.size) { + item = Q.pop(); + dist = item[0]; + pred = item[2]; + v = item[3]; + + if (v in D) + continue; + + sigma[v] += sigma[pred]; + S.push(v); + D[v] = dist; + + edges = graph + .undirectedEdges(v) + .concat(graph.outEdges(v)); + + for (i = 0, l = edges.length; i < l; i++) { + e = edges[i]; + w = graph.opposite(v, e); + cost = dist + (graph.getEdgeAttribute(e, weightAttribute) || 1); + + if (!(w in D) && (!(w in seen) || cost < seen[w])) { + seen[w] = cost; + Q.push([cost, count++, v, w]); + sigma[w] = 0; + P[w] = [v]; + } + else if (cost === seen[w]) { + sigma[w] += sigma[v]; + P[w].push(v); + } + } + } + + return [S, P, sigma]; +} + +/** + * Exporting. + */ +module.exports = { + bidirectional: bidirectionalDijkstra, + singleSource: singleSourceDijkstra, + brandes: brandes +}; + + +/***/ }), +/* 237 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseRest = __webpack_require__(119), + eq = __webpack_require__(27), + isIterateeCall = __webpack_require__(122), + keysIn = __webpack_require__(121); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Assigns own and inherited enumerable string keyed properties of source + * objects to the destination object for all destination properties that + * resolve to `undefined`. Source objects are applied from left to right. + * Once a property is set, additional values of the same property are ignored. + * + * **Note:** This method mutates `object`. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category Object + * @param {Object} object The destination object. + * @param {...Object} [sources] The source objects. + * @returns {Object} Returns `object`. + * @see _.defaultsDeep + * @example + * + * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); + * // => { 'a': 1, 'b': 2 } + */ +var defaults = baseRest(function(object, sources) { + object = Object(object); + + var index = -1; + var length = sources.length; + var guard = length > 2 ? sources[2] : undefined; + + if (guard && isIterateeCall(sources[0], sources[1], guard)) { + length = 1; + } + + while (++index < length) { + var source = sources[index]; + var props = keysIn(source); + var propsIndex = -1; + var propsLength = props.length; + + while (++propsIndex < propsLength) { + var key = props[propsIndex]; + var value = object[key]; + + if (value === undefined || + (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { + object[key] = source[key]; + } + } + } + + return object; +}); + +module.exports = defaults; + + +/***/ }), +/* 238 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Graphology Extent + * ================== + * + * Simple function returning the extent of selected attributes of the graph. + */ +var isGraph = __webpack_require__(1); + +/** + * Function returning the extent of the selected node attributes. + * + * @param {Graph} graph - Target graph. + * @param {string|array} attribute - Single or multiple attributes. + * @return {array|object} + */ +function nodeExtent(graph, attribute) { + if (!isGraph(graph)) + throw new Error('graphology-metrics/extent: the given graph is not a valid graphology instance.'); + + var attributes = [].concat(attribute); + + var nodes = graph.nodes(), + node, + data, + value, + key, + a, + i, + l; + + var results = {}; + + for (a = 0; a < attributes.length; a++) { + key = attributes[a]; + + results[key] = [Infinity, -Infinity]; + } + + for (i = 0, l = nodes.length; i < l; i++) { + node = nodes[i]; + data = graph.getNodeAttributes(node); + + for (a = 0; a < attributes.length; a++) { + key = attributes[a]; + value = data[key]; + + if (value < results[key][0]) + results[key][0] = value; + + if (value > results[key][1]) + results[key][1] = value; + } + } + + return typeof attribute === 'string' ? results[attribute] : results; +} + +/** + * Function returning the extent of the selected edge attributes. + * + * @param {Graph} graph - Target graph. + * @param {string|array} attribute - Single or multiple attributes. + * @return {array|object} + */ +function edgeExtent(graph, attribute) { + if (!isGraph(graph)) + throw new Error('graphology-metrics/extent: the given graph is not a valid graphology instance.'); + + var attributes = [].concat(attribute); + + var edges = graph.edges(), + edge, + data, + value, + key, + a, + i, + l; + + var results = {}; + + for (a = 0; a < attributes.length; a++) { + key = attributes[a]; + + results[key] = [Infinity, -Infinity]; + } + + for (i = 0, l = edges.length; i < l; i++) { + edge = edges[i]; + data = graph.getEdgeAttributes(edge); + + for (a = 0; a < attributes.length; a++) { + key = attributes[a]; + value = data[key]; + + if (value < results[key][0]) + results[key][0] = value; + + if (value > results[key][1]) + results[key][1] = value; + } + } + + return typeof attribute === 'string' ? results[attribute] : results; +} + +/** + * Exporting. + */ +var extent = nodeExtent; +extent.nodeExtent = nodeExtent; +extent.edgeExtent = edgeExtent; + +module.exports = extent; + + +/***/ }), +/* 239 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.assign = assign; + +/** + * Sigma.js Utils + * =============== + * + * Various helper functions & classes used throughout the library. + */ + +/** + * Very simple Object.assign-like function. + * + * @param {object} target - First object. + * @param {object} [...objects] - Objects to merge. + * @return {object} + */ +function assign(target) { + target = target || {}; + + for (var _len = arguments.length, objects = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + objects[_key - 1] = arguments[_key]; + } + + for (var i = 0, l = objects.length; i < l; i++) { + if (!objects[i]) continue; + + for (var k in objects[i]) { + target[k] = objects[i][k]; + } + } + + return target; +} + +/***/ }), +/* 240 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createElement = createElement; +exports.getPixelRatio = getPixelRatio; +exports.createNormalizationFunction = createNormalizationFunction; + +function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } + +function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } + +function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + +/** + * Sigma.js Rendering Utils + * =========================== + * + * Helpers used by most renderers. + */ + +/** + * Function used to create DOM elements easily. + * + * @param {string} tag - Tag name of the element to create. + * @param {object} attributes - Attributes map. + * @return {HTMLElement} + */ +function createElement(tag, attributes) { + var element = document.createElement(tag); + if (!attributes) return element; + + for (var k in attributes) { + if (k === 'style') { + for (var s in attributes[k]) { + element.style[s] = attributes[k][s]; + } + } else { + element.setAttribute(k, attributes[k]); + } + } + + return element; +} +/** + * Function returning the browser's pixel ratio. + * + * @return {number} + */ + + +function getPixelRatio() { + var screen = window.screen; + if (typeof screen.deviceXDPI !== 'undefined' && typeof screen.logicalXDPI !== 'undefined' && screen.deviceXDPI > screen.logicalXDPI) return screen.systemXDPI / screen.logicalXDPI;else if (typeof window.devicePixelRatio !== 'undefined') return window.devicePixelRatio; + return 1; +} +/** + * Factory returning a function normalizing the given node's position & size. + * + * @param {object} extent - Extent of the graph. + * @return {function} + */ + + +function createNormalizationFunction(extent) { + var _extent$x = _slicedToArray(extent.x, 2), + minX = _extent$x[0], + maxX = _extent$x[1], + _extent$y = _slicedToArray(extent.y, 2), + minY = _extent$y[0], + maxY = _extent$y[1]; + + var fn; + var ratio = Math.max(maxX - minX, maxY - minY); + if (ratio === 0) ratio = 1; + var dX = (maxX + minX) / 2, + dY = (maxY + minY) / 2; + + fn = function fn(data) { + return { + x: 0.5 + (data.x - dX) / ratio, + y: 0.5 + (data.y - dY) / ratio + }; + }; // TODO: possibility to apply this in batch over array of indices + + + fn.applyTo = function (data) { + data.x = 0.5 + (data.x - dX) / ratio; + data.y = 0.5 + (data.y - dY) / ratio; + }; + + fn.inverse = function (data) { + return { + x: dX + ratio * (data.x - 0.5), + y: dY + ratio * (data.y - 0.5) + }; + }; + + fn.ratio = ratio; + return fn; +} + +/***/ }), +/* 241 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createCompoundProgram = createCompoundProgram; +exports.default = void 0; + +var _utils = __webpack_require__(730); + +function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } + +function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } + +function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } + +function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } + +/** + * Program class. + * + * @constructor + */ +var Program = +/*#__PURE__*/ +function () { + function Program(gl, vertexShaderSource, fragmentShaderSource) { + _classCallCheck(this, Program); + + this.vertexShaderSource = vertexShaderSource; + this.fragmentShaderSource = fragmentShaderSource; + this.load(gl); + } + /** + * Method used to load the program into a webgl context. + * + * @param {WebGLContext} gl - The WebGL context. + * @return {WebGLProgram} + */ + + + _createClass(Program, [{ + key: "load", + value: function load(gl) { + this.vertexShader = (0, _utils.loadVertexShader)(gl, this.vertexShaderSource); + this.fragmentShader = (0, _utils.loadFragmentShader)(gl, this.fragmentShaderSource); + this.program = (0, _utils.loadProgram)(gl, [this.vertexShader, this.fragmentShader]); + return this.program; + } + }]); + + return Program; +}(); +/** + * Helper function combining two or more programs into a single compound one. + * Note that this is more a quick & easy way to combine program than a really + * performant option. More performant programs can be written entirely. + * + * @param {array} programClasses - Program classes to combine. + * @return {function} + */ +// TODO: maybe those should handle their own canvases + + +exports.default = Program; + +function createCompoundProgram(programClasses) { + return ( + /*#__PURE__*/ + function () { + function CompoundProgram(gl) { + _classCallCheck(this, CompoundProgram); + + this.programs = programClasses.map(function (ProgramClass) { + return new ProgramClass(gl); + }); + } + + _createClass(CompoundProgram, [{ + key: "allocate", + value: function allocate(capacity) { + this.programs.forEach(function (program) { + return program.allocate(capacity); + }); + } + }, { + key: "process", + value: function process() { + var args = arguments; + this.programs.forEach(function (program) { + return program.process.apply(program, _toConsumableArray(args)); + }); + } + }, { + key: "computeIndices", + value: function computeIndices() { + this.programs.forEach(function (program) { + if (typeof program.computeIndices === 'function') program.computeIndices(); + }); + } + }, { + key: "bufferData", + value: function bufferData() { + this.programs.forEach(function (program) { + return program.bufferData(); + }); + } + }, { + key: "render", + value: function render() { + var args = arguments; + this.programs.forEach(function (program) { + program.bind(); + program.bufferData(); + program.render.apply(program, _toConsumableArray(args)); + }); + } + }]); + + return CompoundProgram; + }() + ); +} + +/***/ }), +/* 242 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = drawLabel; + +/** + * Sigma.js Canvas Renderer Label Component + * ========================================= + * + * Function used by the canvas renderer to display a single node's label. + */ +function drawLabel(context, data, settings) { + var size = settings.labelSize, + font = settings.labelFont, + weight = settings.labelWeight; + context.fillStyle = '#000'; + context.font = "".concat(weight, " ").concat(size, "px ").concat(font); + context.fillText(data.label, data.x + data.size + 3, data.y + size / 3); +} + +/***/ }), +/* 243 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +window.app = (settings) => { + + window.settings = settings || {} + console.log(settings) + + // Requiring module's CSS + __webpack_require__(244); + + // Requiring angular-related modules that will spit things in the global scope + __webpack_require__(128); + __webpack_require__(129); + __webpack_require__(130); + __webpack_require__(252); + __webpack_require__(254); + + // Making some modules global for the custom scripts to consume + var d3 = __webpack_require__(256); + window.d3 = d3; + var numeric = __webpack_require__(548); + window.numeric = numeric; + + // Requiring some graphology libraries we are going to make global for the user + var graphology = __webpack_require__(549); + + graphology.library = __webpack_require__(556); + window.graphology = graphology; + window.Graph = graphology; + + var randomLayout = graphology.library.layout.random; + + var forceAtlas2Layout = graphology.library.layoutForceAtlas2; + window.layout = { + random: randomLayout, + forceAtlas2: forceAtlas2Layout + }; + + window.ForceAtlas2Layout = graphology.library.FA2Layout; + + window.louvain = graphology.library.communitiesLouvain; + + // Requiring sigma + window.SigmaWebGLRenderer = __webpack_require__(717).default; + + // Requiring own modules + __webpack_require__(741); + __webpack_require__(742); + __webpack_require__(744); + + // Declare app level module which depends on views, and components + angular.module('graphrecipes', [ + 'ngRoute', + 'ngMaterial', + 'graphrecipes.view_upload', + 'graphrecipes.view_board', + 'graphrecipes.recipes_list' + ]). + config(['$routeProvider', function($routeProvider) { + $routeProvider.otherwise({redirectTo: '/upload'}); + }]) + + // Filters + .filter('number', function() { + return function(d) { + return +d + } + }) + .filter('percent', function() { + return function(d) { + return Math.round(+d*100)+'%' + } + }) + + // Service + .factory('cache', function(){ + var ns = {} + ns.recipes = {} + return ns + }) + + + // Directives + .directive('jsEditor', function ($timeout, $interval, $http, cache) { + return { + restrict: 'A', + scope: { + file: '=', + remind: '=' + }, + templateUrl: 'jsEditor.html', + link: function(scope, element, attrs, ctrl) { + if (scope.remind) { + $timeout(function(){ + // INITIALIZATION + if(cache.recipes[scope.file]){ + document.querySelector('#js-editor').textContent = cache.recipes[scope.file] + } + initAceJS() + }) + } else { + $http.get(scope.file).then(function (data) { + $timeout(function(){ + // INITIALIZATION + if(data.data){ + document.querySelector('#js-editor').textContent = data.data + cache.recipes[scope.file] = data.data + } + initAceJS() + }) + }) + } + scope.$on('$destroy', function(){ + if (window.editor) { + window.editor.destroy() + } + }) + scope.codeKeyPress = function(e){ + if((e.which == 13 || e.which == 10) && (e.ctrlKey || e.shiftKey)){ + scope.$parent.executeScript() + } + } + + function initAceJS() { + // Init Ace JS editor panel + // Note: we keep editor in global scope to be able to edit settings from the console + window.editor = ace.edit("js-editor"); + window.editor.setTheme("ace/theme/clouds"); + window.editor.setFontSize(14) + window.editor.getSession().setMode("ace/mode/javascript"); + window.editor.on('change', function(){ + $timeout(function(){ + cache.recipes[scope.file] = window.editor.getValue() + scope.$apply() + }) + }) + } + } + } + }) + + .directive('lcd', function ($timeout, $interval) { + return { + restrict: 'A', + scope: { + animStatus: '=' + }, + templateUrl: 'lcd.html', + link: function(scope, element, attrs, ctrl) { + var obj = element.find('object') + var sprites = [ + "wait", + "smokesmall", + "smokebig", + "splash", + "casserole", + "flyingfoodbit", + "cookoven", + "cooktop1", + "cooktop2", + "cooklegs", + "cookarmknife1", + "cookarmknife2", + "cookarmknife3", + "foodcut", + "foodbits", + "foodstackbottom", + "foodstackmiddle", + "foodstacktop", + "cooksleeping", + "zzz", + "ovenfood", + "closedovendoor", + "openovendoor", + "closeddoor", + "opendoor", + "cookstanding", + "cookarmnote", + "pen3", + "pen2", + "pen1", + "cookserving", + "cookbubble", + "clientbubble", + "menu", + "spoon", + "dish", + "clientarm1", + "clientarm2", + "flyingdishpiece1", + "flyingdishpiece2", + "clienthead1", + "clienthead2", + "clienthead3", + "thinkbubble", + "background" + ] + var animIntervals = [] + + // obj.removeClass("ng-hide"); + + $timeout(function(){ + // sprites.forEach(hideSprite) + scope.$watch('animStatus', applyStatus) + }, 100) + + function hideSprite(s) { + if (obj[0].contentDocument) + obj[0].contentDocument.getElementById(s).style.display = "none" + } + + function showSprite(s) { + if (obj[0].contentDocument) + obj[0].contentDocument.getElementById(s).style.display = "inline" + } + + function applyStatus(e, os, ns) { + if (os != ns) { + animIntervals.forEach(function(promise){ + $interval.cancel(promise) + }) + sprites.forEach(hideSprite) + switch (scope.animStatus) { + case 'off': + // Nothing to do, everything off by default + break; + + case 'error': + sprites + .filter(function(){return Math.random()>0.5}) + .forEach(function(sprite){ + showSprite(sprite) + }) + break; + + case 'waiting': + showSprite('background') + showSprite('closeddoor') + showSprite('openovendoor') + showSprite('cooksleeping') + showSprite('clienthead3') + break; + + case 'choose-recipe': + showSprite('background') + showSprite('foodstacktop') + showSprite('foodstackmiddle') + showSprite('foodstackbottom') + showSprite('closeddoor') + showSprite('closedovendoor') + showSprite('cooksleeping') + addAnimInterval([ + {'zzz': true}, {'zzz': false} + ], 600) + addAnimInterval([ + {'clienthead3': true , 'thinkbubble': true , 'clienthead1': false, 'clientarm1': false, 'menu': false}, + {'clienthead3': false, 'thinkbubble': false, 'clienthead1': true , 'clientarm1': true , 'menu': true} + ], 1500) + break; + + case 'edit-script': + showSprite('background') + showSprite('foodstacktop') + showSprite('foodstackmiddle') + showSprite('foodstackbottom') + showSprite('opendoor') + showSprite('closedovendoor') + showSprite('clientarm1') + showSprite('cookstanding') + showSprite('menu') + addAnimInterval([ + { + 'clienthead1': false, + 'clienthead2': true, + 'clientbubble': true, + 'cookbubble': false + }, + { + 'clienthead1': true, + 'clienthead2': false, + 'clientbubble': false, + 'cookbubble': true + } + ], 9*75) + addAnimInterval([ + {'cookarmnote': true, 'pen1': true}, + {'pen1': false, 'pen2': true}, + {'pen2': false, 'pen3': true}, + {'pen3': false, 'pen2': true}, + {'pen2': false, 'pen1': true}, + {'pen1': false, 'pen2': true}, + {'pen2': false, 'pen3': true}, + {'pen3': false, 'pen2': true}, + {'pen2': false, 'pen1': true}, + {'pen1': false, 'cookarmnote': false}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {} + ], 75) + break; + + case 'cooking': + showSprite('background') + showSprite('closeddoor') + showSprite('closedovendoor') + showSprite('clienthead3') + showSprite('casserole') + addAnimInterval([ + { + 'foodcut': true, + 'cooklegs': true, + 'splash': false, + 'cooktop1': false, + 'cooktop2': true, + 'cookarmknife1': true + }, + {'cookarmknife1': false, 'cookarmknife2': true}, + {'cookarmknife2': false, 'cookarmknife3': true, 'foodbits': true}, + {'cookarmknife3': false, 'cookarmknife2': true}, + {'cookarmknife2': false, 'cookarmknife1': true, 'foodbits': false}, + {'cookarmknife1': false, 'cookarmknife2': true}, + {'cookarmknife2': false, 'cookarmknife3': true, 'foodbits': true}, + {'cookarmknife3': false, 'cookarmknife2': true}, + {'cookarmknife2': false, 'cookarmknife1': true, 'foodbits': false}, + {'cookarmknife1': false, 'cookarmknife2': true}, + {'cookarmknife2': false, 'cookarmknife3': true, 'foodbits': true}, + { + 'cookarmknife3': false, + 'foodbits': false, + 'foodcut': false, + 'cooktop2': false, + 'cooktop1': true, + }, + {'flyingfoodbit': true}, + { + 'flyingfoodbit': false, + 'splash': true + } + ], 50) + + addAnimInterval([ + { + 'foodstackbottom': true, + 'foodstackmiddle': true + }, + {'foodstackmiddle': false}, + {'foodstackbottom': false} + ], 14*50) + + // Phase 2 + $timeout(function(){ + if (scope.animStatus != 'cooking') { return } + animIntervals.forEach(function(promise){ + $interval.cancel(promise) + }) + sprites.forEach(hideSprite) + showSprite('background') + showSprite('clienthead3') + showSprite('closeddoor') + addAnimInterval([ + { + 'cookoven': true, + 'openovendoor': true, + 'casserole': true + }, + {'casserole': false, 'ovenfood': true}, + {'openovendoor': false, 'closedovendoor': true} + ], 150) + + // Phase 3 + $timeout(function(){ + if (scope.animStatus != 'cooking') { return } + animIntervals.forEach(function(promise){ + $interval.cancel(promise) + }) + sprites.forEach(hideSprite) + showSprite('background') + showSprite('clienthead3') + showSprite('closeddoor') + showSprite('closedovendoor') + showSprite('ovenfood') + showSprite('cooksleeping') + showSprite('wait') + addAnimInterval([ + {'zzz': true}, {'zzz': false} + ], 600) + addAnimInterval([ + {'smokebig': true, 'smokesmall': false}, {'smokebig': false, 'smokesmall': true} + ], 800) + + }, 3*150) + + }, 14*50*3) + + break; + + case 'service': + showSprite('background') + showSprite('closeddoor') + showSprite('clienthead3') + addAnimInterval([ + { + 'closedovendoor': true, + 'cookoven': true, + 'ovenfood': true + }, + {'closedovendoor': false, 'openovendoor': true}, + { + 'ovenfood': false, + 'cookoven': false, + 'closeddoor': false, + 'opendoor': true, + 'cookserving': true, + }, + {'clienthead3': false, 'clienthead2': true}, + {'cookserving': false, 'cookstanding': true, 'dish': true}, + { + 'clienthead2': false, + 'clienthead1': true, + 'clientarm1': true, + 'spoon': true, + 'cookstanding': false, + 'opendoor': false, + 'closeddoor': true, + 'cooksleeping': true + } + ], 300) + + // Phase 2 + $timeout(function(){ + if (scope.animStatus != 'service') { return } + animIntervals.forEach(function(promise){ + $interval.cancel(promise) + }) + sprites.forEach(hideSprite) + showSprite('background') + showSprite('closeddoor') + showSprite('openovendoor') + showSprite('cooksleeping') + showSprite('dish') + addAnimInterval([ + {'zzz': true}, {'zzz': false} + ], 600) + addAnimInterval([ + { + 'clienthead1': false, + 'clienthead2': true, + 'clientarm1': true, + 'spoon': true + }, + { + 'clientarm1': false, + 'spoon': false, + 'clientarm2': true + }, + {'flyingdishpiece1': true}, + {'flyingdishpiece1': false, 'flyingdishpiece2': true, 'clientarm2': false, 'clientarm1': true}, + {'clienthead2': false, 'clienthead1': true, 'flyingdishpiece2': false, 'spoon': true} + ], 100) + }, 6*300) + } + } + } + + function addAnimInterval(sequence, delay) { + var sprite + for(sprite in sequence[0]) { + if (sequence[0][sprite]) { + showSprite(sprite) + } else { + hideSprite(sprite) + } + } + + var count = 0 + var interval = $interval(function(){ + count = count + 1 + var moment = sequence[count%sequence.length] + for(sprite in moment) { + if (moment[sprite]) { + showSprite(sprite) + } else { + hideSprite(sprite) + } + } + }, delay || 500) + animIntervals.push(interval) + } + } + } + }) + +} + + +/***/ }), +/* 244 */ +/***/ (function(module, exports, __webpack_require__) { + +// style-loader: Adds some css to the DOM by adding a +

    + userType: + Required!
    + userType = {{userType}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    + + + + it('should initialize to model', function() { + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + + expect(userType.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + var userType = element(by.binding('userType')); + var valid = element(by.binding('myForm.input.$valid')); + var userInput = element(by.model('userType')); + + userInput.clear(); + userInput.sendKeys(''); + + expect(userType.getText()).toEqual('userType ='); + expect(valid.getText()).toContain('false'); + }); + + + * + * @param {string=} name Name of the form. If specified, the form controller will be published into + * related scope, under this name. + */ +var formDirectiveFactory = function(isNgForm) { + return ['$timeout', '$parse', function($timeout, $parse) { + var formDirective = { + name: 'form', + restrict: isNgForm ? 'EAC' : 'E', + require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form + controller: FormController, + compile: function ngFormCompile(formElement, attr) { + // Setup initial state of the control + formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS); + + var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false); + + return { + pre: function ngFormPreLink(scope, formElement, attr, ctrls) { + var controller = ctrls[0]; + + // if `action` attr is not present on the form, prevent the default action (submission) + if (!('action' in attr)) { + // we can't use jq events because if a form is destroyed during submission the default + // action is not prevented. see #1238 + // + // IE 9 is not affected because it doesn't fire a submit event and try to do a full + // page reload if the form was destroyed by submission of the form via a click handler + // on a button in the form. Looks like an IE9 specific bug. + var handleFormSubmission = function(event) { + scope.$apply(function() { + controller.$commitViewValue(); + controller.$setSubmitted(); + }); + + event.preventDefault(); + }; + + formElement[0].addEventListener('submit', handleFormSubmission); + + // unregister the preventDefault listener so that we don't not leak memory but in a + // way that will achieve the prevention of the default action. + formElement.on('$destroy', function() { + $timeout(function() { + formElement[0].removeEventListener('submit', handleFormSubmission); + }, 0, false); + }); + } + + var parentFormCtrl = ctrls[1] || controller.$$parentForm; + parentFormCtrl.$addControl(controller); + + var setter = nameAttr ? getSetter(controller.$name) : noop; + + if (nameAttr) { + setter(scope, controller); + attr.$observe(nameAttr, function(newValue) { + if (controller.$name === newValue) return; + setter(scope, undefined); + controller.$$parentForm.$$renameControl(controller, newValue); + setter = getSetter(controller.$name); + setter(scope, controller); + }); + } + formElement.on('$destroy', function() { + controller.$$parentForm.$removeControl(controller); + setter(scope, undefined); + extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards + }); + } + }; + } + }; + + return formDirective; + + function getSetter(expression) { + if (expression === '') { + //create an assignable expression, so forms with an empty name can be renamed later + return $parse('this[""]').assign; + } + return $parse(expression).assign || noop; + } + }]; +}; + +var formDirective = formDirectiveFactory(); +var ngFormDirective = formDirectiveFactory(true); + + + +// helper methods +function setupValidity(instance) { + instance.$$classCache = {}; + instance.$$classCache[INVALID_CLASS] = !(instance.$$classCache[VALID_CLASS] = instance.$$element.hasClass(VALID_CLASS)); +} +function addSetValidityMethod(context) { + var clazz = context.clazz, + set = context.set, + unset = context.unset; + + clazz.prototype.$setValidity = function(validationErrorKey, state, controller) { + if (isUndefined(state)) { + createAndSet(this, '$pending', validationErrorKey, controller); + } else { + unsetAndCleanup(this, '$pending', validationErrorKey, controller); + } + if (!isBoolean(state)) { + unset(this.$error, validationErrorKey, controller); + unset(this.$$success, validationErrorKey, controller); + } else { + if (state) { + unset(this.$error, validationErrorKey, controller); + set(this.$$success, validationErrorKey, controller); + } else { + set(this.$error, validationErrorKey, controller); + unset(this.$$success, validationErrorKey, controller); + } + } + if (this.$pending) { + cachedToggleClass(this, PENDING_CLASS, true); + this.$valid = this.$invalid = undefined; + toggleValidationCss(this, '', null); + } else { + cachedToggleClass(this, PENDING_CLASS, false); + this.$valid = isObjectEmpty(this.$error); + this.$invalid = !this.$valid; + toggleValidationCss(this, '', this.$valid); + } + + // re-read the state as the set/unset methods could have + // combined state in this.$error[validationError] (used for forms), + // where setting/unsetting only increments/decrements the value, + // and does not replace it. + var combinedState; + if (this.$pending && this.$pending[validationErrorKey]) { + combinedState = undefined; + } else if (this.$error[validationErrorKey]) { + combinedState = false; + } else if (this.$$success[validationErrorKey]) { + combinedState = true; + } else { + combinedState = null; + } + + toggleValidationCss(this, validationErrorKey, combinedState); + this.$$parentForm.$setValidity(validationErrorKey, combinedState, this); + }; + + function createAndSet(ctrl, name, value, controller) { + if (!ctrl[name]) { + ctrl[name] = {}; + } + set(ctrl[name], value, controller); + } + + function unsetAndCleanup(ctrl, name, value, controller) { + if (ctrl[name]) { + unset(ctrl[name], value, controller); + } + if (isObjectEmpty(ctrl[name])) { + ctrl[name] = undefined; + } + } + + function cachedToggleClass(ctrl, className, switchValue) { + if (switchValue && !ctrl.$$classCache[className]) { + ctrl.$$animate.addClass(ctrl.$$element, className); + ctrl.$$classCache[className] = true; + } else if (!switchValue && ctrl.$$classCache[className]) { + ctrl.$$animate.removeClass(ctrl.$$element, className); + ctrl.$$classCache[className] = false; + } + } + + function toggleValidationCss(ctrl, validationErrorKey, isValid) { + validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; + + cachedToggleClass(ctrl, VALID_CLASS + validationErrorKey, isValid === true); + cachedToggleClass(ctrl, INVALID_CLASS + validationErrorKey, isValid === false); + } +} + +function isObjectEmpty(obj) { + if (obj) { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + return false; + } + } + } + return true; +} + +/* global + VALID_CLASS: false, + INVALID_CLASS: false, + PRISTINE_CLASS: false, + DIRTY_CLASS: false, + ngModelMinErr: false +*/ + +// Regex code was initially obtained from SO prior to modification: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231 +var ISO_DATE_REGEXP = /^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/; +// See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987) +// Note: We are being more lenient, because browsers are too. +// 1. Scheme +// 2. Slashes +// 3. Username +// 4. Password +// 5. Hostname +// 6. Port +// 7. Path +// 8. Query +// 9. Fragment +// 1111111111111111 222 333333 44444 55555555555555555555555 666 77777777 8888888 999 +var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; +// eslint-disable-next-line max-len +var EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/; +var NUMBER_REGEXP = /^\s*(-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; +var DATE_REGEXP = /^(\d{4,})-(\d{2})-(\d{2})$/; +var DATETIMELOCAL_REGEXP = /^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; +var WEEK_REGEXP = /^(\d{4,})-W(\d\d)$/; +var MONTH_REGEXP = /^(\d{4,})-(\d\d)$/; +var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; + +var PARTIAL_VALIDATION_EVENTS = 'keydown wheel mousedown'; +var PARTIAL_VALIDATION_TYPES = createMap(); +forEach('date,datetime-local,month,time,week'.split(','), function(type) { + PARTIAL_VALIDATION_TYPES[type] = true; +}); + +var inputType = { + + /** + * @ngdoc input + * @name input[text] + * + * @description + * Standard HTML text input with AngularJS data binding, inherited by most of the `input` elements. + * + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Adds `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} + * does not match a RegExp found by evaluating the AngularJS expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false AngularJS will not automatically trim the input. + * This parameter is ignored for input[type=password] controls, which will never trim the + * input. + * + * @example + + + +
    + +
    + + Required! + + Single word only! +
    + text = {{example.text}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var text = element(by.binding('example.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('guest'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if multi word', function() { + input.clear(); + input.sendKeys('hello world'); + + expect(valid.getText()).toContain('false'); + }); + +
    + */ + 'text': textInputType, + + /** + * @ngdoc input + * @name input[date] + * + * @description + * Input with date validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601 + * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many + * modern browsers do not yet support this input type, it is important to provide cues to users on the + * expected input format via a placeholder or label. + * + * The model must always be a Date object, otherwise AngularJS will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a + * valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute + * (e.g. `min="{{minDate | date:'yyyy-MM-dd'}}"`). Note that `min` will also add native HTML5 + * constraint validation. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be + * a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute + * (e.g. `max="{{maxDate | date:'yyyy-MM-dd'}}"`). Note that `max` will also add native HTML5 + * constraint validation. + * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string + * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. + * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string + * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + + +
    + + Required! + + Not a valid date! +
    + value = {{example.value | date: "yyyy-MM-dd"}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value | date: "yyyy-MM-dd"')); + var valid = element(by.binding('myForm.input.$valid')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (see https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-10-22'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01-01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
    + */ + 'date': createDateInputType('date', DATE_REGEXP, + createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']), + 'yyyy-MM-dd'), + + /** + * @ngdoc input + * @name input[datetime-local] + * + * @description + * Input with datetime validation and transformation. In browsers that do not yet support + * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`. + * + * The model must always be a Date object, otherwise AngularJS will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * The format of the displayed time can be adjusted with the + * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat` + * and `timeStripZeroSeconds`. + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation + * inside this attribute (e.g. `min="{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`). + * Note that `min` will also add native HTML5 constraint validation. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation + * inside this attribute (e.g. `max="{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`). + * Note that `max` will also add native HTML5 constraint validation. + * @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string + * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. + * @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string + * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + + +
    + + Required! + + Not a valid date! +
    + value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"')); + var valid = element(by.binding('myForm.input.$valid')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2010-12-28T14:57:00'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01-01T23:59:00'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
    + */ + 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP, + createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']), + 'yyyy-MM-ddTHH:mm:ss.sss'), + + /** + * @ngdoc input + * @name input[time] + * + * @description + * Input with time validation and transformation. In browsers that do not yet support + * the HTML5 time input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a + * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`. + * + * The model must always be a Date object, otherwise AngularJS will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions}. By default, + * this is the timezone of the browser. + * + * The format of the displayed time can be adjusted with the + * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat` + * and `timeStripZeroSeconds`. + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this + * attribute (e.g. `min="{{minTime | date:'HH:mm:ss'}}"`). Note that `min` will also add + * native HTML5 constraint validation. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this + * attribute (e.g. `max="{{maxTime | date:'HH:mm:ss'}}"`). Note that `max` will also add + * native HTML5 constraint validation. + * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the + * `ngMin` expression evaluates to. Note that it does not set the `min` attribute. + * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the + * `ngMax` expression evaluates to. Note that it does not set the `max` attribute. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + + +
    + + Required! + + Not a valid date! +
    + value = {{example.value | date: "HH:mm:ss"}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value | date: "HH:mm:ss"')); + var valid = element(by.binding('myForm.input.$valid')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('14:57:00'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('23:59:00'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
    + */ + 'time': createDateInputType('time', TIME_REGEXP, + createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']), + 'HH:mm:ss.sss'), + + /** + * @ngdoc input + * @name input[week] + * + * @description + * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support + * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * week format (yyyy-W##), for example: `2013-W02`. + * + * The model must always be a Date object, otherwise AngularJS will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * + * The value of the resulting Date object will be set to Thursday at 00:00:00 of the requested week, + * due to ISO-8601 week numbering standards. Information on ISO's system for numbering the weeks of the + * year can be found at: https://en.wikipedia.org/wiki/ISO_8601#Week_dates + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this + * attribute (e.g. `min="{{minWeek | date:'yyyy-Www'}}"`). Note that `min` will also add + * native HTML5 constraint validation. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this + * attribute (e.g. `max="{{maxWeek | date:'yyyy-Www'}}"`). Note that `max` will also add + * native HTML5 constraint validation. + * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string + * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. + * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string + * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + +
    + + Required! + + Not a valid date! +
    + value = {{example.value | date: "yyyy-Www"}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value | date: "yyyy-Www"')); + var valid = element(by.binding('myForm.input.$valid')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-W01'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-W01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
    + */ + 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'), + + /** + * @ngdoc input + * @name input[month] + * + * @description + * Input with month validation and transformation. In browsers that do not yet support + * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 + * month format (yyyy-MM), for example: `2009-01`. + * + * The model must always be a Date object, otherwise AngularJS will throw an error. + * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. + * If the model is not set to the first of the month, the next view to model update will set it + * to the first of the month. + * + * The timezone to be used to read/write the `Date` instance in the model can be defined using + * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this + * attribute (e.g. `min="{{minMonth | date:'yyyy-MM'}}"`). Note that `min` will also add + * native HTML5 constraint validation. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this + * attribute (e.g. `max="{{maxMonth | date:'yyyy-MM'}}"`). Note that `max` will also add + * native HTML5 constraint validation. + * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string + * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. + * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string + * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. + + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + + +
    + + Required! + + Not a valid month! +
    + value = {{example.value | date: "yyyy-MM"}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value | date: "yyyy-MM"')); + var valid = element(by.binding('myForm.input.$valid')); + + // currently protractor/webdriver does not support + // sending keys to all known HTML5 input controls + // for various browsers (https://github.com/angular/protractor/issues/562). + function setInput(val) { + // set the value of the element and force validation. + var scr = "var ipt = document.getElementById('exampleInput'); " + + "ipt.value = '" + val + "';" + + "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; + browser.executeScript(scr); + } + + it('should initialize to model', function() { + expect(value.getText()).toContain('2013-10'); + expect(valid.getText()).toContain('myForm.input.$valid = true'); + }); + + it('should be invalid if empty', function() { + setInput(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + + it('should be invalid if over max', function() { + setInput('2015-01'); + expect(value.getText()).toContain(''); + expect(valid.getText()).toContain('myForm.input.$valid = false'); + }); + +
    + */ + 'month': createDateInputType('month', MONTH_REGEXP, + createDateParser(MONTH_REGEXP, ['yyyy', 'MM']), + 'yyyy-MM'), + + /** + * @ngdoc input + * @name input[number] + * + * @description + * Text input with number validation and transformation. Sets the `number` validation + * error if not a valid number. + * + *
    + * The model must always be of type `number` otherwise AngularJS will throw an error. + * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt} + * error docs for more information and an example of how to convert your model if necessary. + *
    + * + * + * + * @knownIssue + * + * ### HTML5 constraint validation and `allowInvalid` + * + * In browsers that follow the + * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29), + * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}. + * If a non-number is entered in the input, the browser will report the value as an empty string, + * which means the view / model values in `ngModel` and subsequently the scope value + * will also be an empty string. + * + * @knownIssue + * + * ### Large numbers and `step` validation + * + * The `step` validation will not work correctly for very large numbers (e.g. 9999999999) due to + * Javascript's arithmetic limitations. If you need to handle large numbers, purpose-built + * libraries (e.g. https://github.com/MikeMcl/big.js/), can be included into AngularJS by + * {@link guide/forms#modifying-built-in-validators overwriting the validators} + * for `number` and / or `step`, or by {@link guide/forms#custom-validation applying custom validators} + * to an `input[text]` element. The source for `input[number]` type can be used as a starting + * point for both implementations. + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. + * Can be interpolated. + * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. + * Can be interpolated. + * @param {string=} ngMin Like `min`, sets the `min` validation error key if the value entered is less than `ngMin`, + * but does not trigger HTML5 native validation. Takes an expression. + * @param {string=} ngMax Like `max`, sets the `max` validation error key if the value entered is greater than `ngMax`, + * but does not trigger HTML5 native validation. Takes an expression. + * @param {string=} step Sets the `step` validation error key if the value entered does not fit the `step` constraint. + * Can be interpolated. + * @param {string=} ngStep Like `step`, sets the `step` validation error key if the value entered does not fit the `ngStep` constraint, + * but does not trigger HTML5 native validation. Takes an expression. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} + * does not match a RegExp found by evaluating the AngularJS expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + +
    + + Required! + + Not valid number! +
    + value = {{example.value}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    +
    +
    + + var value = element(by.binding('example.value')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('example.value')); + + it('should initialize to model', function() { + expect(value.getText()).toContain('12'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if over max', function() { + input.clear(); + input.sendKeys('123'); + expect(value.getText()).toEqual('value ='); + expect(valid.getText()).toContain('false'); + }); + +
    + */ + 'number': numberInputType, + + + /** + * @ngdoc input + * @name input[url] + * + * @description + * Text input with URL validation. Sets the `url` validation error key if the content is not a + * valid URL. + * + *
    + * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex + * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify + * the built-in validators (see the {@link guide/forms Forms guide}) + *
    + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} + * does not match a RegExp found by evaluating the AngularJS expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    +
    + + var text = element(by.binding('url.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('url.text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('http://google.com'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if not url', function() { + input.clear(); + input.sendKeys('box'); + + expect(valid.getText()).toContain('false'); + }); + +
    + */ + 'url': urlInputType, + + + /** + * @ngdoc input + * @name input[email] + * + * @description + * Text input with email validation. Sets the `email` validation error key if not a valid email + * address. + * + *
    + * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex + * used in Chromium, which may not fulfill your app's requirements. + * If you need stricter (e.g. requiring a top-level domain), or more relaxed validation + * (e.g. allowing IPv6 address literals) you can use `ng-pattern` or + * modify the built-in validators (see the {@link guide/forms Forms guide}). + *
    + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of + * any length. + * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string + * that contains the regular expression body that will be converted to a regular expression + * as in the ngPattern directive. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} + * does not match a RegExp found by evaluating the AngularJS expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    + +
    + + Required! + + Not valid email! +
    + text = {{email.text}}
    + myForm.input.$valid = {{myForm.input.$valid}}
    + myForm.input.$error = {{myForm.input.$error}}
    + myForm.$valid = {{myForm.$valid}}
    + myForm.$error.required = {{!!myForm.$error.required}}
    + myForm.$error.email = {{!!myForm.$error.email}}
    +
    +
    + + var text = element(by.binding('email.text')); + var valid = element(by.binding('myForm.input.$valid')); + var input = element(by.model('email.text')); + + it('should initialize to model', function() { + expect(text.getText()).toContain('me@example.com'); + expect(valid.getText()).toContain('true'); + }); + + it('should be invalid if empty', function() { + input.clear(); + input.sendKeys(''); + expect(text.getText()).toEqual('text ='); + expect(valid.getText()).toContain('false'); + }); + + it('should be invalid if not email', function() { + input.clear(); + input.sendKeys('xxx'); + + expect(valid.getText()).toContain('false'); + }); + +
    + */ + 'email': emailInputType, + + + /** + * @ngdoc input + * @name input[radio] + * + * @description + * HTML radio button. + * + * **Note:**
    + * All inputs controlled by {@link ngModel ngModel} (including those of type `radio`) will use the + * value of their `name` attribute to determine the property under which their + * {@link ngModel.NgModelController NgModelController} will be published on the parent + * {@link form.FormController FormController}. Thus, if you use the same `name` for multiple + * inputs of a form (e.g. a group of radio inputs), only _one_ `NgModelController` will be + * published on the parent `FormController` under that name. The rest of the controllers will + * continue to work as expected, but you won't be able to access them as properties on the parent + * `FormController`. + * + *
    + *

    + * In plain HTML forms, the `name` attribute is used to identify groups of radio inputs, so + * that the browser can manage their state (checked/unchecked) based on the state of other + * inputs in the same group. + *

    + *

    + * In AngularJS forms, this is not necessary. The input's state will be updated based on the + * value of the underlying model data. + *

    + *
    + * + *
    + * If you omit the `name` attribute on a radio input, `ngModel` will automatically assign it a + * unique name. + *
    + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string} value The value to which the `ngModel` expression should be set when selected. + * Note that `value` only supports `string` values, i.e. the scope model needs to be a string, + * too. Use `ngValue` if you need complex models (`number`, `object`, ...). + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * @param {string} ngValue AngularJS expression to which `ngModel` will be be set when the radio + * is selected. Should be used instead of the `value` attribute if you need + * a non-string `ngModel` (`boolean`, `array`, ...). + * + * @example + + + +
    +
    +
    +
    + color = {{color.name | json}}
    +
    + Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`. +
    + + it('should change state', function() { + var inputs = element.all(by.model('color.name')); + var color = element(by.binding('color.name')); + + expect(color.getText()).toContain('blue'); + + inputs.get(0).click(); + expect(color.getText()).toContain('red'); + + inputs.get(1).click(); + expect(color.getText()).toContain('green'); + }); + +
    + */ + 'radio': radioInputType, + + /** + * @ngdoc input + * @name input[range] + * + * @description + * Native range input with validation and transformation. + * + * The model for the range input must always be a `Number`. + * + * IE9 and other browsers that do not support the `range` type fall back + * to a text input without any default values for `min`, `max` and `step`. Model binding, + * validation and number parsing are nevertheless supported. + * + * Browsers that support range (latest Chrome, Safari, Firefox, Edge) treat `input[range]` + * in a way that never allows the input to hold an invalid value. That means: + * - any non-numerical value is set to `(max + min) / 2`. + * - any numerical value that is less than the current min val, or greater than the current max val + * is set to the min / max val respectively. + * - additionally, the current `step` is respected, so the nearest value that satisfies a step + * is used. + * + * See the [HTML Spec on input[type=range]](https://www.w3.org/TR/html5/forms.html#range-state-(type=range)) + * for more info. + * + * This has the following consequences for AngularJS: + * + * Since the element value should always reflect the current model value, a range input + * will set the bound ngModel expression to the value that the browser has set for the + * input element. For example, in the following input ``, + * if the application sets `model.value = null`, the browser will set the input to `'50'`. + * AngularJS will then set the model to `50`, to prevent input and model value being out of sync. + * + * That means the model for range will immediately be set to `50` after `ngModel` has been + * initialized. It also means a range input can never have the required error. + * + * This does not only affect changes to the model value, but also to the values of the `min`, + * `max`, and `step` attributes. When these change in a way that will cause the browser to modify + * the input value, AngularJS will also update the model value. + * + * Automatic value adjustment also means that a range input element can never have the `required`, + * `min`, or `max` errors. + * + * However, `step` is currently only fully implemented by Firefox. Other browsers have problems + * when the step value changes dynamically - they do not adjust the element value correctly, but + * instead may set the `stepMismatch` error. If that's the case, the AngularJS will set the `step` + * error on the input, and set the model to `undefined`. + * + * Note that `input[range]` is not compatible with`ngMax`, `ngMin`, and `ngStep`, because they do + * not set the `min` and `max` attributes, which means that the browser won't automatically adjust + * the input value based on their values, and will always assume min = 0, max = 100, and step = 1. + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} min Sets the `min` validation to ensure that the value entered is greater + * than `min`. Can be interpolated. + * @param {string=} max Sets the `max` validation to ensure that the value entered is less than `max`. + * Can be interpolated. + * @param {string=} step Sets the `step` validation to ensure that the value entered matches the `step` + * Can be interpolated. + * @param {expression=} ngChange AngularJS expression to be executed when the ngModel value changes due + * to user interaction with the input element. + * @param {expression=} ngChecked If the expression is truthy, then the `checked` attribute will be set on the + * element. **Note** : `ngChecked` should not be used alongside `ngModel`. + * Checkout {@link ng.directive:ngChecked ngChecked} for usage. + * + * @example + + + +
    + + Model as range: +
    + Model as number:
    + Min:
    + Max:
    + value = {{value}}
    + myForm.range.$valid = {{myForm.range.$valid}}
    + myForm.range.$error = {{myForm.range.$error}} +
    +
    +
    + + * ## Range Input with ngMin & ngMax attributes + + * @example + + + +
    + Model as range: +
    + Model as number:
    + Min:
    + Max:
    + value = {{value}}
    + myForm.range.$valid = {{myForm.range.$valid}}
    + myForm.range.$error = {{myForm.range.$error}} +
    +
    +
    + + */ + 'range': rangeInputType, + + /** + * @ngdoc input + * @name input[checkbox] + * + * @description + * HTML checkbox. + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {expression=} ngTrueValue The value to which the expression should be set when selected. + * @param {expression=} ngFalseValue The value to which the expression should be set when not selected. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * + * @example + + + +
    +
    +
    + value1 = {{checkboxModel.value1}}
    + value2 = {{checkboxModel.value2}}
    +
    +
    + + it('should change state', function() { + var value1 = element(by.binding('checkboxModel.value1')); + var value2 = element(by.binding('checkboxModel.value2')); + + expect(value1.getText()).toContain('true'); + expect(value2.getText()).toContain('YES'); + + element(by.model('checkboxModel.value1')).click(); + element(by.model('checkboxModel.value2')).click(); + + expect(value1.getText()).toContain('false'); + expect(value2.getText()).toContain('NO'); + }); + +
    + */ + 'checkbox': checkboxInputType, + + 'hidden': noop, + 'button': noop, + 'submit': noop, + 'reset': noop, + 'file': noop +}; + +function stringBasedInputType(ctrl) { + ctrl.$formatters.push(function(value) { + return ctrl.$isEmpty(value) ? value : value.toString(); + }); +} + +function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); +} + +function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { + var type = lowercase(element[0].type); + + // In composition mode, users are still inputting intermediate text buffer, + // hold the listener until composition is done. + // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent + if (!$sniffer.android) { + var composing = false; + + element.on('compositionstart', function() { + composing = true; + }); + + // Support: IE9+ + element.on('compositionupdate', function(ev) { + // End composition when ev.data is empty string on 'compositionupdate' event. + // When the input de-focusses (e.g. by clicking away), IE triggers 'compositionupdate' + // instead of 'compositionend'. + if (isUndefined(ev.data) || ev.data === '') { + composing = false; + } + }); + + element.on('compositionend', function() { + composing = false; + listener(); + }); + } + + var timeout; + + var listener = function(ev) { + if (timeout) { + $browser.defer.cancel(timeout); + timeout = null; + } + if (composing) return; + var value = element.val(), + event = ev && ev.type; + + // By default we will trim the value + // If the attribute ng-trim exists we will avoid trimming + // If input type is 'password', the value is never trimmed + if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) { + value = trim(value); + } + + // If a control is suffering from bad input (due to native validators), browsers discard its + // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the + // control's value is the same empty value twice in a row. + if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) { + ctrl.$setViewValue(value, event); + } + }; + + // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the + // input event on backspace, delete or cut + if ($sniffer.hasEvent('input')) { + element.on('input', listener); + } else { + var deferListener = function(ev, input, origValue) { + if (!timeout) { + timeout = $browser.defer(function() { + timeout = null; + if (!input || input.value !== origValue) { + listener(ev); + } + }); + } + }; + + element.on('keydown', /** @this */ function(event) { + var key = event.keyCode; + + // ignore + // command modifiers arrows + if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; + + deferListener(event, this, this.value); + }); + + // if user modifies input value using context menu in IE, we need "paste", "cut" and "drop" events to catch it + if ($sniffer.hasEvent('paste')) { + element.on('paste cut drop', deferListener); + } + } + + // if user paste into input using mouse on older browser + // or form autocomplete on newer browser, we need "change" event to catch it + element.on('change', listener); + + // Some native input types (date-family) have the ability to change validity without + // firing any input/change events. + // For these event types, when native validators are present and the browser supports the type, + // check for validity changes on various DOM events. + if (PARTIAL_VALIDATION_TYPES[type] && ctrl.$$hasNativeValidators && type === attr.type) { + element.on(PARTIAL_VALIDATION_EVENTS, /** @this */ function(ev) { + if (!timeout) { + var validity = this[VALIDITY_STATE_PROPERTY]; + var origBadInput = validity.badInput; + var origTypeMismatch = validity.typeMismatch; + timeout = $browser.defer(function() { + timeout = null; + if (validity.badInput !== origBadInput || validity.typeMismatch !== origTypeMismatch) { + listener(ev); + } + }); + } + }); + } + + ctrl.$render = function() { + // Workaround for Firefox validation #12102. + var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue; + if (element.val() !== value) { + element.val(value); + } + }; +} + +function weekParser(isoWeek, existingDate) { + if (isDate(isoWeek)) { + return isoWeek; + } + + if (isString(isoWeek)) { + WEEK_REGEXP.lastIndex = 0; + var parts = WEEK_REGEXP.exec(isoWeek); + if (parts) { + var year = +parts[1], + week = +parts[2], + hours = 0, + minutes = 0, + seconds = 0, + milliseconds = 0, + firstThurs = getFirstThursdayOfYear(year), + addDays = (week - 1) * 7; + + if (existingDate) { + hours = existingDate.getHours(); + minutes = existingDate.getMinutes(); + seconds = existingDate.getSeconds(); + milliseconds = existingDate.getMilliseconds(); + } + + return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds); + } + } + + return NaN; +} + +function createDateParser(regexp, mapping) { + return function(iso, previousDate) { + var parts, map; + + if (isDate(iso)) { + return iso; + } + + if (isString(iso)) { + // When a date is JSON'ified to wraps itself inside of an extra + // set of double quotes. This makes the date parsing code unable + // to match the date string and parse it as a date. + if (iso.charAt(0) === '"' && iso.charAt(iso.length - 1) === '"') { + iso = iso.substring(1, iso.length - 1); + } + if (ISO_DATE_REGEXP.test(iso)) { + return new Date(iso); + } + regexp.lastIndex = 0; + parts = regexp.exec(iso); + + if (parts) { + parts.shift(); + if (previousDate) { + map = { + yyyy: previousDate.getFullYear(), + MM: previousDate.getMonth() + 1, + dd: previousDate.getDate(), + HH: previousDate.getHours(), + mm: previousDate.getMinutes(), + ss: previousDate.getSeconds(), + sss: previousDate.getMilliseconds() / 1000 + }; + } else { + map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 }; + } + + forEach(parts, function(part, index) { + if (index < mapping.length) { + map[mapping[index]] = +part; + } + }); + + var date = new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0); + if (map.yyyy < 100) { + // In the constructor, 2-digit years map to 1900-1999. + // Use `setFullYear()` to set the correct year. + date.setFullYear(map.yyyy); + } + + return date; + } + } + + return NaN; + }; +} + +function createDateInputType(type, regexp, parseDate, format) { + return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { + badInputChecker(scope, element, attr, ctrl, type); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + + var isTimeType = type === 'time' || type === 'datetimelocal'; + var previousDate; + var previousTimezone; + + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + + if (regexp.test(value)) { + // Note: We cannot read ctrl.$modelValue, as there might be a different + // parser/formatter in the processing chain so that the model + // contains some different data format! + return parseDateAndConvertTimeZoneToLocal(value, previousDate); + } + ctrl.$$parserName = type; + return undefined; + }); + + ctrl.$formatters.push(function(value) { + if (value && !isDate(value)) { + throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value); + } + if (isValidDate(value)) { + previousDate = value; + var timezone = ctrl.$options.getOption('timezone'); + + if (timezone) { + previousTimezone = timezone; + previousDate = convertTimezoneToLocal(previousDate, timezone, true); + } + + return formatter(value, timezone); + } else { + previousDate = null; + previousTimezone = null; + return ''; + } + }); + + if (isDefined(attr.min) || attr.ngMin) { + var minVal = attr.min || $parse(attr.ngMin)(scope); + var parsedMinVal = parseObservedDateValue(minVal); + + ctrl.$validators.min = function(value) { + return !isValidDate(value) || isUndefined(parsedMinVal) || parseDate(value) >= parsedMinVal; + }; + attr.$observe('min', function(val) { + if (val !== minVal) { + parsedMinVal = parseObservedDateValue(val); + minVal = val; + ctrl.$validate(); + } + }); + } + + if (isDefined(attr.max) || attr.ngMax) { + var maxVal = attr.max || $parse(attr.ngMax)(scope); + var parsedMaxVal = parseObservedDateValue(maxVal); + + ctrl.$validators.max = function(value) { + return !isValidDate(value) || isUndefined(parsedMaxVal) || parseDate(value) <= parsedMaxVal; + }; + attr.$observe('max', function(val) { + if (val !== maxVal) { + parsedMaxVal = parseObservedDateValue(val); + maxVal = val; + ctrl.$validate(); + } + }); + } + + function isValidDate(value) { + // Invalid Date: getTime() returns NaN + return value && !(value.getTime && value.getTime() !== value.getTime()); + } + + function parseObservedDateValue(val) { + return isDefined(val) && !isDate(val) ? parseDateAndConvertTimeZoneToLocal(val) || undefined : val; + } + + function parseDateAndConvertTimeZoneToLocal(value, previousDate) { + var timezone = ctrl.$options.getOption('timezone'); + + if (previousTimezone && previousTimezone !== timezone) { + // If the timezone has changed, adjust the previousDate to the default timezone + // so that the new date is converted with the correct timezone offset + previousDate = addDateMinutes(previousDate, timezoneToOffset(previousTimezone)); + } + + var parsedDate = parseDate(value, previousDate); + + if (!isNaN(parsedDate) && timezone) { + parsedDate = convertTimezoneToLocal(parsedDate, timezone); + } + return parsedDate; + } + + function formatter(value, timezone) { + var targetFormat = format; + + if (isTimeType && isString(ctrl.$options.getOption('timeSecondsFormat'))) { + targetFormat = format + .replace('ss.sss', ctrl.$options.getOption('timeSecondsFormat')) + .replace(/:$/, ''); + } + + var formatted = $filter('date')(value, targetFormat, timezone); + + if (isTimeType && ctrl.$options.getOption('timeStripZeroSeconds')) { + formatted = formatted.replace(/(?::00)?(?:\.000)?$/, ''); + } + + return formatted; + } + }; +} + +function badInputChecker(scope, element, attr, ctrl, parserName) { + var node = element[0]; + var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity); + if (nativeValidation) { + ctrl.$parsers.push(function(value) { + var validity = element.prop(VALIDITY_STATE_PROPERTY) || {}; + if (validity.badInput || validity.typeMismatch) { + ctrl.$$parserName = parserName; + return undefined; + } + + return value; + }); + } +} + +function numberFormatterParser(ctrl) { + ctrl.$parsers.push(function(value) { + if (ctrl.$isEmpty(value)) return null; + if (NUMBER_REGEXP.test(value)) return parseFloat(value); + + ctrl.$$parserName = 'number'; + return undefined; + }); + + ctrl.$formatters.push(function(value) { + if (!ctrl.$isEmpty(value)) { + if (!isNumber(value)) { + throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value); + } + value = value.toString(); + } + return value; + }); +} + +function parseNumberAttrVal(val) { + if (isDefined(val) && !isNumber(val)) { + val = parseFloat(val); + } + return !isNumberNaN(val) ? val : undefined; +} + +function isNumberInteger(num) { + // See http://stackoverflow.com/questions/14636536/how-to-check-if-a-variable-is-an-integer-in-javascript#14794066 + // (minus the assumption that `num` is a number) + + // eslint-disable-next-line no-bitwise + return (num | 0) === num; +} + +function countDecimals(num) { + var numString = num.toString(); + var decimalSymbolIndex = numString.indexOf('.'); + + if (decimalSymbolIndex === -1) { + if (-1 < num && num < 1) { + // It may be in the exponential notation format (`1e-X`) + var match = /e-(\d+)$/.exec(numString); + + if (match) { + return Number(match[1]); + } + } + + return 0; + } + + return numString.length - decimalSymbolIndex - 1; +} + +function isValidForStep(viewValue, stepBase, step) { + // At this point `stepBase` and `step` are expected to be non-NaN values + // and `viewValue` is expected to be a valid stringified number. + var value = Number(viewValue); + + var isNonIntegerValue = !isNumberInteger(value); + var isNonIntegerStepBase = !isNumberInteger(stepBase); + var isNonIntegerStep = !isNumberInteger(step); + + // Due to limitations in Floating Point Arithmetic (e.g. `0.3 - 0.2 !== 0.1` or + // `0.5 % 0.1 !== 0`), we need to convert all numbers to integers. + if (isNonIntegerValue || isNonIntegerStepBase || isNonIntegerStep) { + var valueDecimals = isNonIntegerValue ? countDecimals(value) : 0; + var stepBaseDecimals = isNonIntegerStepBase ? countDecimals(stepBase) : 0; + var stepDecimals = isNonIntegerStep ? countDecimals(step) : 0; + + var decimalCount = Math.max(valueDecimals, stepBaseDecimals, stepDecimals); + var multiplier = Math.pow(10, decimalCount); + + value = value * multiplier; + stepBase = stepBase * multiplier; + step = step * multiplier; + + if (isNonIntegerValue) value = Math.round(value); + if (isNonIntegerStepBase) stepBase = Math.round(stepBase); + if (isNonIntegerStep) step = Math.round(step); + } + + return (value - stepBase) % step === 0; +} + +function numberInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { + badInputChecker(scope, element, attr, ctrl, 'number'); + numberFormatterParser(ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + + var parsedMinVal; + + if (isDefined(attr.min) || attr.ngMin) { + var minVal = attr.min || $parse(attr.ngMin)(scope); + parsedMinVal = parseNumberAttrVal(minVal); + + ctrl.$validators.min = function(modelValue, viewValue) { + return ctrl.$isEmpty(viewValue) || isUndefined(parsedMinVal) || viewValue >= parsedMinVal; + }; + + attr.$observe('min', function(val) { + if (val !== minVal) { + parsedMinVal = parseNumberAttrVal(val); + minVal = val; + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); + } + }); + } + + if (isDefined(attr.max) || attr.ngMax) { + var maxVal = attr.max || $parse(attr.ngMax)(scope); + var parsedMaxVal = parseNumberAttrVal(maxVal); + + ctrl.$validators.max = function(modelValue, viewValue) { + return ctrl.$isEmpty(viewValue) || isUndefined(parsedMaxVal) || viewValue <= parsedMaxVal; + }; + + attr.$observe('max', function(val) { + if (val !== maxVal) { + parsedMaxVal = parseNumberAttrVal(val); + maxVal = val; + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); + } + }); + } + + if (isDefined(attr.step) || attr.ngStep) { + var stepVal = attr.step || $parse(attr.ngStep)(scope); + var parsedStepVal = parseNumberAttrVal(stepVal); + + ctrl.$validators.step = function(modelValue, viewValue) { + return ctrl.$isEmpty(viewValue) || isUndefined(parsedStepVal) || + isValidForStep(viewValue, parsedMinVal || 0, parsedStepVal); + }; + + attr.$observe('step', function(val) { + // TODO(matsko): implement validateLater to reduce number of validations + if (val !== stepVal) { + parsedStepVal = parseNumberAttrVal(val); + stepVal = val; + ctrl.$validate(); + } + + }); + + } +} + +function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) { + badInputChecker(scope, element, attr, ctrl, 'range'); + numberFormatterParser(ctrl); + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + + var supportsRange = ctrl.$$hasNativeValidators && element[0].type === 'range', + minVal = supportsRange ? 0 : undefined, + maxVal = supportsRange ? 100 : undefined, + stepVal = supportsRange ? 1 : undefined, + validity = element[0].validity, + hasMinAttr = isDefined(attr.min), + hasMaxAttr = isDefined(attr.max), + hasStepAttr = isDefined(attr.step); + + var originalRender = ctrl.$render; + + ctrl.$render = supportsRange && isDefined(validity.rangeUnderflow) && isDefined(validity.rangeOverflow) ? + //Browsers that implement range will set these values automatically, but reading the adjusted values after + //$render would cause the min / max validators to be applied with the wrong value + function rangeRender() { + originalRender(); + ctrl.$setViewValue(element.val()); + } : + originalRender; + + if (hasMinAttr) { + minVal = parseNumberAttrVal(attr.min); + + ctrl.$validators.min = supportsRange ? + // Since all browsers set the input to a valid value, we don't need to check validity + function noopMinValidator() { return true; } : + // non-support browsers validate the min val + function minValidator(modelValue, viewValue) { + return ctrl.$isEmpty(viewValue) || isUndefined(minVal) || viewValue >= minVal; + }; + + setInitialValueAndObserver('min', minChange); + } + + if (hasMaxAttr) { + maxVal = parseNumberAttrVal(attr.max); + + ctrl.$validators.max = supportsRange ? + // Since all browsers set the input to a valid value, we don't need to check validity + function noopMaxValidator() { return true; } : + // non-support browsers validate the max val + function maxValidator(modelValue, viewValue) { + return ctrl.$isEmpty(viewValue) || isUndefined(maxVal) || viewValue <= maxVal; + }; + + setInitialValueAndObserver('max', maxChange); + } + + if (hasStepAttr) { + stepVal = parseNumberAttrVal(attr.step); + + ctrl.$validators.step = supportsRange ? + function nativeStepValidator() { + // Currently, only FF implements the spec on step change correctly (i.e. adjusting the + // input element value to a valid value). It's possible that other browsers set the stepMismatch + // validity error instead, so we can at least report an error in that case. + return !validity.stepMismatch; + } : + // ngStep doesn't set the setp attr, so the browser doesn't adjust the input value as setting step would + function stepValidator(modelValue, viewValue) { + return ctrl.$isEmpty(viewValue) || isUndefined(stepVal) || + isValidForStep(viewValue, minVal || 0, stepVal); + }; + + setInitialValueAndObserver('step', stepChange); + } + + function setInitialValueAndObserver(htmlAttrName, changeFn) { + // interpolated attributes set the attribute value only after a digest, but we need the + // attribute value when the input is first rendered, so that the browser can adjust the + // input value based on the min/max value + element.attr(htmlAttrName, attr[htmlAttrName]); + var oldVal = attr[htmlAttrName]; + attr.$observe(htmlAttrName, function wrappedObserver(val) { + if (val !== oldVal) { + oldVal = val; + changeFn(val); + } + }); + } + + function minChange(val) { + minVal = parseNumberAttrVal(val); + // ignore changes before model is initialized + if (isNumberNaN(ctrl.$modelValue)) { + return; + } + + if (supportsRange) { + var elVal = element.val(); + // IE11 doesn't set the el val correctly if the minVal is greater than the element value + if (minVal > elVal) { + elVal = minVal; + element.val(elVal); + } + ctrl.$setViewValue(elVal); + } else { + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); + } + } + + function maxChange(val) { + maxVal = parseNumberAttrVal(val); + // ignore changes before model is initialized + if (isNumberNaN(ctrl.$modelValue)) { + return; + } + + if (supportsRange) { + var elVal = element.val(); + // IE11 doesn't set the el val correctly if the maxVal is less than the element value + if (maxVal < elVal) { + element.val(maxVal); + // IE11 and Chrome don't set the value to the minVal when max < min + elVal = maxVal < minVal ? minVal : maxVal; + } + ctrl.$setViewValue(elVal); + } else { + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); + } + } + + function stepChange(val) { + stepVal = parseNumberAttrVal(val); + // ignore changes before model is initialized + if (isNumberNaN(ctrl.$modelValue)) { + return; + } + + // Some browsers don't adjust the input value correctly, but set the stepMismatch error + if (!supportsRange) { + // TODO(matsko): implement validateLater to reduce number of validations + ctrl.$validate(); + } else if (ctrl.$viewValue !== element.val()) { + ctrl.$setViewValue(element.val()); + } + } +} + +function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { + // Note: no badInputChecker here by purpose as `url` is only a validation + // in browsers, i.e. we can always read out input.value even if it is not valid! + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + + ctrl.$validators.url = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || URL_REGEXP.test(value); + }; +} + +function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { + // Note: no badInputChecker here by purpose as `url` is only a validation + // in browsers, i.e. we can always read out input.value even if it is not valid! + baseInputType(scope, element, attr, ctrl, $sniffer, $browser); + stringBasedInputType(ctrl); + + ctrl.$validators.email = function(modelValue, viewValue) { + var value = modelValue || viewValue; + return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value); + }; +} + +function radioInputType(scope, element, attr, ctrl) { + var doTrim = !attr.ngTrim || trim(attr.ngTrim) !== 'false'; + // make the name unique, if not defined + if (isUndefined(attr.name)) { + element.attr('name', nextUid()); + } + + var listener = function(ev) { + var value; + if (element[0].checked) { + value = attr.value; + if (doTrim) { + value = trim(value); + } + ctrl.$setViewValue(value, ev && ev.type); + } + }; + + element.on('change', listener); + + ctrl.$render = function() { + var value = attr.value; + if (doTrim) { + value = trim(value); + } + element[0].checked = (value === ctrl.$viewValue); + }; + + attr.$observe('value', ctrl.$render); +} + +function parseConstantExpr($parse, context, name, expression, fallback) { + var parseFn; + if (isDefined(expression)) { + parseFn = $parse(expression); + if (!parseFn.constant) { + throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' + + '`{1}`.', name, expression); + } + return parseFn(context); + } + return fallback; +} + +function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { + var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true); + var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false); + + var listener = function(ev) { + ctrl.$setViewValue(element[0].checked, ev && ev.type); + }; + + element.on('change', listener); + + ctrl.$render = function() { + element[0].checked = ctrl.$viewValue; + }; + + // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false` + // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert + // it to a boolean. + ctrl.$isEmpty = function(value) { + return value === false; + }; + + ctrl.$formatters.push(function(value) { + return equals(value, trueValue); + }); + + ctrl.$parsers.push(function(value) { + return value ? trueValue : falseValue; + }); +} + + +/** + * @ngdoc directive + * @name textarea + * @restrict E + * + * @description + * HTML textarea element control with AngularJS data-binding. The data-binding and validation + * properties of this element are exactly the same as those of the + * {@link ng.directive:input input element}. + * + * @param {string} ngModel Assignable AngularJS expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} required Sets `required` validation error key if the value is not entered. + * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to + * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of + * `required` when you want to data-bind to the `required` attribute. + * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than + * minlength. + * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than + * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any + * length. + * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} + * does not match a RegExp found by evaluating the AngularJS expression given in the attribute value. + * If the expression evaluates to a RegExp object, then this is used directly. + * If the expression evaluates to a string, then it will be converted to a RegExp + * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to + * `new RegExp('^abc$')`.
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + * @param {string=} ngChange AngularJS expression to be executed when input changes due to user + * interaction with the input element. + * @param {boolean=} [ngTrim=true] If set to false AngularJS will not automatically trim the input. + * + * @knownIssue + * + * When specifying the `placeholder` attribute of ` + *
    {{ list | json }}
    + * + * + * it("should split the text by newlines", function() { + * var listInput = element(by.model('list')); + * var output = element(by.binding('list | json')); + * listInput.sendKeys('abc\ndef\nghi'); + * expect(output.getText()).toContain('[\n "abc",\n "def",\n "ghi"\n]'); + * }); + * + * + * + */ +var ngListDirective = function() { + return { + restrict: 'A', + priority: 100, + require: 'ngModel', + link: function(scope, element, attr, ctrl) { + var ngList = attr.ngList || ', '; + var trimValues = attr.ngTrim !== 'false'; + var separator = trimValues ? trim(ngList) : ngList; + + var parse = function(viewValue) { + // If the viewValue is invalid (say required but empty) it will be `undefined` + if (isUndefined(viewValue)) return; + + var list = []; + + if (viewValue) { + forEach(viewValue.split(separator), function(value) { + if (value) list.push(trimValues ? trim(value) : value); + }); + } + + return list; + }; + + ctrl.$parsers.push(parse); + ctrl.$formatters.push(function(value) { + if (isArray(value)) { + return value.join(ngList); + } + + return undefined; + }); + + // Override the standard $isEmpty because an empty array means the input is empty. + ctrl.$isEmpty = function(value) { + return !value || !value.length; + }; + } + }; +}; + +/* global VALID_CLASS: true, + INVALID_CLASS: true, + PRISTINE_CLASS: true, + DIRTY_CLASS: true, + UNTOUCHED_CLASS: true, + TOUCHED_CLASS: true, + PENDING_CLASS: true, + addSetValidityMethod: true, + setupValidity: true, + defaultModelOptions: false +*/ + + +var VALID_CLASS = 'ng-valid', + INVALID_CLASS = 'ng-invalid', + PRISTINE_CLASS = 'ng-pristine', + DIRTY_CLASS = 'ng-dirty', + UNTOUCHED_CLASS = 'ng-untouched', + TOUCHED_CLASS = 'ng-touched', + EMPTY_CLASS = 'ng-empty', + NOT_EMPTY_CLASS = 'ng-not-empty'; + +var ngModelMinErr = minErr('ngModel'); + +/** + * @ngdoc type + * @name ngModel.NgModelController + * @property {*} $viewValue The actual value from the control's view. For `input` elements, this is a + * String. See {@link ngModel.NgModelController#$setViewValue} for information about when the $viewValue + * is set. + * + * @property {*} $modelValue The value in the model that the control is bound to. + * + * @property {Array.} $parsers Array of functions to execute, as a pipeline, whenever + * the control updates the ngModelController with a new {@link ngModel.NgModelController#$viewValue + `$viewValue`} from the DOM, usually via user input. + See {@link ngModel.NgModelController#$setViewValue `$setViewValue()`} for a detailed lifecycle explanation. + Note that the `$parsers` are not called when the bound ngModel expression changes programmatically. + + The functions are called in array order, each passing + its return value through to the next. The last return value is forwarded to the + {@link ngModel.NgModelController#$validators `$validators`} collection. + + Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue + `$viewValue`}. + + Returning `undefined` from a parser means a parse error occurred. In that case, + no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel` + will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`} + is set to `true`. The parse error is stored in `ngModel.$error.parse`. + + This simple example shows a parser that would convert text input value to lowercase: + * ```js + * function parse(value) { + * if (value) { + * return value.toLowerCase(); + * } + * } + * ngModelController.$parsers.push(parse); + * ``` + + * + * @property {Array.} $formatters Array of functions to execute, as a pipeline, whenever + the bound ngModel expression changes programmatically. The `$formatters` are not called when the + value of the control is changed by user interaction. + + Formatters are used to format / convert the {@link ngModel.NgModelController#$modelValue + `$modelValue`} for display in the control. + + The functions are called in reverse array order, each passing the value through to the + next. The last return value is used as the actual DOM value. + + This simple example shows a formatter that would convert the model value to uppercase: + + * ```js + * function format(value) { + * if (value) { + * return value.toUpperCase(); + * } + * } + * ngModel.$formatters.push(format); + * ``` + * + * @property {Object.} $validators A collection of validators that are applied + * whenever the model value changes. The key value within the object refers to the name of the + * validator while the function refers to the validation operation. The validation operation is + * provided with the model value as an argument and must return a true or false value depending + * on the response of that validation. + * + * ```js + * ngModel.$validators.validCharacters = function(modelValue, viewValue) { + * var value = modelValue || viewValue; + * return /[0-9]+/.test(value) && + * /[a-z]+/.test(value) && + * /[A-Z]+/.test(value) && + * /\W+/.test(value); + * }; + * ``` + * + * @property {Object.} $asyncValidators A collection of validations that are expected to + * perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided + * is expected to return a promise when it is run during the model validation process. Once the promise + * is delivered then the validation status will be set to true when fulfilled and false when rejected. + * When the asynchronous validators are triggered, each of the validators will run in parallel and the model + * value will only be updated once all validators have been fulfilled. As long as an asynchronous validator + * is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators + * will only run once all synchronous validators have passed. + * + * Please note that if $http is used then it is important that the server returns a success HTTP response code + * in order to fulfill the validation and a status level of `4xx` in order to reject the validation. + * + * ```js + * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) { + * var value = modelValue || viewValue; + * + * // Lookup user by username + * return $http.get('/api/users/' + value). + * then(function resolved() { + * //username exists, this means validation fails + * return $q.reject('exists'); + * }, function rejected() { + * //username does not exist, therefore this validation passes + * return true; + * }); + * }; + * ``` + * + * @property {Array.} $viewChangeListeners Array of functions to execute whenever + * a change to {@link ngModel.NgModelController#$viewValue `$viewValue`} has caused a change + * to {@link ngModel.NgModelController#$modelValue `$modelValue`}. + * It is called with no arguments, and its return value is ignored. + * This can be used in place of additional $watches against the model value. + * + * @property {Object} $error An object hash with all failing validator ids as keys. + * @property {Object} $pending An object hash with all pending validator ids as keys. + * + * @property {boolean} $untouched True if control has not lost focus yet. + * @property {boolean} $touched True if control has lost focus. + * @property {boolean} $pristine True if user has not interacted with the control yet. + * @property {boolean} $dirty True if user has already interacted with the control. + * @property {boolean} $valid True if there is no error. + * @property {boolean} $invalid True if at least one error on the control. + * @property {string} $name The name attribute of the control. + * + * @description + * + * `NgModelController` provides API for the {@link ngModel `ngModel`} directive. + * The controller contains services for data-binding, validation, CSS updates, and value formatting + * and parsing. It purposefully does not contain any logic which deals with DOM rendering or + * listening to DOM events. + * Such DOM related logic should be provided by other directives which make use of + * `NgModelController` for data-binding to control elements. + * AngularJS provides this DOM logic for most {@link input `input`} elements. + * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example + * custom control example} that uses `ngModelController` to bind to `contenteditable` elements. + * + * @example + * ### Custom Control Example + * This example shows how to use `NgModelController` with a custom control to achieve + * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`) + * collaborate together to achieve the desired result. + * + * `contenteditable` is an HTML5 attribute, which tells the browser to let the element + * contents be edited in place by the user. + * + * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize} + * module to automatically remove "bad" content like inline event listener (e.g. ``). + * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks + * that content using the `$sce` service. + * + * + + [contenteditable] { + border: 1px solid black; + background-color: white; + min-height: 20px; + } + + .ng-invalid { + border: 1px solid red; + } + + + + angular.module('customControl', ['ngSanitize']). + directive('contenteditable', ['$sce', function($sce) { + return { + restrict: 'A', // only activate on element attribute + require: '?ngModel', // get a hold of NgModelController + link: function(scope, element, attrs, ngModel) { + if (!ngModel) return; // do nothing if no ng-model + + // Specify how UI should be updated + ngModel.$render = function() { + element.html($sce.getTrustedHtml(ngModel.$viewValue || '')); + }; + + // Listen for change events to enable binding + element.on('blur keyup change', function() { + scope.$evalAsync(read); + }); + read(); // initialize + + // Write data to the model + function read() { + var html = element.html(); + // When we clear the content editable the browser leaves a
    behind + // If strip-br attribute is provided then we strip this out + if (attrs.stripBr && html === '
    ') { + html = ''; + } + ngModel.$setViewValue(html); + } + } + }; + }]); +
    + +
    +
    Change me!
    + Required! +
    + +
    +
    + + it('should data-bind and become invalid', function() { + if (browser.params.browser === 'safari' || browser.params.browser === 'firefox') { + // SafariDriver can't handle contenteditable + // and Firefox driver can't clear contenteditables very well + return; + } + var contentEditable = element(by.css('[contenteditable]')); + var content = 'Change me!'; + + expect(contentEditable.getText()).toEqual(content); + + contentEditable.clear(); + contentEditable.sendKeys(protractor.Key.BACK_SPACE); + expect(contentEditable.getText()).toEqual(''); + expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/); + }); + + *
    + * + * + */ +NgModelController.$inject = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$q', '$interpolate']; +function NgModelController($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $q, $interpolate) { + this.$viewValue = Number.NaN; + this.$modelValue = Number.NaN; + this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity. + this.$validators = {}; + this.$asyncValidators = {}; + this.$parsers = []; + this.$formatters = []; + this.$viewChangeListeners = []; + this.$untouched = true; + this.$touched = false; + this.$pristine = true; + this.$dirty = false; + this.$valid = true; + this.$invalid = false; + this.$error = {}; // keep invalid keys here + this.$$success = {}; // keep valid keys here + this.$pending = undefined; // keep pending keys here + this.$name = $interpolate($attr.name || '', false)($scope); + this.$$parentForm = nullFormCtrl; + this.$options = defaultModelOptions; + this.$$updateEvents = ''; + // Attach the correct context to the event handler function for updateOn + this.$$updateEventHandler = this.$$updateEventHandler.bind(this); + + this.$$parsedNgModel = $parse($attr.ngModel); + this.$$parsedNgModelAssign = this.$$parsedNgModel.assign; + this.$$ngModelGet = this.$$parsedNgModel; + this.$$ngModelSet = this.$$parsedNgModelAssign; + this.$$pendingDebounce = null; + this.$$parserValid = undefined; + this.$$parserName = 'parse'; + + this.$$currentValidationRunId = 0; + + this.$$scope = $scope; + this.$$rootScope = $scope.$root; + this.$$attr = $attr; + this.$$element = $element; + this.$$animate = $animate; + this.$$timeout = $timeout; + this.$$parse = $parse; + this.$$q = $q; + this.$$exceptionHandler = $exceptionHandler; + + setupValidity(this); + setupModelWatcher(this); +} + +NgModelController.prototype = { + $$initGetterSetters: function() { + if (this.$options.getOption('getterSetter')) { + var invokeModelGetter = this.$$parse(this.$$attr.ngModel + '()'), + invokeModelSetter = this.$$parse(this.$$attr.ngModel + '($$$p)'); + + this.$$ngModelGet = function($scope) { + var modelValue = this.$$parsedNgModel($scope); + if (isFunction(modelValue)) { + modelValue = invokeModelGetter($scope); + } + return modelValue; + }; + this.$$ngModelSet = function($scope, newValue) { + if (isFunction(this.$$parsedNgModel($scope))) { + invokeModelSetter($scope, {$$$p: newValue}); + } else { + this.$$parsedNgModelAssign($scope, newValue); + } + }; + } else if (!this.$$parsedNgModel.assign) { + throw ngModelMinErr('nonassign', 'Expression \'{0}\' is non-assignable. Element: {1}', + this.$$attr.ngModel, startingTag(this.$$element)); + } + }, + + + /** + * @ngdoc method + * @name ngModel.NgModelController#$render + * + * @description + * Called when the view needs to be updated. It is expected that the user of the ng-model + * directive will implement this method. + * + * The `$render()` method is invoked in the following situations: + * + * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last + * committed value then `$render()` is called to update the input control. + * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and + * the `$viewValue` are different from last time. + * + * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of + * `$modelValue` and `$viewValue` are actually different from their previous values. If `$modelValue` + * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be + * invoked if you only change a property on the objects. + */ + $render: noop, + + /** + * @ngdoc method + * @name ngModel.NgModelController#$isEmpty + * + * @description + * This is called when we need to determine if the value of an input is empty. + * + * For instance, the required directive does this to work out if the input has data or not. + * + * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`. + * + * You can override this for input directives whose concept of being empty is different from the + * default. The `checkboxInputType` directive does this because in its case a value of `false` + * implies empty. + * + * @param {*} value The value of the input to check for emptiness. + * @returns {boolean} True if `value` is "empty". + */ + $isEmpty: function(value) { + // eslint-disable-next-line no-self-compare + return isUndefined(value) || value === '' || value === null || value !== value; + }, + + $$updateEmptyClasses: function(value) { + if (this.$isEmpty(value)) { + this.$$animate.removeClass(this.$$element, NOT_EMPTY_CLASS); + this.$$animate.addClass(this.$$element, EMPTY_CLASS); + } else { + this.$$animate.removeClass(this.$$element, EMPTY_CLASS); + this.$$animate.addClass(this.$$element, NOT_EMPTY_CLASS); + } + }, + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setPristine + * + * @description + * Sets the control to its pristine state. + * + * This method can be called to remove the `ng-dirty` class and set the control to its pristine + * state (`ng-pristine` class). A model is considered to be pristine when the control + * has not been changed from when first compiled. + */ + $setPristine: function() { + this.$dirty = false; + this.$pristine = true; + this.$$animate.removeClass(this.$$element, DIRTY_CLASS); + this.$$animate.addClass(this.$$element, PRISTINE_CLASS); + }, + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setDirty + * + * @description + * Sets the control to its dirty state. + * + * This method can be called to remove the `ng-pristine` class and set the control to its dirty + * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed + * from when first compiled. + */ + $setDirty: function() { + this.$dirty = true; + this.$pristine = false; + this.$$animate.removeClass(this.$$element, PRISTINE_CLASS); + this.$$animate.addClass(this.$$element, DIRTY_CLASS); + this.$$parentForm.$setDirty(); + }, + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setUntouched + * + * @description + * Sets the control to its untouched state. + * + * This method can be called to remove the `ng-touched` class and set the control to its + * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched + * by default, however this function can be used to restore that state if the model has + * already been touched by the user. + */ + $setUntouched: function() { + this.$touched = false; + this.$untouched = true; + this.$$animate.setClass(this.$$element, UNTOUCHED_CLASS, TOUCHED_CLASS); + }, + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setTouched + * + * @description + * Sets the control to its touched state. + * + * This method can be called to remove the `ng-untouched` class and set the control to its + * touched state (`ng-touched` class). A model is considered to be touched when the user has + * first focused the control element and then shifted focus away from the control (blur event). + */ + $setTouched: function() { + this.$touched = true; + this.$untouched = false; + this.$$animate.setClass(this.$$element, TOUCHED_CLASS, UNTOUCHED_CLASS); + }, + + /** + * @ngdoc method + * @name ngModel.NgModelController#$rollbackViewValue + * + * @description + * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`, + * which may be caused by a pending debounced event or because the input is waiting for some + * future event. + * + * If you have an input that uses `ng-model-options` to set up debounced updates or updates that + * depend on special events such as `blur`, there can be a period when the `$viewValue` is out of + * sync with the ngModel's `$modelValue`. + * + * In this case, you can use `$rollbackViewValue()` to manually cancel the debounced / future update + * and reset the input to the last committed view value. + * + * It is also possible that you run into difficulties if you try to update the ngModel's `$modelValue` + * programmatically before these debounced/future events have resolved/occurred, because AngularJS's + * dirty checking mechanism is not able to tell whether the model has actually changed or not. + * + * The `$rollbackViewValue()` method should be called before programmatically changing the model of an + * input which may have such events pending. This is important in order to make sure that the + * input field will be updated with the new model value and any pending operations are cancelled. + * + * @example + * + * + * angular.module('cancel-update-example', []) + * + * .controller('CancelUpdateController', ['$scope', function($scope) { + * $scope.model = {value1: '', value2: ''}; + * + * $scope.setEmpty = function(e, value, rollback) { + * if (e.keyCode === 27) { + * e.preventDefault(); + * if (rollback) { + * $scope.myForm[value].$rollbackViewValue(); + * } + * $scope.model[value] = ''; + * } + * }; + * }]); + * + * + *
    + *

    Both of these inputs are only updated if they are blurred. Hitting escape should + * empty them. Follow these steps and observe the difference:

    + *
      + *
    1. Type something in the input. You will see that the model is not yet updated
    2. + *
    3. Press the Escape key. + *
        + *
      1. In the first example, nothing happens, because the model is already '', and no + * update is detected. If you blur the input, the model will be set to the current view. + *
      2. + *
      3. In the second example, the pending update is cancelled, and the input is set back + * to the last committed view value (''). Blurring the input does nothing. + *
      4. + *
      + *
    4. + *
    + * + *
    + *
    + *

    Without $rollbackViewValue():

    + * + * value1: "{{ model.value1 }}" + *
    + * + *
    + *

    With $rollbackViewValue():

    + * + * value2: "{{ model.value2 }}" + *
    + *
    + *
    + *
    + + div { + display: table-cell; + } + div:nth-child(1) { + padding-right: 30px; + } + + + *
    + */ + $rollbackViewValue: function() { + this.$$timeout.cancel(this.$$pendingDebounce); + this.$viewValue = this.$$lastCommittedViewValue; + this.$render(); + }, + + /** + * @ngdoc method + * @name ngModel.NgModelController#$validate + * + * @description + * Runs each of the registered validators (first synchronous validators and then + * asynchronous validators). + * If the validity changes to invalid, the model will be set to `undefined`, + * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`. + * If the validity changes to valid, it will set the model to the last available valid + * `$modelValue`, i.e. either the last parsed value or the last value set from the scope. + */ + $validate: function() { + + // ignore $validate before model is initialized + if (isNumberNaN(this.$modelValue)) { + return; + } + + var viewValue = this.$$lastCommittedViewValue; + // Note: we use the $$rawModelValue as $modelValue might have been + // set to undefined during a view -> model update that found validation + // errors. We can't parse the view here, since that could change + // the model although neither viewValue nor the model on the scope changed + var modelValue = this.$$rawModelValue; + + var prevValid = this.$valid; + var prevModelValue = this.$modelValue; + + var allowInvalid = this.$options.getOption('allowInvalid'); + + var that = this; + this.$$runValidators(modelValue, viewValue, function(allValid) { + // If there was no change in validity, don't update the model + // This prevents changing an invalid modelValue to undefined + if (!allowInvalid && prevValid !== allValid) { + // Note: Don't check this.$valid here, as we could have + // external validators (e.g. calculated on the server), + // that just call $setValidity and need the model value + // to calculate their validity. + that.$modelValue = allValid ? modelValue : undefined; + + if (that.$modelValue !== prevModelValue) { + that.$$writeModelToScope(); + } + } + }); + }, + + $$runValidators: function(modelValue, viewValue, doneCallback) { + this.$$currentValidationRunId++; + var localValidationRunId = this.$$currentValidationRunId; + var that = this; + + // check parser error + if (!processParseErrors()) { + validationDone(false); + return; + } + if (!processSyncValidators()) { + validationDone(false); + return; + } + processAsyncValidators(); + + function processParseErrors() { + var errorKey = that.$$parserName; + + if (isUndefined(that.$$parserValid)) { + setValidity(errorKey, null); + } else { + if (!that.$$parserValid) { + forEach(that.$validators, function(v, name) { + setValidity(name, null); + }); + forEach(that.$asyncValidators, function(v, name) { + setValidity(name, null); + }); + } + + // Set the parse error last, to prevent unsetting it, should a $validators key == parserName + setValidity(errorKey, that.$$parserValid); + return that.$$parserValid; + } + return true; + } + + function processSyncValidators() { + var syncValidatorsValid = true; + forEach(that.$validators, function(validator, name) { + var result = Boolean(validator(modelValue, viewValue)); + syncValidatorsValid = syncValidatorsValid && result; + setValidity(name, result); + }); + if (!syncValidatorsValid) { + forEach(that.$asyncValidators, function(v, name) { + setValidity(name, null); + }); + return false; + } + return true; + } + + function processAsyncValidators() { + var validatorPromises = []; + var allValid = true; + forEach(that.$asyncValidators, function(validator, name) { + var promise = validator(modelValue, viewValue); + if (!isPromiseLike(promise)) { + throw ngModelMinErr('nopromise', + 'Expected asynchronous validator to return a promise but got \'{0}\' instead.', promise); + } + setValidity(name, undefined); + validatorPromises.push(promise.then(function() { + setValidity(name, true); + }, function() { + allValid = false; + setValidity(name, false); + })); + }); + if (!validatorPromises.length) { + validationDone(true); + } else { + that.$$q.all(validatorPromises).then(function() { + validationDone(allValid); + }, noop); + } + } + + function setValidity(name, isValid) { + if (localValidationRunId === that.$$currentValidationRunId) { + that.$setValidity(name, isValid); + } + } + + function validationDone(allValid) { + if (localValidationRunId === that.$$currentValidationRunId) { + + doneCallback(allValid); + } + } + }, + + /** + * @ngdoc method + * @name ngModel.NgModelController#$commitViewValue + * + * @description + * Commit a pending update to the `$modelValue`. + * + * Updates may be pending by a debounced event or because the input is waiting for a some future + * event defined in `ng-model-options`. this method is rarely needed as `NgModelController` + * usually handles calling this in response to input events. + */ + $commitViewValue: function() { + var viewValue = this.$viewValue; + + this.$$timeout.cancel(this.$$pendingDebounce); + + // If the view value has not changed then we should just exit, except in the case where there is + // a native validator on the element. In this case the validation state may have changed even though + // the viewValue has stayed empty. + if (this.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !this.$$hasNativeValidators)) { + return; + } + this.$$updateEmptyClasses(viewValue); + this.$$lastCommittedViewValue = viewValue; + + // change to dirty + if (this.$pristine) { + this.$setDirty(); + } + this.$$parseAndValidate(); + }, + + $$parseAndValidate: function() { + var viewValue = this.$$lastCommittedViewValue; + var modelValue = viewValue; + var that = this; + + this.$$parserValid = isUndefined(modelValue) ? undefined : true; + + // Reset any previous parse error + this.$setValidity(this.$$parserName, null); + this.$$parserName = 'parse'; + + if (this.$$parserValid) { + for (var i = 0; i < this.$parsers.length; i++) { + modelValue = this.$parsers[i](modelValue); + if (isUndefined(modelValue)) { + this.$$parserValid = false; + break; + } + } + } + if (isNumberNaN(this.$modelValue)) { + // this.$modelValue has not been touched yet... + this.$modelValue = this.$$ngModelGet(this.$$scope); + } + var prevModelValue = this.$modelValue; + var allowInvalid = this.$options.getOption('allowInvalid'); + this.$$rawModelValue = modelValue; + + if (allowInvalid) { + this.$modelValue = modelValue; + writeToModelIfNeeded(); + } + + // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date. + // This can happen if e.g. $setViewValue is called from inside a parser + this.$$runValidators(modelValue, this.$$lastCommittedViewValue, function(allValid) { + if (!allowInvalid) { + // Note: Don't check this.$valid here, as we could have + // external validators (e.g. calculated on the server), + // that just call $setValidity and need the model value + // to calculate their validity. + that.$modelValue = allValid ? modelValue : undefined; + writeToModelIfNeeded(); + } + }); + + function writeToModelIfNeeded() { + if (that.$modelValue !== prevModelValue) { + that.$$writeModelToScope(); + } + } + }, + + $$writeModelToScope: function() { + this.$$ngModelSet(this.$$scope, this.$modelValue); + forEach(this.$viewChangeListeners, function(listener) { + try { + listener(); + } catch (e) { + // eslint-disable-next-line no-invalid-this + this.$$exceptionHandler(e); + } + }, this); + }, + + /** + * @ngdoc method + * @name ngModel.NgModelController#$setViewValue + * + * @description + * Update the view value. + * + * This method should be called when a control wants to change the view value; typically, + * this is done from within a DOM event handler. For example, the {@link ng.directive:input input} + * directive calls it when the value of the input changes and {@link ng.directive:select select} + * calls it when an option is selected. + * + * When `$setViewValue` is called, the new `value` will be staged for committing through the `$parsers` + * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged + * value is sent directly for processing through the `$parsers` pipeline. After this, the `$validators` and + * `$asyncValidators` are called and the value is applied to `$modelValue`. + * Finally, the value is set to the **expression** specified in the `ng-model` attribute and + * all the registered change listeners, in the `$viewChangeListeners` list are called. + * + * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn` + * and the `default` trigger is not listed, all those actions will remain pending until one of the + * `updateOn` events is triggered on the DOM element. + * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions} + * directive is used with a custom debounce for this particular event. + * Note that a `$digest` is only triggered once the `updateOn` events are fired, or if `debounce` + * is specified, once the timer runs out. + * + * When used with standard inputs, the view value will always be a string (which is in some cases + * parsed into another type, such as a `Date` object for `input[date]`.) + * However, custom controls might also pass objects to this method. In this case, we should make + * a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not + * perform a deep watch of objects, it only looks for a change of identity. If you only change + * the property of the object then ngModel will not realize that the object has changed and + * will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should + * not change properties of the copy once it has been passed to `$setViewValue`. + * Otherwise you may cause the model value on the scope to change incorrectly. + * + *
    + * In any case, the value passed to the method should always reflect the current value + * of the control. For example, if you are calling `$setViewValue` for an input element, + * you should pass the input DOM value. Otherwise, the control and the scope model become + * out of sync. It's also important to note that `$setViewValue` does not call `$render` or change + * the control's DOM value in any way. If we want to change the control's DOM value + * programmatically, we should update the `ngModel` scope expression. Its new value will be + * picked up by the model controller, which will run it through the `$formatters`, `$render` it + * to update the DOM, and finally call `$validate` on it. + *
    + * + * @param {*} value value from the view. + * @param {string} trigger Event that triggered the update. + */ + $setViewValue: function(value, trigger) { + this.$viewValue = value; + if (this.$options.getOption('updateOnDefault')) { + this.$$debounceViewValueCommit(trigger); + } + }, + + $$debounceViewValueCommit: function(trigger) { + var debounceDelay = this.$options.getOption('debounce'); + + if (isNumber(debounceDelay[trigger])) { + debounceDelay = debounceDelay[trigger]; + } else if (isNumber(debounceDelay['default']) && + this.$options.getOption('updateOn').indexOf(trigger) === -1 + ) { + debounceDelay = debounceDelay['default']; + } else if (isNumber(debounceDelay['*'])) { + debounceDelay = debounceDelay['*']; + } + + this.$$timeout.cancel(this.$$pendingDebounce); + var that = this; + if (debounceDelay > 0) { // this fails if debounceDelay is an object + this.$$pendingDebounce = this.$$timeout(function() { + that.$commitViewValue(); + }, debounceDelay); + } else if (this.$$rootScope.$$phase) { + this.$commitViewValue(); + } else { + this.$$scope.$apply(function() { + that.$commitViewValue(); + }); + } + }, + + /** + * @ngdoc method + * + * @name ngModel.NgModelController#$overrideModelOptions + * + * @description + * + * Override the current model options settings programmatically. + * + * The previous `ModelOptions` value will not be modified. Instead, a + * new `ModelOptions` object will inherit from the previous one overriding + * or inheriting settings that are defined in the given parameter. + * + * See {@link ngModelOptions} for information about what options can be specified + * and how model option inheritance works. + * + *
    + * **Note:** this function only affects the options set on the `ngModelController`, + * and not the options on the {@link ngModelOptions} directive from which they might have been + * obtained initially. + *
    + * + *
    + * **Note:** it is not possible to override the `getterSetter` option. + *
    + * + * @param {Object} options a hash of settings to override the previous options + * + */ + $overrideModelOptions: function(options) { + this.$options = this.$options.createChild(options); + this.$$setUpdateOnEvents(); + }, + + /** + * @ngdoc method + * + * @name ngModel.NgModelController#$processModelValue + + * @description + * + * Runs the model -> view pipeline on the current + * {@link ngModel.NgModelController#$modelValue $modelValue}. + * + * The following actions are performed by this method: + * + * - the `$modelValue` is run through the {@link ngModel.NgModelController#$formatters $formatters} + * and the result is set to the {@link ngModel.NgModelController#$viewValue $viewValue} + * - the `ng-empty` or `ng-not-empty` class is set on the element + * - if the `$viewValue` has changed: + * - {@link ngModel.NgModelController#$render $render} is called on the control + * - the {@link ngModel.NgModelController#$validators $validators} are run and + * the validation status is set. + * + * This method is called by ngModel internally when the bound scope value changes. + * Application developers usually do not have to call this function themselves. + * + * This function can be used when the `$viewValue` or the rendered DOM value are not correctly + * formatted and the `$modelValue` must be run through the `$formatters` again. + * + * @example + * Consider a text input with an autocomplete list (for fruit), where the items are + * objects with a name and an id. + * A user enters `ap` and then selects `Apricot` from the list. + * Based on this, the autocomplete widget will call `$setViewValue({name: 'Apricot', id: 443})`, + * but the rendered value will still be `ap`. + * The widget can then call `ctrl.$processModelValue()` to run the model -> view + * pipeline again, which formats the object to the string `Apricot`, + * then updates the `$viewValue`, and finally renders it in the DOM. + * + * + +
    +
    + Search Fruit: + +
    +
    + Model:
    +
    {{selectedFruit | json}}
    +
    +
    +
    + + angular.module('inputExample', []) + .controller('inputController', function($scope) { + $scope.items = [ + {name: 'Apricot', id: 443}, + {name: 'Clementine', id: 972}, + {name: 'Durian', id: 169}, + {name: 'Jackfruit', id: 982}, + {name: 'Strawberry', id: 863} + ]; + }) + .component('basicAutocomplete', { + bindings: { + items: '<', + onSelect: '&' + }, + templateUrl: 'autocomplete.html', + controller: function($element, $scope) { + var that = this; + var ngModel; + + that.$postLink = function() { + ngModel = $element.find('input').controller('ngModel'); + + ngModel.$formatters.push(function(value) { + return (value && value.name) || value; + }); + + ngModel.$parsers.push(function(value) { + var match = value; + for (var i = 0; i < that.items.length; i++) { + if (that.items[i].name === value) { + match = that.items[i]; + break; + } + } + + return match; + }); + }; + + that.selectItem = function(item) { + ngModel.$setViewValue(item); + ngModel.$processModelValue(); + that.onSelect({item: item}); + }; + } + }); + + +
    + +
      +
    • + +
    • +
    +
    +
    + *
    + * + */ + $processModelValue: function() { + var viewValue = this.$$format(); + + if (this.$viewValue !== viewValue) { + this.$$updateEmptyClasses(viewValue); + this.$viewValue = this.$$lastCommittedViewValue = viewValue; + this.$render(); + // It is possible that model and view value have been updated during render + this.$$runValidators(this.$modelValue, this.$viewValue, noop); + } + }, + + /** + * This method is called internally to run the $formatters on the $modelValue + */ + $$format: function() { + var formatters = this.$formatters, + idx = formatters.length; + + var viewValue = this.$modelValue; + while (idx--) { + viewValue = formatters[idx](viewValue); + } + + return viewValue; + }, + + /** + * This method is called internally when the bound scope value changes. + */ + $$setModelValue: function(modelValue) { + this.$modelValue = this.$$rawModelValue = modelValue; + this.$$parserValid = undefined; + this.$processModelValue(); + }, + + $$setUpdateOnEvents: function() { + if (this.$$updateEvents) { + this.$$element.off(this.$$updateEvents, this.$$updateEventHandler); + } + + this.$$updateEvents = this.$options.getOption('updateOn'); + if (this.$$updateEvents) { + this.$$element.on(this.$$updateEvents, this.$$updateEventHandler); + } + }, + + $$updateEventHandler: function(ev) { + this.$$debounceViewValueCommit(ev && ev.type); + } +}; + +function setupModelWatcher(ctrl) { + // model -> value + // Note: we cannot use a normal scope.$watch as we want to detect the following: + // 1. scope value is 'a' + // 2. user enters 'b' + // 3. ng-change kicks in and reverts scope value to 'a' + // -> scope value did not change since the last digest as + // ng-change executes in apply phase + // 4. view should be changed back to 'a' + ctrl.$$scope.$watch(function ngModelWatch(scope) { + var modelValue = ctrl.$$ngModelGet(scope); + + // if scope model value and ngModel value are out of sync + // This cannot be moved to the action function, because it would not catch the + // case where the model is changed in the ngChange function or the model setter + if (modelValue !== ctrl.$modelValue && + // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator + // eslint-disable-next-line no-self-compare + (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue) + ) { + ctrl.$$setModelValue(modelValue); + } + + return modelValue; + }); +} + +/** + * @ngdoc method + * @name ngModel.NgModelController#$setValidity + * + * @description + * Change the validity state, and notify the form. + * + * This method can be called within $parsers/$formatters or a custom validation implementation. + * However, in most cases it should be sufficient to use the `ngModel.$validators` and + * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically. + * + * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned + * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]` + * (for unfulfilled `$asyncValidators`), so that it is available for data-binding. + * The `validationErrorKey` should be in camelCase and will get converted into dash-case + * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error` + * classes and can be bound to as `{{ someForm.someControl.$error.myError }}`. + * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined), + * or skipped (null). Pending is used for unfulfilled `$asyncValidators`. + * Skipped is used by AngularJS when validators do not run because of parse errors and + * when `$asyncValidators` do not run because any of the `$validators` failed. + */ +addSetValidityMethod({ + clazz: NgModelController, + set: function(object, property) { + object[property] = true; + }, + unset: function(object, property) { + delete object[property]; + } +}); + + +/** + * @ngdoc directive + * @name ngModel + * @restrict A + * @priority 1 + * @param {expression} ngModel assignable {@link guide/expression Expression} to bind to. + * + * @description + * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a + * property on the scope using {@link ngModel.NgModelController NgModelController}, + * which is created and exposed by this directive. + * + * `ngModel` is responsible for: + * + * - Binding the view into the model, which other directives such as `input`, `textarea` or `select` + * require. + * - Providing validation behavior (i.e. required, number, email, url). + * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors). + * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, + * `ng-untouched`, `ng-empty`, `ng-not-empty`) including animations. + * - Registering the control with its parent {@link ng.directive:form form}. + * + * Note: `ngModel` will try to bind to the property given by evaluating the expression on the + * current scope. If the property doesn't already exist on this scope, it will be created + * implicitly and added to the scope. + * + * For best practices on using `ngModel`, see: + * + * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes) + * + * For basic examples, how to use `ngModel`, see: + * + * - {@link ng.directive:input input} + * - {@link input[text] text} + * - {@link input[checkbox] checkbox} + * - {@link input[radio] radio} + * - {@link input[number] number} + * - {@link input[email] email} + * - {@link input[url] url} + * - {@link input[date] date} + * - {@link input[datetime-local] datetime-local} + * - {@link input[time] time} + * - {@link input[month] month} + * - {@link input[week] week} + * - {@link ng.directive:select select} + * - {@link ng.directive:textarea textarea} + * + * ## Complex Models (objects or collections) + * + * By default, `ngModel` watches the model by reference, not value. This is important to know when + * binding inputs to models that are objects (e.g. `Date`) or collections (e.g. arrays). If only properties of the + * object or collection change, `ngModel` will not be notified and so the input will not be re-rendered. + * + * The model must be assigned an entirely new object or collection before a re-rendering will occur. + * + * Some directives have options that will cause them to use a custom `$watchCollection` on the model expression + * - for example, `ngOptions` will do so when a `track by` clause is included in the comprehension expression or + * if the select is given the `multiple` attribute. + * + * The `$watchCollection()` method only does a shallow comparison, meaning that changing properties deeper than the + * first level of the object (or only changing the properties of an item in the collection if it's an array) will still + * not trigger a re-rendering of the model. + * + * ## CSS classes + * The following CSS classes are added and removed on the associated input/select/textarea element + * depending on the validity of the model. + * + * - `ng-valid`: the model is valid + * - `ng-invalid`: the model is invalid + * - `ng-valid-[key]`: for each valid key added by `$setValidity` + * - `ng-invalid-[key]`: for each invalid key added by `$setValidity` + * - `ng-pristine`: the control hasn't been interacted with yet + * - `ng-dirty`: the control has been interacted with + * - `ng-touched`: the control has been blurred + * - `ng-untouched`: the control hasn't been blurred + * - `ng-pending`: any `$asyncValidators` are unfulfilled + * - `ng-empty`: the view does not contain a value or the value is deemed "empty", as defined + * by the {@link ngModel.NgModelController#$isEmpty} method + * - `ng-not-empty`: the view contains a non-empty value + * + * Keep in mind that ngAnimate can detect each of these classes when added and removed. + * + * @animations + * Animations within models are triggered when any of the associated CSS classes are added and removed + * on the input element which is attached to the model. These classes include: `.ng-pristine`, `.ng-dirty`, + * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself. + * The animations that are triggered within ngModel are similar to how they work in ngClass and + * animations can be hooked into using CSS transitions, keyframes as well as JS animations. + * + * The following example shows a simple way to utilize CSS transitions to style an input element + * that has been rendered as invalid after it has been validated: + * + *
    + * //be sure to include ngAnimate as a module to hook into more
    + * //advanced animations
    + * .my-input {
    + *   transition:0.5s linear all;
    + *   background: white;
    + * }
    + * .my-input.ng-invalid {
    + *   background: red;
    + *   color:white;
    + * }
    + * 
    + * + * @example + * ### Basic Usage + * + + + +

    + Update input to see transitions when valid/invalid. + Integer is a valid value. +

    +
    + +
    +
    + *
    + * + * @example + * ### Binding to a getter/setter + * + * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a + * function that returns a representation of the model when called with zero arguments, and sets + * the internal state of a model when called with an argument. It's sometimes useful to use this + * for models that have an internal representation that's different from what the model exposes + * to the view. + * + *
    + * **Best Practice:** It's best to keep getters fast because AngularJS is likely to call them more + * frequently than other parts of your code. + *
    + * + * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that + * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to + * a `
    `, which will enable this behavior for all ``s within it. See + * {@link ng.directive:ngModelOptions `ngModelOptions`} for more. + * + * The following example shows how to use `ngModel` with a getter/setter: + * + * @example + * + +
    + + + +
    user.name = 
    +
    +
    + + angular.module('getterSetterExample', []) + .controller('ExampleController', ['$scope', function($scope) { + var _name = 'Brian'; + $scope.user = { + name: function(newName) { + // Note that newName can be undefined for two reasons: + // 1. Because it is called as a getter and thus called with no arguments + // 2. Because the property should actually be set to undefined. This happens e.g. if the + // input is invalid + return arguments.length ? (_name = newName) : _name; + } + }; + }]); + + *
    + */ +var ngModelDirective = ['$rootScope', function($rootScope) { + return { + restrict: 'A', + require: ['ngModel', '^?form', '^?ngModelOptions'], + controller: NgModelController, + // Prelink needs to run before any input directive + // so that we can set the NgModelOptions in NgModelController + // before anyone else uses it. + priority: 1, + compile: function ngModelCompile(element) { + // Setup initial state of the control + element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS); + + return { + pre: function ngModelPreLink(scope, element, attr, ctrls) { + var modelCtrl = ctrls[0], + formCtrl = ctrls[1] || modelCtrl.$$parentForm, + optionsCtrl = ctrls[2]; + + if (optionsCtrl) { + modelCtrl.$options = optionsCtrl.$options; + } + + modelCtrl.$$initGetterSetters(); + + // notify others, especially parent forms + formCtrl.$addControl(modelCtrl); + + attr.$observe('name', function(newValue) { + if (modelCtrl.$name !== newValue) { + modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue); + } + }); + + scope.$on('$destroy', function() { + modelCtrl.$$parentForm.$removeControl(modelCtrl); + }); + }, + post: function ngModelPostLink(scope, element, attr, ctrls) { + var modelCtrl = ctrls[0]; + modelCtrl.$$setUpdateOnEvents(); + + function setTouched() { + modelCtrl.$setTouched(); + } + + element.on('blur', function() { + if (modelCtrl.$touched) return; + + if ($rootScope.$$phase) { + scope.$evalAsync(setTouched); + } else { + scope.$apply(setTouched); + } + }); + } + }; + } + }; +}]; + +/* exported defaultModelOptions */ +var defaultModelOptions; +var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/; + +/** + * @ngdoc type + * @name ModelOptions + * @description + * A container for the options set by the {@link ngModelOptions} directive + */ +function ModelOptions(options) { + this.$$options = options; +} + +ModelOptions.prototype = { + + /** + * @ngdoc method + * @name ModelOptions#getOption + * @param {string} name the name of the option to retrieve + * @returns {*} the value of the option + * @description + * Returns the value of the given option + */ + getOption: function(name) { + return this.$$options[name]; + }, + + /** + * @ngdoc method + * @name ModelOptions#createChild + * @param {Object} options a hash of options for the new child that will override the parent's options + * @return {ModelOptions} a new `ModelOptions` object initialized with the given options. + */ + createChild: function(options) { + var inheritAll = false; + + // make a shallow copy + options = extend({}, options); + + // Inherit options from the parent if specified by the value `"$inherit"` + forEach(options, /** @this */ function(option, key) { + if (option === '$inherit') { + if (key === '*') { + inheritAll = true; + } else { + options[key] = this.$$options[key]; + // `updateOn` is special so we must also inherit the `updateOnDefault` option + if (key === 'updateOn') { + options.updateOnDefault = this.$$options.updateOnDefault; + } + } + } else { + if (key === 'updateOn') { + // If the `updateOn` property contains the `default` event then we have to remove + // it from the event list and set the `updateOnDefault` flag. + options.updateOnDefault = false; + options[key] = trim(option.replace(DEFAULT_REGEXP, function() { + options.updateOnDefault = true; + return ' '; + })); + } + } + }, this); + + if (inheritAll) { + // We have a property of the form: `"*": "$inherit"` + delete options['*']; + defaults(options, this.$$options); + } + + // Finally add in any missing defaults + defaults(options, defaultModelOptions.$$options); + + return new ModelOptions(options); + } +}; + + +defaultModelOptions = new ModelOptions({ + updateOn: '', + updateOnDefault: true, + debounce: 0, + getterSetter: false, + allowInvalid: false, + timezone: null +}); + + +/** + * @ngdoc directive + * @name ngModelOptions + * @restrict A + * @priority 10 + * + * @description + * This directive allows you to modify the behaviour of {@link ngModel} directives within your + * application. You can specify an `ngModelOptions` directive on any element. All {@link ngModel} + * directives will use the options of their nearest `ngModelOptions` ancestor. + * + * The `ngModelOptions` settings are found by evaluating the value of the attribute directive as + * an AngularJS expression. This expression should evaluate to an object, whose properties contain + * the settings. For example: `
    + *
    + * + *
    + *
    + * ``` + * + * the `input` element will have the following settings + * + * ```js + * { allowInvalid: true, updateOn: 'default', debounce: 0 } + * ``` + * + * Notice that the `debounce` setting was not inherited and used the default value instead. + * + * You can specify that all undefined settings are automatically inherited from an ancestor by + * including a property with key of `"*"` and value of `"$inherit"`. + * + * For example given the following fragment of HTML + * + * + * ```html + *
    + *
    + * + *
    + *
    + * ``` + * + * the `input` element will have the following settings + * + * ```js + * { allowInvalid: true, updateOn: 'default', debounce: 200 } + * ``` + * + * Notice that the `debounce` setting now inherits the value from the outer `
    ` element. + * + * If you are creating a reusable component then you should be careful when using `"*": "$inherit"` + * since you may inadvertently inherit a setting in the future that changes the behavior of your component. + * + * + * ## Triggering and debouncing model updates + * + * The `updateOn` and `debounce` properties allow you to specify a custom list of events that will + * trigger a model update and/or a debouncing delay so that the actual update only takes place when + * a timer expires; this timer will be reset after another change takes place. + * + * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might + * be different from the value in the actual model. This means that if you update the model you + * should also invoke {@link ngModel.NgModelController#$rollbackViewValue} on the relevant input field in + * order to make sure it is synchronized with the model and that any debounced action is canceled. + * + * The easiest way to reference the control's {@link ngModel.NgModelController#$rollbackViewValue} + * method is by making sure the input is placed inside a form that has a `name` attribute. This is + * important because `form` controllers are published to the related scope under the name in their + * `name` attribute. + * + * Any pending changes will take place immediately when an enclosing form is submitted via the + * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` + * to have access to the updated model. + * + * ### Overriding immediate updates + * + * The following example shows how to override immediate updates. Changes on the inputs within the + * form will update the model only when the control loses focus (blur event). If `escape` key is + * pressed while the input field is focused, the value is reset to the value in the current model. + * + * + * + *
    + *
    + *
    + *
    + *
    + *
    user.name = 
    + *
    + *
    + * + * angular.module('optionsExample', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.user = { name: 'say', data: '' }; + * + * $scope.cancel = function(e) { + * if (e.keyCode === 27) { + * $scope.userForm.userName.$rollbackViewValue(); + * } + * }; + * }]); + * + * + * var model = element(by.binding('user.name')); + * var input = element(by.model('user.name')); + * var other = element(by.model('user.data')); + * + * it('should allow custom events', function() { + * input.sendKeys(' hello'); + * input.click(); + * expect(model.getText()).toEqual('say'); + * other.click(); + * expect(model.getText()).toEqual('say hello'); + * }); + * + * it('should $rollbackViewValue when model changes', function() { + * input.sendKeys(' hello'); + * expect(input.getAttribute('value')).toEqual('say hello'); + * input.sendKeys(protractor.Key.ESCAPE); + * expect(input.getAttribute('value')).toEqual('say'); + * other.click(); + * expect(model.getText()).toEqual('say'); + * }); + * + *
    + * + * ### Debouncing updates + * + * The next example shows how to debounce model changes. Model will be updated only 1 sec after last change. + * If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty. + * + * + * + *
    + *
    + * Name: + * + *
    + *
    + *
    user.name = 
    + *
    + *
    + * + * angular.module('optionsExample', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.user = { name: 'say' }; + * }]); + * + *
    + * + * ### Default events, extra triggers, and catch-all debounce values + * + * This example shows the relationship between "default" update events and + * additional `updateOn` triggers. + * + * `default` events are those that are bound to the control, and when fired, update the `$viewValue` + * via {@link ngModel.NgModelController#$setViewValue $setViewValue}. Every event that is not listed + * in `updateOn` is considered a "default" event, since different control types have different + * default events. + * + * The control in this example updates by "default", "click", and "blur", with different `debounce` + * values. You can see that "click" doesn't have an individual `debounce` value - + * therefore it uses the `*` debounce value. + * + * There is also a button that calls {@link ngModel.NgModelController#$setViewValue $setViewValue} + * directly with a "custom" event. Since "custom" is not defined in the `updateOn` list, + * it is considered a "default" event and will update the + * control if "default" is defined in `updateOn`, and will receive the "default" debounce value. + * Note that this is just to illustrate how custom controls would possibly call `$setViewValue`. + * + * You can change the `updateOn` and `debounce` configuration to test different scenarios. This + * is done with {@link ngModel.NgModelController#$overrideModelOptions $overrideModelOptions}. + * + + + + + + angular.module('optionsExample', []) + .component('modelUpdateDemo', { + templateUrl: 'template.html', + controller: function() { + this.name = 'Chinua'; + + this.options = { + updateOn: 'default blur click', + debounce: { + default: 2000, + blur: 0, + '*': 1000 + } + }; + + this.updateEvents = function() { + var eventList = this.options.updateOn.split(' '); + eventList.push('*'); + var events = {}; + + for (var i = 0; i < eventList.length; i++) { + events[eventList[i]] = this.options.debounce[eventList[i]]; + } + + this.events = events; + }; + + this.updateOptions = function() { + var options = angular.extend(this.options, { + updateOn: Object.keys(this.events).join(' ').replace('*', ''), + debounce: this.events + }); + + this.form.input.$overrideModelOptions(options); + }; + + // Initialize the event form + this.updateEvents(); + } + }); + + +
    + Input: +
    + Model: {{$ctrl.name}} +
    + + +
    +
    + updateOn
    + + + + + + + + + + + +
    OptionDebounce value
    {{key}}
    + +
    + +
    +
    +
    + * + * + * ## Model updates and validation + * + * The default behaviour in `ngModel` is that the model value is set to `undefined` when the + * validation determines that the value is invalid. By setting the `allowInvalid` property to true, + * the model will still be updated even if the value is invalid. + * + * + * ## Connecting to the scope + * + * By setting the `getterSetter` property to true you are telling ngModel that the `ngModel` expression + * on the scope refers to a "getter/setter" function rather than the value itself. + * + * The following example shows how to bind to getter/setters: + * + * + * + *
    + *
    + * + *
    + *
    user.name = 
    + *
    + *
    + * + * angular.module('getterSetterExample', []) + * .controller('ExampleController', ['$scope', function($scope) { + * var _name = 'Brian'; + * $scope.user = { + * name: function(newName) { + * return angular.isDefined(newName) ? (_name = newName) : _name; + * } + * }; + * }]); + * + *
    + * + * + * ## Programmatically changing options + * + * The `ngModelOptions` expression is only evaluated once when the directive is linked; it is not + * watched for changes. However, it is possible to override the options on a single + * {@link ngModel.NgModelController} instance with + * {@link ngModel.NgModelController#$overrideModelOptions `NgModelController#$overrideModelOptions()`}. + * See also the example for + * {@link ngModelOptions#default-events-extra-triggers-and-catch-all-debounce-values + * Default events, extra triggers, and catch-all debounce values}. + * + * + * ## Specifying timezones + * + * You can specify the timezone that date/time input directives expect by providing its name in the + * `timezone` property. + * + * + * ## Formatting the value of `time` and `datetime-local` + * + * With the options `timeSecondsFormat` and `timeStripZeroSeconds` it is possible to adjust the value + * that is displayed in the control. Note that browsers may apply their own formatting + * in the user interface. + * + + + + + + angular.module('timeExample', []) + .component('timeExample', { + templateUrl: 'timeExample.html', + controller: function() { + this.time = new Date(1970, 0, 1, 14, 57, 0); + + this.options = { + timeSecondsFormat: 'ss', + timeStripZeroSeconds: true + }; + + this.optionChange = function() { + this.timeForm.timeFormatted.$overrideModelOptions(this.options); + this.time = new Date(this.time); + }; + } + }); + + +
    + Default: +
    + With options: + +
    + + Options:
    + timeSecondsFormat: + +
    + timeStripZeroSeconds: + +
    +
    + *
    + * + * @param {Object} ngModelOptions options to apply to {@link ngModel} directives on this element and + * and its descendents. + * + * **General options**: + * + * - `updateOn`: string specifying which event should the input be bound to. You can set several + * events using an space delimited list. There is a special event called `default` that + * matches the default events belonging to the control. These are the events that are bound to + * the control, and when fired, update the `$viewValue` via `$setViewValue`. + * + * `ngModelOptions` considers every event that is not listed in `updateOn` a "default" event, + * since different control types use different default events. + * + * See also the section {@link ngModelOptions#triggering-and-debouncing-model-updates + * Triggering and debouncing model updates}. + * + * - `debounce`: integer value which contains the debounce model update value in milliseconds. A + * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a + * custom value for each event. For example: + * ``` + * ng-model-options="{ + * updateOn: 'default blur', + * debounce: { 'default': 500, 'blur': 0 } + * }" + * ``` + * You can use the `*` key to specify a debounce value that applies to all events that are not + * specifically listed. In the following example, `mouseup` would have a debounce delay of 1000: + * ``` + * ng-model-options="{ + * updateOn: 'default blur mouseup', + * debounce: { 'default': 500, 'blur': 0, '*': 1000 } + * }" + * ``` + * - `allowInvalid`: boolean value which indicates that the model can be set with values that did + * not validate correctly instead of the default behavior of setting the model to undefined. + * - `getterSetter`: boolean value which determines whether or not to treat functions bound to + * `ngModel` as getters/setters. + * + * + * **Input-type specific options**: + * + * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for + * ``, ``, ... . It understands UTC/GMT and the + * continental US time zone abbreviations, but for general use, use a time zone offset, for + * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian) + * If not specified, the timezone of the browser will be used. + * Note that changing the timezone will have no effect on the current date, and is only applied after + * the next input / model change. + * + * - `timeSecondsFormat`: Defines if the `time` and `datetime-local` types should show seconds and + * milliseconds. The option follows the format string of {@link date date filter}. + * By default, the options is `undefined` which is equal to `'ss.sss'` (seconds and milliseconds). + * The other options are `'ss'` (strips milliseconds), and `''` (empty string), which strips both + * seconds and milliseconds. + * Note that browsers that support `time` and `datetime-local` require the hour and minutes + * part of the time string, and may show the value differently in the user interface. + * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. + * + * - `timeStripZeroSeconds`: Defines if the `time` and `datetime-local` types should strip the + * seconds and milliseconds from the formatted value if they are zero. This option is applied + * after `timeSecondsFormat`. + * This option can be used to make the formatting consistent over different browsers, as some + * browsers with support for `time` will natively hide the milliseconds and + * seconds if they are zero, but others won't, and browsers that don't implement these input + * types will always show the full string. + * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. + * + */ +var ngModelOptionsDirective = function() { + NgModelOptionsController.$inject = ['$attrs', '$scope']; + function NgModelOptionsController($attrs, $scope) { + this.$$attrs = $attrs; + this.$$scope = $scope; + } + NgModelOptionsController.prototype = { + $onInit: function() { + var parentOptions = this.parentCtrl ? this.parentCtrl.$options : defaultModelOptions; + var modelOptionsDefinition = this.$$scope.$eval(this.$$attrs.ngModelOptions); + + this.$options = parentOptions.createChild(modelOptionsDefinition); + } + }; + + return { + restrict: 'A', + // ngModelOptions needs to run before ngModel and input directives + priority: 10, + require: {parentCtrl: '?^^ngModelOptions'}, + bindToController: true, + controller: NgModelOptionsController + }; +}; + + +// shallow copy over values from `src` that are not already specified on `dst` +function defaults(dst, src) { + forEach(src, function(value, key) { + if (!isDefined(dst[key])) { + dst[key] = value; + } + }); +} + +/** + * @ngdoc directive + * @name ngNonBindable + * @restrict AC + * @priority 1000 + * @element ANY + * + * @description + * The `ngNonBindable` directive tells AngularJS not to compile or bind the contents of the current + * DOM element, including directives on the element itself that have a lower priority than + * `ngNonBindable`. This is useful if the element contains what appears to be AngularJS directives + * and bindings but which should be ignored by AngularJS. This could be the case if you have a site + * that displays snippets of code, for instance. + * + * @example + * In this example there are two locations where a simple interpolation binding (`{{}}`) is present, + * but the one wrapped in `ngNonBindable` is left alone. + * + + +
    Normal: {{1 + 2}}
    +
    Ignored: {{1 + 2}}
    +
    + + it('should check ng-non-bindable', function() { + expect(element(by.binding('1 + 2')).getText()).toContain('3'); + expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/); + }); + +
    + */ +var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); + +/* exported ngOptionsDirective */ + +/* global jqLiteRemove */ + +var ngOptionsMinErr = minErr('ngOptions'); + +/** + * @ngdoc directive + * @name ngOptions + * @restrict A + * + * @description + * + * The `ngOptions` attribute can be used to dynamically generate a list of `` + * DOM element. + * * `disable`: The result of this expression will be used to disable the rendered `
    wrappers assigned to root
    + *
    + * wrapper.ngRepeatToggle.isOpen(): {{wrapper.ngRepeatToggle.isOpen() | json}} + *
    + * + *
      + *
    • + * ngRepeat + *
      outerToggle.isOpen(): {{$ctrl.outerToggle.isOpen() | json}}
      + * ngRepeat Toggle {{$index + 1}} + *
    • + *
    + * + *
    ngIfToggle.isOpen(): {{ngIfToggle.isOpen()}} // This is always undefined because it's + * assigned to the child scope created by ngIf. + *
    + *
    + ngIf + * ngIf Toggle + *
    ngIfToggle.isOpen(): {{ngIfToggle.isOpen() | json}}
    + *
    outerToggle.isOpen(): {{$ctrl.outerToggle.isOpen() | json}}
    + *
    + * + * + * ul { + * list-style: none; + * padding-left: 0; + * } + * + * li[ng-repeat] { + * background: lightgreen; + * padding: 8px; + * margin: 8px; + * } + * + * [ng-if] { + * background: lightgrey; + * padding: 8px; + * } + * + * my-root { + * background: lightgoldenrodyellow; + * padding: 8px; + * display: block; + * } + * + * my-wrapper { + * background: lightsalmon; + * padding: 8px; + * display: block; + * } + * + * my-toggle { + * background: lightblue; + * padding: 8px; + * display: block; + * } + * + * + * var OuterToggle = function() { + * this.toggle = function() { + * element(by.buttonText('Outer Toggle')).click(); + * }; + * this.isOpen = function() { + * return element.all(by.binding('outerToggle.isOpen()')).first().getText(); + * }; + * }; + * var NgRepeatToggle = function(i) { + * var parent = element.all(by.repeater('(index, value) in [1,2,3]')).get(i - 1); + * this.toggle = function() { + * element(by.buttonText('ngRepeat Toggle ' + i)).click(); + * }; + * this.isOpen = function() { + * return parent.element(by.binding('ngRepeatToggle.isOpen() | json')).getText(); + * }; + * this.isOuterOpen = function() { + * return parent.element(by.binding('outerToggle.isOpen() | json')).getText(); + * }; + * }; + * var NgRepeatToggles = function() { + * var toggles = [1,2,3].map(function(i) { return new NgRepeatToggle(i); }); + * this.forEach = function(fn) { + * toggles.forEach(fn); + * }; + * this.isOuterOpen = function(i) { + * return toggles[i - 1].isOuterOpen(); + * }; + * }; + * var NgIfToggle = function() { + * var parent = element(by.css('[ng-if]')); + * this.toggle = function() { + * element(by.buttonText('ngIf Toggle')).click(); + * }; + * this.isOpen = function() { + * return by.binding('ngIfToggle.isOpen() | json').getText(); + * }; + * this.isOuterOpen = function() { + * return parent.element(by.binding('outerToggle.isOpen() | json')).getText(); + * }; + * }; + * + * it('should toggle the outer toggle', function() { + * var outerToggle = new OuterToggle(); + * expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): false'); + * outerToggle.toggle(); + * expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): true'); + * }); + * + * it('should toggle all outer toggles', function() { + * var outerToggle = new OuterToggle(); + * var repeatToggles = new NgRepeatToggles(); + * var ifToggle = new NgIfToggle(); + * expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): false'); + * expect(repeatToggles.isOuterOpen(1)).toEqual('outerToggle.isOpen(): false'); + * expect(repeatToggles.isOuterOpen(2)).toEqual('outerToggle.isOpen(): false'); + * expect(repeatToggles.isOuterOpen(3)).toEqual('outerToggle.isOpen(): false'); + * expect(ifToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): false'); + * outerToggle.toggle(); + * expect(outerToggle.isOpen()).toEqual('outerToggle.isOpen(): true'); + * expect(repeatToggles.isOuterOpen(1)).toEqual('outerToggle.isOpen(): true'); + * expect(repeatToggles.isOuterOpen(2)).toEqual('outerToggle.isOpen(): true'); + * expect(repeatToggles.isOuterOpen(3)).toEqual('outerToggle.isOpen(): true'); + * expect(ifToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): true'); + * }); + * + * it('should toggle each repeat iteration separately', function() { + * var repeatToggles = new NgRepeatToggles(); + * + * repeatToggles.forEach(function(repeatToggle) { + * expect(repeatToggle.isOpen()).toEqual('ngRepeatToggle.isOpen(): false'); + * expect(repeatToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): false'); + * repeatToggle.toggle(); + * expect(repeatToggle.isOpen()).toEqual('ngRepeatToggle.isOpen(): true'); + * expect(repeatToggle.isOuterOpen()).toEqual('outerToggle.isOpen(): false'); + * }); + * }); + * + * + * + */ + +var ngRefMinErr = minErr('ngRef'); + +var ngRefDirective = ['$parse', function($parse) { + return { + priority: -1, // Needed for compatibility with element transclusion on the same element + restrict: 'A', + compile: function(tElement, tAttrs) { + // Get the expected controller name, converts into "someThing" + var controllerName = directiveNormalize(nodeName_(tElement)); + + // Get the expression for value binding + var getter = $parse(tAttrs.ngRef); + var setter = getter.assign || function() { + throw ngRefMinErr('nonassign', 'Expression in ngRef="{0}" is non-assignable!', tAttrs.ngRef); + }; + + return function(scope, element, attrs) { + var refValue; + + if (attrs.hasOwnProperty('ngRefRead')) { + if (attrs.ngRefRead === '$element') { + refValue = element; + } else { + refValue = element.data('$' + attrs.ngRefRead + 'Controller'); + + if (!refValue) { + throw ngRefMinErr( + 'noctrl', + 'The controller for ngRefRead="{0}" could not be found on ngRef="{1}"', + attrs.ngRefRead, + tAttrs.ngRef + ); + } + } + } else { + refValue = element.data('$' + controllerName + 'Controller'); + } + + refValue = refValue || element; + + setter(scope, refValue); + + // when the element is removed, remove it (nullify it) + element.on('$destroy', function() { + // only remove it if value has not changed, + // because animations (and other procedures) may duplicate elements + if (getter(scope) === refValue) { + setter(scope, null); + } + }); + }; + } + }; +}]; + +/* exported ngRepeatDirective */ + +/** + * @ngdoc directive + * @name ngRepeat + * @multiElement + * @restrict A + * + * @description + * The `ngRepeat` directive instantiates a template once per item from a collection. Each template + * instance gets its own scope, where the given loop variable is set to the current collection item, + * and `$index` is set to the item index or key. + * + * Special properties are exposed on the local scope of each template instance, including: + * + * | Variable | Type | Details | + * |-----------|-----------------|-----------------------------------------------------------------------------| + * | `$index` | {@type number} | iterator offset of the repeated element (0..length-1) | + * | `$first` | {@type boolean} | true if the repeated element is first in the iterator. | + * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. | + * | `$last` | {@type boolean} | true if the repeated element is last in the iterator. | + * | `$even` | {@type boolean} | true if the iterator position `$index` is even (otherwise false). | + * | `$odd` | {@type boolean} | true if the iterator position `$index` is odd (otherwise false). | + * + *
    + * Creating aliases for these properties is possible with {@link ng.directive:ngInit `ngInit`}. + * This may be useful when, for instance, nesting ngRepeats. + *
    + * + * + * ## Iterating over object properties + * + * It is possible to get `ngRepeat` to iterate over the properties of an object using the following + * syntax: + * + * ```js + *
    ...
    + * ``` + * + * However, there are a few limitations compared to array iteration: + * + * - The JavaScript specification does not define the order of keys + * returned for an object, so AngularJS relies on the order returned by the browser + * when running `for key in myObj`. Browsers generally follow the strategy of providing + * keys in the order in which they were defined, although there are exceptions when keys are deleted + * and reinstated. See the + * [MDN page on `delete` for more info](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete#Cross-browser_notes). + * + * - `ngRepeat` will silently *ignore* object keys starting with `$`, because + * it's a prefix used by AngularJS for public (`$`) and private (`$$`) properties. + * + * - The built-in filters {@link ng.orderBy orderBy} and {@link ng.filter filter} do not work with + * objects, and will throw an error if used with one. + * + * If you are hitting any of these limitations, the recommended workaround is to convert your object into an array + * that is sorted into the order that you prefer before providing it to `ngRepeat`. You could + * do this with a filter such as [toArrayFilter](http://ngmodules.org/modules/angular-toArrayFilter) + * or implement a `$watch` on the object yourself. + * + * + * ## Tracking and Duplicates + * + * `ngRepeat` uses {@link $rootScope.Scope#$watchCollection $watchCollection} to detect changes in + * the collection. When a change happens, `ngRepeat` then makes the corresponding changes to the DOM: + * + * * When an item is added, a new instance of the template is added to the DOM. + * * When an item is removed, its template instance is removed from the DOM. + * * When items are reordered, their respective templates are reordered in the DOM. + * + * To minimize creation of DOM elements, `ngRepeat` uses a function + * to "keep track" of all items in the collection and their corresponding DOM elements. + * For example, if an item is added to the collection, `ngRepeat` will know that all other items + * already have DOM elements, and will not re-render them. + * + * All different types of tracking functions, their syntax, and their support for duplicate + * items in collections can be found in the + * {@link ngRepeat#ngRepeat-arguments ngRepeat expression description}. + * + *
    + * **Best Practice:** If you are working with objects that have a unique identifier property, you + * should track by this identifier instead of the object instance, + * e.g. `item in items track by item.id`. + * Should you reload your data later, `ngRepeat` will not have to rebuild the DOM elements for items + * it has already rendered, even if the JavaScript objects in the collection have been substituted + * for new ones. For large collections, this significantly improves rendering performance. + *
    + * + * ### Effects of DOM Element re-use + * + * When DOM elements are re-used, ngRepeat updates the scope for the element, which will + * automatically update any active bindings on the template. However, other + * functionality will not be updated, because the element is not re-created: + * + * - Directives are not re-compiled + * - {@link guide/expression#one-time-binding one-time expressions} on the repeated template are not + * updated if they have stabilized. + * + * The above affects all kinds of element re-use due to tracking, but may be especially visible + * when tracking by `$index` due to the way ngRepeat re-uses elements. + * + * The following example shows the effects of different actions with tracking: + + + + angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) { + var friends = [ + {name:'John', age:25}, + {name:'Mary', age:40}, + {name:'Peter', age:85} + ]; + + $scope.removeFirst = function() { + $scope.friends.shift(); + }; + + $scope.updateAge = function() { + $scope.friends.forEach(function(el) { + el.age = el.age + 5; + }); + }; + + $scope.copy = function() { + $scope.friends = angular.copy($scope.friends); + }; + + $scope.reset = function() { + $scope.friends = angular.copy(friends); + }; + + $scope.reset(); + }); + + +
    +
      +
    1. When you click "Update Age", only the first list updates the age, because all others have + a one-time binding on the age property. If you then click "Copy", the current friend list + is copied, and now the second list updates the age, because the identity of the collection items + has changed and the list must be re-rendered. The 3rd and 4th list stay the same, because all the + items are already known according to their tracking functions. +
    2. +
    3. When you click "Remove First", the 4th list has the wrong age on both remaining items. This is + due to tracking by $index: when the first collection item is removed, ngRepeat reuses the first + DOM element for the new first collection item, and so on. Since the age property is one-time + bound, the value remains from the collection item which was previously at this index. +
    4. +
    + + + + +
    +
    + track by $id(friend) (default): +
      +
    • + {{friend.name}} is {{friend.age}} years old. +
    • +
    + track by $id(friend) (default), with age one-time binding: +
      +
    • + {{friend.name}} is {{::friend.age}} years old. +
    • +
    + track by friend.name, with age one-time binding: +
      +
    • + {{friend.name}} is {{::friend.age}} years old. +
    • +
    + track by $index, with age one-time binding: +
      +
    • + {{friend.name}} is {{::friend.age}} years old. +
    • +
    +
    +
    + + .example-animate-container { + background:white; + border:1px solid black; + list-style:none; + margin:0; + padding:0 10px; + } + + .animate-repeat { + line-height:30px; + list-style:none; + box-sizing:border-box; + } + + .animate-repeat.ng-move, + .animate-repeat.ng-enter, + .animate-repeat.ng-leave { + transition:all linear 0.5s; + } + + .animate-repeat.ng-leave.ng-leave-active, + .animate-repeat.ng-move, + .animate-repeat.ng-enter { + opacity:0; + max-height:0; + } + + .animate-repeat.ng-leave, + .animate-repeat.ng-move.ng-move-active, + .animate-repeat.ng-enter.ng-enter-active { + opacity:1; + max-height:30px; + } + +
    + + * + * ## Special repeat start and end points + * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending + * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively. + * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on) + * up to and including the ending HTML tag where **ng-repeat-end** is placed. + * + * The example below makes use of this feature: + * ```html + *
    + * Header {{ item }} + *
    + *
    + * Body {{ item }} + *
    + *
    + * Footer {{ item }} + *
    + * ``` + * + * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to: + * ```html + *
    + * Header A + *
    + *
    + * Body A + *
    + *
    + * Footer A + *
    + *
    + * Header B + *
    + *
    + * Body B + *
    + *
    + * Footer B + *
    + * ``` + * + * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such + * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**). + * + * @animations + * | Animation | Occurs | + * |----------------------------------|-------------------------------------| + * | {@link ng.$animate#enter enter} | when a new item is added to the list or when an item is revealed after a filter | + * | {@link ng.$animate#leave leave} | when an item is removed from the list or when an item is filtered out | + * | {@link ng.$animate#move move } | when an adjacent item is filtered out causing a reorder or when the item contents are reordered | + * + * See the example below for defining CSS animations with ngRepeat. + * + * @element ANY + * @scope + * @priority 1000 + * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These + * formats are currently supported: + * + * * `variable in expression` – where variable is the user defined loop variable and `expression` + * is a scope expression giving the collection to enumerate. + * + * For example: `album in artist.albums`. + * + * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers, + * and `expression` is the scope expression giving the collection to enumerate. + * + * For example: `(name, age) in {'adam':10, 'amalie':12}`. + * + * * `variable in expression track by tracking_expression` – You can also provide an optional tracking expression + * which can be used to associate the objects in the collection with the DOM elements. If no tracking expression + * is specified, ng-repeat associates elements by identity. It is an error to have + * more than one tracking expression value resolve to the same key. (This would mean that two distinct objects are + * mapped to the same DOM element, which is not possible.) + * + * *Default tracking: $id()*: `item in items` is equivalent to `item in items track by $id(item)`. + * This implies that the DOM elements will be associated by item identity in the collection. + * + * The built-in `$id()` function can be used to assign a unique + * `$$hashKey` property to each item in the collection. This property is then used as a key to associated DOM elements + * with the corresponding item in the collection by identity. Moving the same object would move + * the DOM element in the same way in the DOM. + * Note that the default id function does not support duplicate primitive values (`number`, `string`), + * but supports duplictae non-primitive values (`object`) that are *equal* in shape. + * + * *Custom Expression*: It is possible to use any AngularJS expression to compute the tracking + * id, for example with a function, or using a property on the collection items. + * `item in items track by item.id` is a typical pattern when the items have a unique identifier, + * e.g. database id. In this case the object identity does not matter. Two objects are considered + * equivalent as long as their `id` property is same. + * Tracking by unique identifier is the most performant way and should be used whenever possible. + * + * *$index*: This special property tracks the collection items by their index, and + * re-uses the DOM elements that match that index, e.g. `item in items track by $index`. This can + * be used for a performance improvement if no unique identfier is available and the identity of + * the collection items cannot be easily computed. It also allows duplicates. + * + *
    + * Note: Re-using DOM elements can have unforeseen effects. Read the + * {@link ngRepeat#tracking-and-duplicates section on tracking and duplicates} for + * more info. + *
    + * + *
    + * Note: the `track by` expression must come last - after any filters, and the alias expression: + * `item in items | filter:searchText as results track by item.id` + *
    + * + * * `variable in expression as alias_expression` – You can also provide an optional alias expression which will then store the + * intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message + * when a filter is active on the repeater, but the filtered result set is empty. + * + * For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after + * the items have been processed through the filter. + * + * Please note that `as [variable name] is not an operator but rather a part of ngRepeat + * micro-syntax so it can be used only after all filters (and not as operator, inside an expression). + * + * For example: `item in items | filter : x | orderBy : order | limitTo : limit as results track by item.id` . + * + * @example + * This example uses `ngRepeat` to display a list of people. A filter is used to restrict the displayed + * results by name or by age. New (entering) and removed (leaving) items are animated. + + +
    + I have {{friends.length}} friends. They are: + +
      +
    • + [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. +
    • +
    • + No results found... +
    • +
    +
    +
    + + angular.module('ngRepeat', ['ngAnimate']).controller('repeatController', function($scope) { + $scope.friends = [ + {name:'John', age:25, gender:'boy'}, + {name:'Jessie', age:30, gender:'girl'}, + {name:'Johanna', age:28, gender:'girl'}, + {name:'Joy', age:15, gender:'girl'}, + {name:'Mary', age:28, gender:'girl'}, + {name:'Peter', age:95, gender:'boy'}, + {name:'Sebastian', age:50, gender:'boy'}, + {name:'Erika', age:27, gender:'girl'}, + {name:'Patrick', age:40, gender:'boy'}, + {name:'Samantha', age:60, gender:'girl'} + ]; + }); + + + .example-animate-container { + background:white; + border:1px solid black; + list-style:none; + margin:0; + padding:0 10px; + } + + .animate-repeat { + line-height:30px; + list-style:none; + box-sizing:border-box; + } + + .animate-repeat.ng-move, + .animate-repeat.ng-enter, + .animate-repeat.ng-leave { + transition:all linear 0.5s; + } + + .animate-repeat.ng-leave.ng-leave-active, + .animate-repeat.ng-move, + .animate-repeat.ng-enter { + opacity:0; + max-height:0; + } + + .animate-repeat.ng-leave, + .animate-repeat.ng-move.ng-move-active, + .animate-repeat.ng-enter.ng-enter-active { + opacity:1; + max-height:30px; + } + + + var friends = element.all(by.repeater('friend in friends')); + + it('should render initial data set', function() { + expect(friends.count()).toBe(10); + expect(friends.get(0).getText()).toEqual('[1] John who is 25 years old.'); + expect(friends.get(1).getText()).toEqual('[2] Jessie who is 30 years old.'); + expect(friends.last().getText()).toEqual('[10] Samantha who is 60 years old.'); + expect(element(by.binding('friends.length')).getText()) + .toMatch("I have 10 friends. They are:"); + }); + + it('should update repeater when filter predicate changes', function() { + expect(friends.count()).toBe(10); + + element(by.model('q')).sendKeys('ma'); + + expect(friends.count()).toBe(2); + expect(friends.get(0).getText()).toEqual('[1] Mary who is 28 years old.'); + expect(friends.last().getText()).toEqual('[2] Samantha who is 60 years old.'); + }); + +
    + */ +var ngRepeatDirective = ['$parse', '$animate', '$compile', function($parse, $animate, $compile) { + var NG_REMOVED = '$$NG_REMOVED'; + var ngRepeatMinErr = minErr('ngRepeat'); + + var updateScope = function(scope, index, valueIdentifier, value, keyIdentifier, key, arrayLength) { + // TODO(perf): generate setters to shave off ~40ms or 1-1.5% + scope[valueIdentifier] = value; + if (keyIdentifier) scope[keyIdentifier] = key; + scope.$index = index; + scope.$first = (index === 0); + scope.$last = (index === (arrayLength - 1)); + scope.$middle = !(scope.$first || scope.$last); + // eslint-disable-next-line no-bitwise + scope.$odd = !(scope.$even = (index & 1) === 0); + }; + + var getBlockStart = function(block) { + return block.clone[0]; + }; + + var getBlockEnd = function(block) { + return block.clone[block.clone.length - 1]; + }; + + var trackByIdArrayFn = function($scope, key, value) { + return hashKey(value); + }; + + var trackByIdObjFn = function($scope, key) { + return key; + }; + + return { + restrict: 'A', + multiElement: true, + transclude: 'element', + priority: 1000, + terminal: true, + $$tlb: true, + compile: function ngRepeatCompile($element, $attr) { + var expression = $attr.ngRepeat; + var ngRepeatEndComment = $compile.$$createComment('end ngRepeat', expression); + + var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/); + + if (!match) { + throw ngRepeatMinErr('iexp', 'Expected expression in form of \'_item_ in _collection_[ track by _id_]\' but got \'{0}\'.', + expression); + } + + var lhs = match[1]; + var rhs = match[2]; + var aliasAs = match[3]; + var trackByExp = match[4]; + + match = lhs.match(/^(?:(\s*[$\w]+)|\(\s*([$\w]+)\s*,\s*([$\w]+)\s*\))$/); + + if (!match) { + throw ngRepeatMinErr('iidexp', '\'_item_\' in \'_item_ in _collection_\' should be an identifier or \'(_key_, _value_)\' expression, but got \'{0}\'.', + lhs); + } + var valueIdentifier = match[3] || match[1]; + var keyIdentifier = match[2]; + + if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) || + /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) { + throw ngRepeatMinErr('badident', 'alias \'{0}\' is invalid --- must be a valid JS identifier which is not a reserved name.', + aliasAs); + } + + var trackByIdExpFn; + + if (trackByExp) { + var hashFnLocals = {$id: hashKey}; + var trackByExpGetter = $parse(trackByExp); + + trackByIdExpFn = function($scope, key, value, index) { + // assign key, value, and $index to the locals so that they can be used in hash functions + if (keyIdentifier) hashFnLocals[keyIdentifier] = key; + hashFnLocals[valueIdentifier] = value; + hashFnLocals.$index = index; + return trackByExpGetter($scope, hashFnLocals); + }; + } + + return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) { + + // Store a list of elements from previous run. This is a hash where key is the item from the + // iterator, and the value is objects with following properties. + // - scope: bound scope + // - clone: previous element. + // - index: position + // + // We are using no-proto object so that we don't need to guard against inherited props via + // hasOwnProperty. + var lastBlockMap = createMap(); + + //watch props + $scope.$watchCollection(rhs, function ngRepeatAction(collection) { + var index, length, + previousNode = $element[0], // node that cloned nodes should be inserted after + // initialized to the comment node anchor + nextNode, + // Same as lastBlockMap but it has the current state. It will become the + // lastBlockMap on the next iteration. + nextBlockMap = createMap(), + collectionLength, + key, value, // key/value of iteration + trackById, + trackByIdFn, + collectionKeys, + block, // last object information {scope, element, id} + nextBlockOrder, + elementsToRemove; + + if (aliasAs) { + $scope[aliasAs] = collection; + } + + if (isArrayLike(collection)) { + collectionKeys = collection; + trackByIdFn = trackByIdExpFn || trackByIdArrayFn; + } else { + trackByIdFn = trackByIdExpFn || trackByIdObjFn; + // if object, extract keys, in enumeration order, unsorted + collectionKeys = []; + for (var itemKey in collection) { + if (hasOwnProperty.call(collection, itemKey) && itemKey.charAt(0) !== '$') { + collectionKeys.push(itemKey); + } + } + } + + collectionLength = collectionKeys.length; + nextBlockOrder = new Array(collectionLength); + + // locate existing items + for (index = 0; index < collectionLength; index++) { + key = (collection === collectionKeys) ? index : collectionKeys[index]; + value = collection[key]; + trackById = trackByIdFn($scope, key, value, index); + if (lastBlockMap[trackById]) { + // found previously seen block + block = lastBlockMap[trackById]; + delete lastBlockMap[trackById]; + nextBlockMap[trackById] = block; + nextBlockOrder[index] = block; + } else if (nextBlockMap[trackById]) { + // if collision detected. restore lastBlockMap and throw an error + forEach(nextBlockOrder, function(block) { + if (block && block.scope) lastBlockMap[block.id] = block; + }); + throw ngRepeatMinErr('dupes', + 'Duplicates in a repeater are not allowed. Use \'track by\' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}', + expression, trackById, value); + } else { + // new never before seen block + nextBlockOrder[index] = {id: trackById, scope: undefined, clone: undefined}; + nextBlockMap[trackById] = true; + } + } + + // Clear the value property from the hashFnLocals object to prevent a reference to the last value + // being leaked into the ngRepeatCompile function scope + if (hashFnLocals) { + hashFnLocals[valueIdentifier] = undefined; + } + + // remove leftover items + for (var blockKey in lastBlockMap) { + block = lastBlockMap[blockKey]; + elementsToRemove = getBlockNodes(block.clone); + $animate.leave(elementsToRemove); + if (elementsToRemove[0].parentNode) { + // if the element was not removed yet because of pending animation, mark it as deleted + // so that we can ignore it later + for (index = 0, length = elementsToRemove.length; index < length; index++) { + elementsToRemove[index][NG_REMOVED] = true; + } + } + block.scope.$destroy(); + } + + // we are not using forEach for perf reasons (trying to avoid #call) + for (index = 0; index < collectionLength; index++) { + key = (collection === collectionKeys) ? index : collectionKeys[index]; + value = collection[key]; + block = nextBlockOrder[index]; + + if (block.scope) { + // if we have already seen this object, then we need to reuse the + // associated scope/element + + nextNode = previousNode; + + // skip nodes that are already pending removal via leave animation + do { + nextNode = nextNode.nextSibling; + } while (nextNode && nextNode[NG_REMOVED]); + + if (getBlockStart(block) !== nextNode) { + // existing item which got moved + $animate.move(getBlockNodes(block.clone), null, previousNode); + } + previousNode = getBlockEnd(block); + updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); + } else { + // new item which we don't know about + $transclude(function ngRepeatTransclude(clone, scope) { + block.scope = scope; + // http://jsperf.com/clone-vs-createcomment + var endNode = ngRepeatEndComment.cloneNode(false); + clone[clone.length++] = endNode; + + $animate.enter(clone, null, previousNode); + previousNode = endNode; + // Note: We only need the first/last node of the cloned nodes. + // However, we need to keep the reference to the jqlite wrapper as it might be changed later + // by a directive with templateUrl when its template arrives. + block.clone = clone; + nextBlockMap[block.id] = block; + updateScope(block.scope, index, valueIdentifier, value, keyIdentifier, key, collectionLength); + }); + } + } + lastBlockMap = nextBlockMap; + }); + }; + } + }; +}]; + +var NG_HIDE_CLASS = 'ng-hide'; +var NG_HIDE_IN_PROGRESS_CLASS = 'ng-hide-animate'; +/** + * @ngdoc directive + * @name ngShow + * @multiElement + * + * @description + * The `ngShow` directive shows or hides the given HTML element based on the expression provided to + * the `ngShow` attribute. + * + * The element is shown or hidden by removing or adding the `.ng-hide` CSS class onto the element. + * The `.ng-hide` CSS class is predefined in AngularJS and sets the display style to none (using an + * `!important` flag). For CSP mode please add `angular-csp.css` to your HTML file (see + * {@link ng.directive:ngCsp ngCsp}). + * + * ```html + * + *
    + * + * + *
    + * ``` + * + * When the `ngShow` expression evaluates to a falsy value then the `.ng-hide` CSS class is added + * to the class attribute on the element causing it to become hidden. When truthy, the `.ng-hide` + * CSS class is removed from the element causing the element not to appear hidden. + * + * ## Why is `!important` used? + * + * You may be wondering why `!important` is used for the `.ng-hide` CSS class. This is because the + * `.ng-hide` selector can be easily overridden by heavier selectors. For example, something as + * simple as changing the display style on a HTML list item would make hidden elements appear + * visible. This also becomes a bigger issue when dealing with CSS frameworks. + * + * By using `!important`, the show and hide behavior will work as expected despite any clash between + * CSS selector specificity (when `!important` isn't used with any conflicting styles). If a + * developer chooses to override the styling to change how to hide an element then it is just a + * matter of using `!important` in their own CSS code. + * + * ### Overriding `.ng-hide` + * + * By default, the `.ng-hide` class will style the element with `display: none !important`. If you + * wish to change the hide behavior with `ngShow`/`ngHide`, you can simply overwrite the styles for + * the `.ng-hide` CSS class. Note that the selector that needs to be used is actually + * `.ng-hide:not(.ng-hide-animate)` to cope with extra animation classes that can be added. + * + * ```css + * .ng-hide:not(.ng-hide-animate) { + * /* These are just alternative ways of hiding an element */ + * display: block!important; + * position: absolute; + * top: -9999px; + * left: -9999px; + * } + * ``` + * + * By default you don't need to override anything in CSS and the animations will work around the + * display style. + * + * @animations + * | Animation | Occurs | + * |-----------------------------------------------------|---------------------------------------------------------------------------------------------------------------| + * | {@link $animate#addClass addClass} `.ng-hide` | After the `ngShow` expression evaluates to a non truthy value and just before the contents are set to hidden. | + * | {@link $animate#removeClass removeClass} `.ng-hide` | After the `ngShow` expression evaluates to a truthy value and just before contents are set to visible. | + * + * Animations in `ngShow`/`ngHide` work with the show and hide events that are triggered when the + * directive expression is true and false. This system works like the animation system present with + * `ngClass` except that you must also include the `!important` flag to override the display + * property so that the elements are not actually hidden during the animation. + * + * ```css + * /* A working example can be found at the bottom of this page. */ + * .my-element.ng-hide-add, .my-element.ng-hide-remove { + * transition: all 0.5s linear; + * } + * + * .my-element.ng-hide-add { ... } + * .my-element.ng-hide-add.ng-hide-add-active { ... } + * .my-element.ng-hide-remove { ... } + * .my-element.ng-hide-remove.ng-hide-remove-active { ... } + * ``` + * + * Keep in mind that, as of AngularJS version 1.3, there is no need to change the display property + * to block during animation states - ngAnimate will automatically handle the style toggling for you. + * + * @element ANY + * @param {expression} ngShow If the {@link guide/expression expression} is truthy/falsy then the + * element is shown/hidden respectively. + * + * @example + * A simple example, animating the element's opacity: + * + + + Show:
    +
    + I show up when your checkbox is checked. +
    +
    + + .animate-show-hide.ng-hide { + opacity: 0; + } + + .animate-show-hide.ng-hide-add, + .animate-show-hide.ng-hide-remove { + transition: all linear 0.5s; + } + + .check-element { + border: 1px solid black; + opacity: 1; + padding: 10px; + } + + + it('should check ngShow', function() { + var checkbox = element(by.model('checked')); + var checkElem = element(by.css('.check-element')); + + expect(checkElem.isDisplayed()).toBe(false); + checkbox.click(); + expect(checkElem.isDisplayed()).toBe(true); + }); + +
    + * + *
    + * @example + * A more complex example, featuring different show/hide animations: + * + + + Show:
    +
    + I show up when your checkbox is checked. +
    +
    + + body { + overflow: hidden; + perspective: 1000px; + } + + .funky-show-hide.ng-hide-add { + transform: rotateZ(0); + transform-origin: right; + transition: all 0.5s ease-in-out; + } + + .funky-show-hide.ng-hide-add.ng-hide-add-active { + transform: rotateZ(-135deg); + } + + .funky-show-hide.ng-hide-remove { + transform: rotateY(90deg); + transform-origin: left; + transition: all 0.5s ease; + } + + .funky-show-hide.ng-hide-remove.ng-hide-remove-active { + transform: rotateY(0); + } + + .check-element { + border: 1px solid black; + opacity: 1; + padding: 10px; + } + + + it('should check ngShow', function() { + var checkbox = element(by.model('checked')); + var checkElem = element(by.css('.check-element')); + + expect(checkElem.isDisplayed()).toBe(false); + checkbox.click(); + expect(checkElem.isDisplayed()).toBe(true); + }); + +
    + * + * @knownIssue + * + * ### Flickering when using ngShow to toggle between elements + * + * When using {@link ngShow} and / or {@link ngHide} to toggle between elements, it can + * happen that both the element to show and the element to hide are visible for a very short time. + * + * This usually happens when the {@link ngAnimate ngAnimate module} is included, but no actual animations + * are defined for {@link ngShow} / {@link ngHide}. Internet Explorer is affected more often than + * other browsers. + * + * There are several way to mitigate this problem: + * + * - {@link guide/animations#how-to-selectively-enable-disable-and-skip-animations Disable animations on the affected elements}. + * - Use {@link ngIf} or {@link ngSwitch} instead of {@link ngShow} / {@link ngHide}. + * - Use the special CSS selector `ng-hide.ng-hide-animate` to set `{display: none}` or similar on the affected elements. + * - Use `ng-class="{'ng-hide': expression}` instead of instead of {@link ngShow} / {@link ngHide}. + * - Define an animation on the affected elements. + */ +var ngShowDirective = ['$animate', function($animate) { + return { + restrict: 'A', + multiElement: true, + link: function(scope, element, attr) { + scope.$watch(attr.ngShow, function ngShowWatchAction(value) { + // we're adding a temporary, animation-specific class for ng-hide since this way + // we can control when the element is actually displayed on screen without having + // to have a global/greedy CSS selector that breaks when other animations are run. + // Read: https://github.com/angular/angular.js/issues/9103#issuecomment-58335845 + $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, { + tempClasses: NG_HIDE_IN_PROGRESS_CLASS + }); + }); + } + }; +}]; + + +/** + * @ngdoc directive + * @name ngHide + * @multiElement + * + * @description + * The `ngHide` directive shows or hides the given HTML element based on the expression provided to + * the `ngHide` attribute. + * + * The element is shown or hidden by removing or adding the `.ng-hide` CSS class onto the element. + * The `.ng-hide` CSS class is predefined in AngularJS and sets the display style to none (using an + * `!important` flag). For CSP mode please add `angular-csp.css` to your HTML file (see + * {@link ng.directive:ngCsp ngCsp}). + * + * ```html + * + *
    + * + * + *
    + * ``` + * + * When the `ngHide` expression evaluates to a truthy value then the `.ng-hide` CSS class is added + * to the class attribute on the element causing it to become hidden. When falsy, the `.ng-hide` + * CSS class is removed from the element causing the element not to appear hidden. + * + * ## Why is `!important` used? + * + * You may be wondering why `!important` is used for the `.ng-hide` CSS class. This is because the + * `.ng-hide` selector can be easily overridden by heavier selectors. For example, something as + * simple as changing the display style on a HTML list item would make hidden elements appear + * visible. This also becomes a bigger issue when dealing with CSS frameworks. + * + * By using `!important`, the show and hide behavior will work as expected despite any clash between + * CSS selector specificity (when `!important` isn't used with any conflicting styles). If a + * developer chooses to override the styling to change how to hide an element then it is just a + * matter of using `!important` in their own CSS code. + * + * ### Overriding `.ng-hide` + * + * By default, the `.ng-hide` class will style the element with `display: none !important`. If you + * wish to change the hide behavior with `ngShow`/`ngHide`, you can simply overwrite the styles for + * the `.ng-hide` CSS class. Note that the selector that needs to be used is actually + * `.ng-hide:not(.ng-hide-animate)` to cope with extra animation classes that can be added. + * + * ```css + * .ng-hide:not(.ng-hide-animate) { + * /* These are just alternative ways of hiding an element */ + * display: block!important; + * position: absolute; + * top: -9999px; + * left: -9999px; + * } + * ``` + * + * By default you don't need to override in CSS anything and the animations will work around the + * display style. + * + * @animations + * | Animation | Occurs | + * |-----------------------------------------------------|------------------------------------------------------------------------------------------------------------| + * | {@link $animate#addClass addClass} `.ng-hide` | After the `ngHide` expression evaluates to a truthy value and just before the contents are set to hidden. | + * | {@link $animate#removeClass removeClass} `.ng-hide` | After the `ngHide` expression evaluates to a non truthy value and just before contents are set to visible. | + * + * Animations in `ngShow`/`ngHide` work with the show and hide events that are triggered when the + * directive expression is true and false. This system works like the animation system present with + * `ngClass` except that you must also include the `!important` flag to override the display + * property so that the elements are not actually hidden during the animation. + * + * ```css + * /* A working example can be found at the bottom of this page. */ + * .my-element.ng-hide-add, .my-element.ng-hide-remove { + * transition: all 0.5s linear; + * } + * + * .my-element.ng-hide-add { ... } + * .my-element.ng-hide-add.ng-hide-add-active { ... } + * .my-element.ng-hide-remove { ... } + * .my-element.ng-hide-remove.ng-hide-remove-active { ... } + * ``` + * + * Keep in mind that, as of AngularJS version 1.3, there is no need to change the display property + * to block during animation states - ngAnimate will automatically handle the style toggling for you. + * + * @element ANY + * @param {expression} ngHide If the {@link guide/expression expression} is truthy/falsy then the + * element is hidden/shown respectively. + * + * @example + * A simple example, animating the element's opacity: + * + + + Hide:
    +
    + I hide when your checkbox is checked. +
    +
    + + .animate-show-hide.ng-hide { + opacity: 0; + } + + .animate-show-hide.ng-hide-add, + .animate-show-hide.ng-hide-remove { + transition: all linear 0.5s; + } + + .check-element { + border: 1px solid black; + opacity: 1; + padding: 10px; + } + + + it('should check ngHide', function() { + var checkbox = element(by.model('checked')); + var checkElem = element(by.css('.check-element')); + + expect(checkElem.isDisplayed()).toBe(true); + checkbox.click(); + expect(checkElem.isDisplayed()).toBe(false); + }); + +
    + * + *
    + * @example + * A more complex example, featuring different show/hide animations: + * + + + Hide:
    +
    + I hide when your checkbox is checked. +
    +
    + + body { + overflow: hidden; + perspective: 1000px; + } + + .funky-show-hide.ng-hide-add { + transform: rotateZ(0); + transform-origin: right; + transition: all 0.5s ease-in-out; + } + + .funky-show-hide.ng-hide-add.ng-hide-add-active { + transform: rotateZ(-135deg); + } + + .funky-show-hide.ng-hide-remove { + transform: rotateY(90deg); + transform-origin: left; + transition: all 0.5s ease; + } + + .funky-show-hide.ng-hide-remove.ng-hide-remove-active { + transform: rotateY(0); + } + + .check-element { + border: 1px solid black; + opacity: 1; + padding: 10px; + } + + + it('should check ngHide', function() { + var checkbox = element(by.model('checked')); + var checkElem = element(by.css('.check-element')); + + expect(checkElem.isDisplayed()).toBe(true); + checkbox.click(); + expect(checkElem.isDisplayed()).toBe(false); + }); + +
    + * + * @knownIssue + * + * ### Flickering when using ngHide to toggle between elements + * + * When using {@link ngShow} and / or {@link ngHide} to toggle between elements, it can + * happen that both the element to show and the element to hide are visible for a very short time. + * + * This usually happens when the {@link ngAnimate ngAnimate module} is included, but no actual animations + * are defined for {@link ngShow} / {@link ngHide}. Internet Explorer is affected more often than + * other browsers. + * + * There are several way to mitigate this problem: + * + * - {@link guide/animations#how-to-selectively-enable-disable-and-skip-animations Disable animations on the affected elements}. + * - Use {@link ngIf} or {@link ngSwitch} instead of {@link ngShow} / {@link ngHide}. + * - Use the special CSS selector `ng-hide.ng-hide-animate` to set `{display: none}` or similar on the affected elements. + * - Use `ng-class="{'ng-hide': expression}` instead of instead of {@link ngShow} / {@link ngHide}. + * - Define an animation on the affected elements. + */ +var ngHideDirective = ['$animate', function($animate) { + return { + restrict: 'A', + multiElement: true, + link: function(scope, element, attr) { + scope.$watch(attr.ngHide, function ngHideWatchAction(value) { + // The comment inside of the ngShowDirective explains why we add and + // remove a temporary class for the show/hide animation + $animate[value ? 'addClass' : 'removeClass'](element,NG_HIDE_CLASS, { + tempClasses: NG_HIDE_IN_PROGRESS_CLASS + }); + }); + } + }; +}]; + +/** + * @ngdoc directive + * @name ngStyle + * @restrict AC + * + * @description + * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally. + * + * @knownIssue + * You should not use {@link guide/interpolation interpolation} in the value of the `style` + * attribute, when using the `ngStyle` directive on the same element. + * See {@link guide/interpolation#known-issues here} for more info. + * + * @element ANY + * @param {expression} ngStyle + * + * {@link guide/expression Expression} which evals to an + * object whose keys are CSS style names and values are corresponding values for those CSS + * keys. + * + * Since some CSS style names are not valid keys for an object, they must be quoted. + * See the 'background-color' style in the example below. + * + * @example + + + + + +
    + Sample Text +
    myStyle={{myStyle}}
    +
    + + span { + color: black; + } + + + var colorSpan = element(by.css('span')); + + it('should check ng-style', function() { + expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); + element(by.css('input[value=\'set color\']')).click(); + expect(colorSpan.getCssValue('color')).toBe('rgba(255, 0, 0, 1)'); + element(by.css('input[value=clear]')).click(); + expect(colorSpan.getCssValue('color')).toBe('rgba(0, 0, 0, 1)'); + }); + +
    + */ +var ngStyleDirective = ngDirective(function(scope, element, attr) { + scope.$watchCollection(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { + if (oldStyles && (newStyles !== oldStyles)) { + if (!newStyles) { + newStyles = {}; + } + forEach(oldStyles, function(val, style) { + if (newStyles[style] == null) { + newStyles[style] = ''; + } + }); + } + if (newStyles) element.css(newStyles); + }); +}); + +/** + * @ngdoc directive + * @name ngSwitch + * @restrict EA + * + * @description + * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression. + * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location + * as specified in the template. + * + * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it + * from the template cache), `ngSwitch` simply chooses one of the nested elements and makes it visible based on which element + * matches the value obtained from the evaluated expression. In other words, you define a container element + * (where you place the directive), place an expression on the **`on="..."` attribute** + * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place + * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on + * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default + * attribute is displayed. + * + *
    + * Be aware that the attribute values to match against cannot be expressions. They are interpreted + * as literal string values to match against. + * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the + * value of the expression `$scope.someVal`. + *
    + + * @animations + * | Animation | Occurs | + * |----------------------------------|-------------------------------------| + * | {@link ng.$animate#enter enter} | after the ngSwitch contents change and the matched child element is placed inside the container | + * | {@link ng.$animate#leave leave} | after the ngSwitch contents change and just before the former contents are removed from the DOM | + * + * @usage + * + * ``` + * + * ... + * ... + * ... + * + * ``` + * + * + * @scope + * @priority 1200 + * @param {*} ngSwitch|on expression to match against ng-switch-when. + * On child elements add: + * + * * `ngSwitchWhen`: the case statement to match against. If match then this + * case will be displayed. If the same match appears multiple times, all the + * elements will be displayed. It is possible to associate multiple values to + * the same `ngSwitchWhen` by defining the optional attribute + * `ngSwitchWhenSeparator`. The separator will be used to split the value of + * the `ngSwitchWhen` attribute into multiple tokens, and the element will show + * if any of the `ngSwitch` evaluates to any of these tokens. + * * `ngSwitchDefault`: the default case when no other case match. If there + * are multiple default cases, all of them will be displayed when no other + * case match. + * + * + * @example + + +
    + + selection={{selection}} +
    +
    +
    Settings Div
    +
    Home Span
    +
    default
    +
    +
    +
    + + angular.module('switchExample', ['ngAnimate']) + .controller('ExampleController', ['$scope', function($scope) { + $scope.items = ['settings', 'home', 'options', 'other']; + $scope.selection = $scope.items[0]; + }]); + + + .animate-switch-container { + position:relative; + background:white; + border:1px solid black; + height:40px; + overflow:hidden; + } + + .animate-switch { + padding:10px; + } + + .animate-switch.ng-animate { + transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; + + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + } + + .animate-switch.ng-leave.ng-leave-active, + .animate-switch.ng-enter { + top:-50px; + } + .animate-switch.ng-leave, + .animate-switch.ng-enter.ng-enter-active { + top:0; + } + + + var switchElem = element(by.css('[ng-switch]')); + var select = element(by.model('selection')); + + it('should start in settings', function() { + expect(switchElem.getText()).toMatch(/Settings Div/); + }); + it('should change to home', function() { + select.all(by.css('option')).get(1).click(); + expect(switchElem.getText()).toMatch(/Home Span/); + }); + it('should change to settings via "options"', function() { + select.all(by.css('option')).get(2).click(); + expect(switchElem.getText()).toMatch(/Settings Div/); + }); + it('should select default', function() { + select.all(by.css('option')).get(3).click(); + expect(switchElem.getText()).toMatch(/default/); + }); + +
    + */ +var ngSwitchDirective = ['$animate', '$compile', function($animate, $compile) { + return { + require: 'ngSwitch', + + // asks for $scope to fool the BC controller module + controller: ['$scope', function NgSwitchController() { + this.cases = {}; + }], + link: function(scope, element, attr, ngSwitchController) { + var watchExpr = attr.ngSwitch || attr.on, + selectedTranscludes = [], + selectedElements = [], + previousLeaveAnimations = [], + selectedScopes = []; + + var spliceFactory = function(array, index) { + return function(response) { + if (response !== false) array.splice(index, 1); + }; + }; + + scope.$watch(watchExpr, function ngSwitchWatchAction(value) { + var i, ii; + + // Start with the last, in case the array is modified during the loop + while (previousLeaveAnimations.length) { + $animate.cancel(previousLeaveAnimations.pop()); + } + + for (i = 0, ii = selectedScopes.length; i < ii; ++i) { + var selected = getBlockNodes(selectedElements[i].clone); + selectedScopes[i].$destroy(); + var runner = previousLeaveAnimations[i] = $animate.leave(selected); + runner.done(spliceFactory(previousLeaveAnimations, i)); + } + + selectedElements.length = 0; + selectedScopes.length = 0; + + if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) { + forEach(selectedTranscludes, function(selectedTransclude) { + selectedTransclude.transclude(function(caseElement, selectedScope) { + selectedScopes.push(selectedScope); + var anchor = selectedTransclude.element; + caseElement[caseElement.length++] = $compile.$$createComment('end ngSwitchWhen'); + var block = { clone: caseElement }; + + selectedElements.push(block); + $animate.enter(caseElement, anchor.parent(), anchor); + }); + }); + } + }); + } + }; +}]; + +var ngSwitchWhenDirective = ngDirective({ + transclude: 'element', + priority: 1200, + require: '^ngSwitch', + multiElement: true, + link: function(scope, element, attrs, ctrl, $transclude) { + + var cases = attrs.ngSwitchWhen.split(attrs.ngSwitchWhenSeparator).sort().filter( + // Filter duplicate cases + function(element, index, array) { return array[index - 1] !== element; } + ); + + forEach(cases, function(whenCase) { + ctrl.cases['!' + whenCase] = (ctrl.cases['!' + whenCase] || []); + ctrl.cases['!' + whenCase].push({ transclude: $transclude, element: element }); + }); + } +}); + +var ngSwitchDefaultDirective = ngDirective({ + transclude: 'element', + priority: 1200, + require: '^ngSwitch', + multiElement: true, + link: function(scope, element, attr, ctrl, $transclude) { + ctrl.cases['?'] = (ctrl.cases['?'] || []); + ctrl.cases['?'].push({ transclude: $transclude, element: element }); + } +}); + +/** + * @ngdoc directive + * @name ngTransclude + * @restrict EAC + * + * @description + * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion. + * + * You can specify that you want to insert a named transclusion slot, instead of the default slot, by providing the slot name + * as the value of the `ng-transclude` or `ng-transclude-slot` attribute. + * + * If the transcluded content is not empty (i.e. contains one or more DOM nodes, including whitespace text nodes), any existing + * content of this element will be removed before the transcluded content is inserted. + * If the transcluded content is empty (or only whitespace), the existing content is left intact. This lets you provide fallback + * content in the case that no transcluded content is provided. + * + * @element ANY + * + * @param {string} ngTransclude|ngTranscludeSlot the name of the slot to insert at this point. If this is not provided, is empty + * or its value is the same as the name of the attribute then the default slot is used. + * + * @example + * ### Basic transclusion + * This example demonstrates basic transclusion of content into a component directive. + * + * + * + *
    + *
    + *
    + * {{text}} + *
    + *
    + * + * it('should have transcluded', function() { + * var titleElement = element(by.model('title')); + * titleElement.clear(); + * titleElement.sendKeys('TITLE'); + * var textElement = element(by.model('text')); + * textElement.clear(); + * textElement.sendKeys('TEXT'); + * expect(element(by.binding('title')).getText()).toEqual('TITLE'); + * expect(element(by.binding('text')).getText()).toEqual('TEXT'); + * }); + * + *
    + * + * @example + * ### Transclude fallback content + * This example shows how to use `NgTransclude` with fallback content, that + * is displayed if no transcluded content is provided. + * + * + * + * + * + * + * + * + * Button2 + * + * + * + * it('should have different transclude element content', function() { + * expect(element(by.id('fallback')).getText()).toBe('Button1'); + * expect(element(by.id('modified')).getText()).toBe('Button2'); + * }); + * + * + * + * @example + * ### Multi-slot transclusion + * This example demonstrates using multi-slot transclusion in a component directive. + * + * + * + *
    + *
    + *
    + * + *
    {{title}} + *

    {{text}}

    + * + *
    + * + * + * angular.module('multiSlotTranscludeExample', []) + * .directive('pane', function() { + * return { + * restrict: 'E', + * transclude: { + * 'title': '?paneTitle', + * 'body': 'paneBody', + * 'footer': '?paneFooter' + * }, + * template: '
    ' + + * '
    Fallback Title
    ' + + * '
    ' + + * '' + + * '
    ' + * }; + * }) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.title = 'Lorem Ipsum'; + * $scope.link = 'https://google.com'; + * $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...'; + * }]); + *
    + * + * it('should have transcluded the title and the body', function() { + * var titleElement = element(by.model('title')); + * titleElement.clear(); + * titleElement.sendKeys('TITLE'); + * var textElement = element(by.model('text')); + * textElement.clear(); + * textElement.sendKeys('TEXT'); + * expect(element(by.css('.title')).getText()).toEqual('TITLE'); + * expect(element(by.binding('text')).getText()).toEqual('TEXT'); + * expect(element(by.css('.footer')).getText()).toEqual('Fallback Footer'); + * }); + * + * + */ +var ngTranscludeMinErr = minErr('ngTransclude'); +var ngTranscludeDirective = ['$compile', function($compile) { + return { + restrict: 'EAC', + compile: function ngTranscludeCompile(tElement) { + + // Remove and cache any original content to act as a fallback + var fallbackLinkFn = $compile(tElement.contents()); + tElement.empty(); + + return function ngTranscludePostLink($scope, $element, $attrs, controller, $transclude) { + + if (!$transclude) { + throw ngTranscludeMinErr('orphan', + 'Illegal use of ngTransclude directive in the template! ' + + 'No parent directive that requires a transclusion found. ' + + 'Element: {0}', + startingTag($element)); + } + + + // If the attribute is of the form: `ng-transclude="ng-transclude"` then treat it like the default + if ($attrs.ngTransclude === $attrs.$attr.ngTransclude) { + $attrs.ngTransclude = ''; + } + var slotName = $attrs.ngTransclude || $attrs.ngTranscludeSlot; + + // If the slot is required and no transclusion content is provided then this call will throw an error + $transclude(ngTranscludeCloneAttachFn, null, slotName); + + // If the slot is optional and no transclusion content is provided then use the fallback content + if (slotName && !$transclude.isSlotFilled(slotName)) { + useFallbackContent(); + } + + function ngTranscludeCloneAttachFn(clone, transcludedScope) { + if (clone.length && notWhitespace(clone)) { + $element.append(clone); + } else { + useFallbackContent(); + // There is nothing linked against the transcluded scope since no content was available, + // so it should be safe to clean up the generated scope. + transcludedScope.$destroy(); + } + } + + function useFallbackContent() { + // Since this is the fallback content rather than the transcluded content, + // we link against the scope of this directive rather than the transcluded scope + fallbackLinkFn($scope, function(clone) { + $element.append(clone); + }); + } + + function notWhitespace(nodes) { + for (var i = 0, ii = nodes.length; i < ii; i++) { + var node = nodes[i]; + if (node.nodeType !== NODE_TYPE_TEXT || node.nodeValue.trim()) { + return true; + } + } + } + }; + } + }; +}]; + +/** + * @ngdoc directive + * @name script + * @restrict E + * + * @description + * Load the content of a ` + + Load inlined template +
    + + + it('should load template defined inside script tag', function() { + element(by.css('#tpl-link')).click(); + expect(element(by.css('#tpl-content')).getText()).toMatch(/Content of the template/); + }); + + + */ +var scriptDirective = ['$templateCache', function($templateCache) { + return { + restrict: 'E', + terminal: true, + compile: function(element, attr) { + if (attr.type === 'text/ng-template') { + var templateUrl = attr.id, + text = element[0].text; + + $templateCache.put(templateUrl, text); + } + } + }; +}]; + +/* exported selectDirective, optionDirective */ + +var noopNgModelController = { $setViewValue: noop, $render: noop }; + +function setOptionSelectedStatus(optionEl, value) { + optionEl.prop('selected', value); + /** + * When unselecting an option, setting the property to null / false should be enough + * However, screenreaders might react to the selected attribute instead, see + * https://github.com/angular/angular.js/issues/14419 + * Note: "selected" is a boolean attr and will be removed when the "value" arg in attr() is false + * or null + */ + optionEl.attr('selected', value); +} + +/** + * @ngdoc type + * @name select.SelectController + * + * @description + * The controller for the {@link ng.select select} directive. The controller exposes + * a few utility methods that can be used to augment the behavior of a regular or an + * {@link ng.ngOptions ngOptions} select element. + * + * @example + * ### Set a custom error when the unknown option is selected + * + * This example sets a custom error "unknownValue" on the ngModelController + * when the select element's unknown option is selected, i.e. when the model is set to a value + * that is not matched by any option. + * + * + * + *
    + *
    + *
    + *
    + * + * Error: The current model doesn't match any option
    + * + *
    + *
    + *
    + *
    + * + * angular.module('staticSelect', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.selected = null; + * + * $scope.forceUnknownOption = function() { + * $scope.selected = 'nonsense'; + * }; + * }]) + * .directive('unknownValueError', function() { + * return { + * require: ['ngModel', 'select'], + * link: function(scope, element, attrs, ctrls) { + * var ngModelCtrl = ctrls[0]; + * var selectCtrl = ctrls[1]; + * + * ngModelCtrl.$validators.unknownValue = function(modelValue, viewValue) { + * if (selectCtrl.$isUnknownOptionSelected()) { + * return false; + * } + * + * return true; + * }; + * } + * + * }; + * }); + * + *
    + * + * + * @example + * ### Set the "required" error when the unknown option is selected. + * + * By default, the "required" error on the ngModelController is only set on a required select + * when the empty option is selected. This example adds a custom directive that also sets the + * error when the unknown option is selected. + * + * + * + *
    + *
    + *
    + *
    + * Error: Please select a value
    + * + *
    + *
    + *
    + *
    + * + * angular.module('staticSelect', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.selected = null; + * + * $scope.forceUnknownOption = function() { + * $scope.selected = 'nonsense'; + * }; + * }]) + * .directive('unknownValueRequired', function() { + * return { + * priority: 1, // This directive must run after the required directive has added its validator + * require: ['ngModel', 'select'], + * link: function(scope, element, attrs, ctrls) { + * var ngModelCtrl = ctrls[0]; + * var selectCtrl = ctrls[1]; + * + * var originalRequiredValidator = ngModelCtrl.$validators.required; + * + * ngModelCtrl.$validators.required = function() { + * if (attrs.required && selectCtrl.$isUnknownOptionSelected()) { + * return false; + * } + * + * return originalRequiredValidator.apply(this, arguments); + * }; + * } + * }; + * }); + * + * + * it('should show the error message when the unknown option is selected', function() { + + var error = element(by.className('error')); + + expect(error.getText()).toBe('Error: Please select a value'); + + element(by.cssContainingText('option', 'Option 1')).click(); + + expect(error.isPresent()).toBe(false); + + element(by.tagName('button')).click(); + + expect(error.getText()).toBe('Error: Please select a value'); + }); + * + *
    + * + * + */ +var SelectController = + ['$element', '$scope', /** @this */ function($element, $scope) { + + var self = this, + optionsMap = new NgMap(); + + self.selectValueMap = {}; // Keys are the hashed values, values the original values + + // If the ngModel doesn't get provided then provide a dummy noop version to prevent errors + self.ngModelCtrl = noopNgModelController; + self.multiple = false; + + // The "unknown" option is one that is prepended to the list if the viewValue + // does not match any of the options. When it is rendered the value of the unknown + // option is '? XXX ?' where XXX is the hashKey of the value that is not known. + // + // Support: IE 9 only + // We can't just jqLite(' + * + *
    + * + *
    + *
    + *
    + * singleSelect = {{data.singleSelect}} + * + *
    + *
    + *
    + * multipleSelect = {{data.multipleSelect}}
    + * + *
    + * + * + * angular.module('staticSelect', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.data = { + * singleSelect: null, + * multipleSelect: [], + * option1: 'option-1' + * }; + * + * $scope.forceUnknownOption = function() { + * $scope.data.singleSelect = 'nonsense'; + * }; + * }]); + * + * + * + * @example + * ### Using `ngRepeat` to generate `select` options + * + * + *
    + *
    + * + * + *
    + *
    + * model = {{data.model}}
    + *
    + *
    + * + * angular.module('ngrepeatSelect', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.data = { + * model: null, + * availableOptions: [ + * {id: '1', name: 'Option A'}, + * {id: '2', name: 'Option B'}, + * {id: '3', name: 'Option C'} + * ] + * }; + * }]); + * + *
    + * + * @example + * ### Using `ngValue` to bind the model to an array of objects + * + * + *
    + *
    + * + * + *
    + *
    + *
    model = {{data.model | json}}

    + *
    + *
    + * + * angular.module('ngvalueSelect', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.data = { + * model: null, + * availableOptions: [ + {value: 'myString', name: 'string'}, + {value: 1, name: 'integer'}, + {value: true, name: 'boolean'}, + {value: null, name: 'null'}, + {value: {prop: 'value'}, name: 'object'}, + {value: ['a'], name: 'array'} + * ] + * }; + * }]); + * + *
    + * + * @example + * ### Using `select` with `ngOptions` and setting a default value + * See the {@link ngOptions ngOptions documentation} for more `ngOptions` usage examples. + * + * + * + *
    + *
    + * + * + *
    + *
    + * option = {{data.selectedOption}}
    + *
    + *
    + * + * angular.module('defaultValueSelect', []) + * .controller('ExampleController', ['$scope', function($scope) { + * $scope.data = { + * availableOptions: [ + * {id: '1', name: 'Option A'}, + * {id: '2', name: 'Option B'}, + * {id: '3', name: 'Option C'} + * ], + * selectedOption: {id: '3', name: 'Option C'} //This sets the default value of the select in the ui + * }; + * }]); + * + *
    + * + * @example + * ### Binding `select` to a non-string value via `ngModel` parsing / formatting + * + * + * + * + * {{ model }} + * + * + * angular.module('nonStringSelect', []) + * .run(function($rootScope) { + * $rootScope.model = { id: 2 }; + * }) + * .directive('convertToNumber', function() { + * return { + * require: 'ngModel', + * link: function(scope, element, attrs, ngModel) { + * ngModel.$parsers.push(function(val) { + * return parseInt(val, 10); + * }); + * ngModel.$formatters.push(function(val) { + * return '' + val; + * }); + * } + * }; + * }); + * + * + * it('should initialize to model', function() { + * expect(element(by.model('model.id')).$('option:checked').getText()).toEqual('Two'); + * }); + * + * + * + */ +var selectDirective = function() { + + return { + restrict: 'E', + require: ['select', '?ngModel'], + controller: SelectController, + priority: 1, + link: { + pre: selectPreLink, + post: selectPostLink + } + }; + + function selectPreLink(scope, element, attr, ctrls) { + + var selectCtrl = ctrls[0]; + var ngModelCtrl = ctrls[1]; + + // if ngModel is not defined, we don't need to do anything but set the registerOption + // function to noop, so options don't get added internally + if (!ngModelCtrl) { + selectCtrl.registerOption = noop; + return; + } + + + selectCtrl.ngModelCtrl = ngModelCtrl; + + // When the selected item(s) changes we delegate getting the value of the select control + // to the `readValue` method, which can be changed if the select can have multiple + // selected values or if the options are being generated by `ngOptions` + element.on('change', function() { + selectCtrl.removeUnknownOption(); + scope.$apply(function() { + ngModelCtrl.$setViewValue(selectCtrl.readValue()); + }); + }); + + // If the select allows multiple values then we need to modify how we read and write + // values from and to the control; also what it means for the value to be empty and + // we have to add an extra watch since ngModel doesn't work well with arrays - it + // doesn't trigger rendering if only an item in the array changes. + if (attr.multiple) { + selectCtrl.multiple = true; + + // Read value now needs to check each option to see if it is selected + selectCtrl.readValue = function readMultipleValue() { + var array = []; + forEach(element.find('option'), function(option) { + if (option.selected && !option.disabled) { + var val = option.value; + array.push(val in selectCtrl.selectValueMap ? selectCtrl.selectValueMap[val] : val); + } + }); + return array; + }; + + // Write value now needs to set the selected property of each matching option + selectCtrl.writeValue = function writeMultipleValue(value) { + forEach(element.find('option'), function(option) { + var shouldBeSelected = !!value && (includes(value, option.value) || + includes(value, selectCtrl.selectValueMap[option.value])); + var currentlySelected = option.selected; + + // Support: IE 9-11 only, Edge 12-15+ + // In IE and Edge adding options to the selection via shift+click/UP/DOWN + // will de-select already selected options if "selected" on those options was set + // more than once (i.e. when the options were already selected) + // So we only modify the selected property if necessary. + // Note: this behavior cannot be replicated via unit tests because it only shows in the + // actual user interface. + if (shouldBeSelected !== currentlySelected) { + setOptionSelectedStatus(jqLite(option), shouldBeSelected); + } + + }); + }; + + // we have to do it on each watch since ngModel watches reference, but + // we need to work of an array, so we need to see if anything was inserted/removed + var lastView, lastViewRef = NaN; + scope.$watch(function selectMultipleWatch() { + if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) { + lastView = shallowCopy(ngModelCtrl.$viewValue); + ngModelCtrl.$render(); + } + lastViewRef = ngModelCtrl.$viewValue; + }); + + // If we are a multiple select then value is now a collection + // so the meaning of $isEmpty changes + ngModelCtrl.$isEmpty = function(value) { + return !value || value.length === 0; + }; + + } + } + + function selectPostLink(scope, element, attrs, ctrls) { + // if ngModel is not defined, we don't need to do anything + var ngModelCtrl = ctrls[1]; + if (!ngModelCtrl) return; + + var selectCtrl = ctrls[0]; + + // We delegate rendering to the `writeValue` method, which can be changed + // if the select can have multiple selected values or if the options are being + // generated by `ngOptions`. + // This must be done in the postLink fn to prevent $render to be called before + // all nodes have been linked correctly. + ngModelCtrl.$render = function() { + selectCtrl.writeValue(ngModelCtrl.$viewValue); + }; + } +}; + + +// The option directive is purely designed to communicate the existence (or lack of) +// of dynamically created (and destroyed) option elements to their containing select +// directive via its controller. +var optionDirective = ['$interpolate', function($interpolate) { + return { + restrict: 'E', + priority: 100, + compile: function(element, attr) { + var interpolateValueFn, interpolateTextFn; + + if (isDefined(attr.ngValue)) { + // Will be handled by registerOption + } else if (isDefined(attr.value)) { + // If the value attribute is defined, check if it contains an interpolation + interpolateValueFn = $interpolate(attr.value, true); + } else { + // If the value attribute is not defined then we fall back to the + // text content of the option element, which may be interpolated + interpolateTextFn = $interpolate(element.text(), true); + if (!interpolateTextFn) { + attr.$set('value', element.text()); + } + } + + return function(scope, element, attr) { + // This is an optimization over using ^^ since we don't want to have to search + // all the way to the root of the DOM for every single option element + var selectCtrlName = '$selectController', + parent = element.parent(), + selectCtrl = parent.data(selectCtrlName) || + parent.parent().data(selectCtrlName); // in case we are in optgroup + + if (selectCtrl) { + selectCtrl.registerOption(scope, element, attr, interpolateValueFn, interpolateTextFn); + } + }; + } + }; +}]; + +/** + * @ngdoc directive + * @name ngRequired + * @restrict A + * + * @param {expression} ngRequired AngularJS expression. If it evaluates to `true`, it sets the + * `required` attribute to the element and adds the `required` + * {@link ngModel.NgModelController#$validators `validator`}. + * + * @description + * + * ngRequired adds the required {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}. + * It is most often used for {@link input `input`} and {@link select `select`} controls, but can also be + * applied to custom controls. + * + * The directive sets the `required` attribute on the element if the AngularJS expression inside + * `ngRequired` evaluates to true. A special directive for setting `required` is necessary because we + * cannot use interpolation inside `required`. See the {@link guide/interpolation interpolation guide} + * for more info. + * + * The validator will set the `required` error key to true if the `required` attribute is set and + * calling {@link ngModel.NgModelController#$isEmpty `NgModelController.$isEmpty`} with the + * {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} returns `true`. For example, the + * `$isEmpty()` implementation for `input[text]` checks the length of the `$viewValue`. When developing + * custom controls, `$isEmpty()` can be overwritten to account for a $viewValue that is not string-based. + * + * @example + * + * + * + *
    + *
    + * + * + *
    + * + *
    + *
    + * required error set? = {{form.input.$error.required}}
    + * model = {{model}} + *
    + *
    + *
    + * + var required = element(by.binding('form.input.$error.required')); + var model = element(by.binding('model')); + var input = element(by.id('input')); + + it('should set the required error', function() { + expect(required.getText()).toContain('true'); + + input.sendKeys('123'); + expect(required.getText()).not.toContain('true'); + expect(model.getText()).toContain('123'); + }); + * + *
    + */ +var requiredDirective = ['$parse', function($parse) { + return { + restrict: 'A', + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + // For boolean attributes like required, presence means true + var value = attr.hasOwnProperty('required') || $parse(attr.ngRequired)(scope); + + if (!attr.ngRequired) { + // force truthy in case we are on non input element + // (input elements do this automatically for boolean attributes like required) + attr.required = true; + } + + ctrl.$validators.required = function(modelValue, viewValue) { + return !value || !ctrl.$isEmpty(viewValue); + }; + + attr.$observe('required', function(newVal) { + + if (value !== newVal) { + value = newVal; + ctrl.$validate(); + } + }); + } + }; +}]; + +/** + * @ngdoc directive + * @name ngPattern + * @restrict A + * + * @param {expression|RegExp} ngPattern AngularJS expression that must evaluate to a `RegExp` or a `String` + * parsable into a `RegExp`, or a `RegExp` literal. See above for + * more details. + * + * @description + * + * ngPattern adds the pattern {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}. + * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls. + * + * The validator sets the `pattern` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} + * does not match a RegExp which is obtained from the `ngPattern` attribute value: + * - the value is an AngularJS expression: + * - If the expression evaluates to a RegExp object, then this is used directly. + * - If the expression evaluates to a string, then it will be converted to a RegExp after wrapping it + * in `^` and `$` characters. For instance, `"abc"` will be converted to `new RegExp('^abc$')`. + * - If the value is a RegExp literal, e.g. `ngPattern="/^\d+$/"`, it is used directly. + * + *
    + * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to + * start at the index of the last search's match, thus not taking the whole input value into + * account. + *
    + * + *
    + * **Note:** This directive is also added when the plain `pattern` attribute is used, with two + * differences: + *
      + *
    1. + * `ngPattern` does not set the `pattern` attribute and therefore HTML5 constraint validation is + * not available. + *
    2. + *
    3. + * The `ngPattern` attribute must be an expression, while the `pattern` value must be + * interpolated. + *
    4. + *
    + *
    + * + * @example + * + * + * + *
    + *
    + * + * + *
    + * + *
    + *
    + * input valid? = {{form.input.$valid}}
    + * model = {{model}} + *
    + *
    + *
    + * + var model = element(by.binding('model')); + var input = element(by.id('input')); + + it('should validate the input with the default pattern', function() { + input.sendKeys('aaa'); + expect(model.getText()).not.toContain('aaa'); + + input.clear().then(function() { + input.sendKeys('123'); + expect(model.getText()).toContain('123'); + }); + }); + * + *
    + */ +var patternDirective = ['$parse', function($parse) { + return { + restrict: 'A', + require: '?ngModel', + compile: function(tElm, tAttr) { + var patternExp; + var parseFn; + + if (tAttr.ngPattern) { + patternExp = tAttr.ngPattern; + + // ngPattern might be a scope expression, or an inlined regex, which is not parsable. + // We get value of the attribute here, so we can compare the old and the new value + // in the observer to avoid unnecessary validations + if (tAttr.ngPattern.charAt(0) === '/' && REGEX_STRING_REGEXP.test(tAttr.ngPattern)) { + parseFn = function() { return tAttr.ngPattern; }; + } else { + parseFn = $parse(tAttr.ngPattern); + } + } + + return function(scope, elm, attr, ctrl) { + if (!ctrl) return; + + var attrVal = attr.pattern; + + if (attr.ngPattern) { + attrVal = parseFn(scope); + } else { + patternExp = attr.pattern; + } + + var regexp = parsePatternAttr(attrVal, patternExp, elm); + + attr.$observe('pattern', function(newVal) { + var oldRegexp = regexp; + + regexp = parsePatternAttr(newVal, patternExp, elm); + + if ((oldRegexp && oldRegexp.toString()) !== (regexp && regexp.toString())) { + ctrl.$validate(); + } + }); + + ctrl.$validators.pattern = function(modelValue, viewValue) { + // HTML5 pattern constraint validates the input value, so we validate the viewValue + return ctrl.$isEmpty(viewValue) || isUndefined(regexp) || regexp.test(viewValue); + }; + }; + } + + }; +}]; + +/** + * @ngdoc directive + * @name ngMaxlength + * @restrict A + * + * @param {expression} ngMaxlength AngularJS expression that must evaluate to a `Number` or `String` + * parsable into a `Number`. Used as value for the `maxlength` + * {@link ngModel.NgModelController#$validators validator}. + * + * @description + * + * ngMaxlength adds the maxlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}. + * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls. + * + * The validator sets the `maxlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} + * is longer than the integer obtained by evaluating the AngularJS expression given in the + * `ngMaxlength` attribute value. + * + *
    + * **Note:** This directive is also added when the plain `maxlength` attribute is used, with two + * differences: + *
      + *
    1. + * `ngMaxlength` does not set the `maxlength` attribute and therefore HTML5 constraint + * validation is not available. + *
    2. + *
    3. + * The `ngMaxlength` attribute must be an expression, while the `maxlength` value must be + * interpolated. + *
    4. + *
    + *
    + * + * @example + * + * + * + *
    + *
    + * + * + *
    + * + *
    + *
    + * input valid? = {{form.input.$valid}}
    + * model = {{model}} + *
    + *
    + *
    + * + var model = element(by.binding('model')); + var input = element(by.id('input')); + + it('should validate the input with the default maxlength', function() { + input.sendKeys('abcdef'); + expect(model.getText()).not.toContain('abcdef'); + + input.clear().then(function() { + input.sendKeys('abcde'); + expect(model.getText()).toContain('abcde'); + }); + }); + * + *
    + */ +var maxlengthDirective = ['$parse', function($parse) { + return { + restrict: 'A', + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + + var maxlength = attr.maxlength || $parse(attr.ngMaxlength)(scope); + var maxlengthParsed = parseLength(maxlength); + + attr.$observe('maxlength', function(value) { + if (maxlength !== value) { + maxlengthParsed = parseLength(value); + maxlength = value; + ctrl.$validate(); + } + }); + ctrl.$validators.maxlength = function(modelValue, viewValue) { + return (maxlengthParsed < 0) || ctrl.$isEmpty(viewValue) || (viewValue.length <= maxlengthParsed); + }; + } + }; +}]; + +/** + * @ngdoc directive + * @name ngMinlength + * @restrict A + * + * @param {expression} ngMinlength AngularJS expression that must evaluate to a `Number` or `String` + * parsable into a `Number`. Used as value for the `minlength` + * {@link ngModel.NgModelController#$validators validator}. + * + * @description + * + * ngMinlength adds the minlength {@link ngModel.NgModelController#$validators `validator`} to {@link ngModel `ngModel`}. + * It is most often used for text-based {@link input `input`} controls, but can also be applied to custom text-based controls. + * + * The validator sets the `minlength` error key if the {@link ngModel.NgModelController#$viewValue `ngModel.$viewValue`} + * is shorter than the integer obtained by evaluating the AngularJS expression given in the + * `ngMinlength` attribute value. + * + *
    + * **Note:** This directive is also added when the plain `minlength` attribute is used, with two + * differences: + *
      + *
    1. + * `ngMinlength` does not set the `minlength` attribute and therefore HTML5 constraint + * validation is not available. + *
    2. + *
    3. + * The `ngMinlength` value must be an expression, while the `minlength` value must be + * interpolated. + *
    4. + *
    + *
    + * + * @example + * + * + * + *
    + *
    + * + * + *
    + * + *
    + *
    + * input valid? = {{form.input.$valid}}
    + * model = {{model}} + *
    + *
    + *
    + * + var model = element(by.binding('model')); + var input = element(by.id('input')); + + it('should validate the input with the default minlength', function() { + input.sendKeys('ab'); + expect(model.getText()).not.toContain('ab'); + + input.sendKeys('abc'); + expect(model.getText()).toContain('abc'); + }); + * + *
    + */ +var minlengthDirective = ['$parse', function($parse) { + return { + restrict: 'A', + require: '?ngModel', + link: function(scope, elm, attr, ctrl) { + if (!ctrl) return; + + var minlength = attr.minlength || $parse(attr.ngMinlength)(scope); + var minlengthParsed = parseLength(minlength) || -1; + + attr.$observe('minlength', function(value) { + if (minlength !== value) { + minlengthParsed = parseLength(value) || -1; + minlength = value; + ctrl.$validate(); + } + + }); + ctrl.$validators.minlength = function(modelValue, viewValue) { + return ctrl.$isEmpty(viewValue) || viewValue.length >= minlengthParsed; + }; + } + }; +}]; + + +function parsePatternAttr(regex, patternExp, elm) { + if (!regex) return undefined; + + if (isString(regex)) { + regex = new RegExp('^' + regex + '$'); + } + + if (!regex.test) { + throw minErr('ngPattern')('noregexp', + 'Expected {0} to be a RegExp but was {1}. Element: {2}', patternExp, + regex, startingTag(elm)); + } + + return regex; +} + +function parseLength(val) { + var intVal = toInt(val); + return isNumberNaN(intVal) ? -1 : intVal; +} + +if (window.angular.bootstrap) { + // AngularJS is already loaded, so we can return here... + if (window.console) { + console.log('WARNING: Tried to load AngularJS more than once.'); + } + return; +} + +// try to bind to jquery now so that one can write jqLite(fn) +// but we will rebind on bootstrap again. +bindJQuery(); + +publishExternalAPI(angular); + +angular.module("ngLocale", [], ["$provide", function($provide) { +var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"}; +function getDecimals(n) { + n = n + ''; + var i = n.indexOf('.'); + return (i == -1) ? 0 : n.length - i - 1; +} + +function getVF(n, opt_precision) { + var v = opt_precision; + + if (undefined === v) { + v = Math.min(getDecimals(n), 3); + } + + var base = Math.pow(10, v); + var f = ((n * base) | 0) % base; + return {v: v, f: f}; +} + +$provide.value("$locale", { + "DATETIME_FORMATS": { + "AMPMS": [ + "AM", + "PM" + ], + "DAY": [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" + ], + "ERANAMES": [ + "Before Christ", + "Anno Domini" + ], + "ERAS": [ + "BC", + "AD" + ], + "FIRSTDAYOFWEEK": 6, + "MONTH": [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ], + "SHORTDAY": [ + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat" + ], + "SHORTMONTH": [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + ], + "STANDALONEMONTH": [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ], + "WEEKENDRANGE": [ + 5, + 6 + ], + "fullDate": "EEEE, MMMM d, y", + "longDate": "MMMM d, y", + "medium": "MMM d, y h:mm:ss a", + "mediumDate": "MMM d, y", + "mediumTime": "h:mm:ss a", + "short": "M/d/yy h:mm a", + "shortDate": "M/d/yy", + "shortTime": "h:mm a" + }, + "NUMBER_FORMATS": { + "CURRENCY_SYM": "$", + "DECIMAL_SEP": ".", + "GROUP_SEP": ",", + "PATTERNS": [ + { + "gSize": 3, + "lgSize": 3, + "maxFrac": 3, + "minFrac": 0, + "minInt": 1, + "negPre": "-", + "negSuf": "", + "posPre": "", + "posSuf": "" + }, + { + "gSize": 3, + "lgSize": 3, + "maxFrac": 2, + "minFrac": 2, + "minInt": 1, + "negPre": "-\u00a4", + "negSuf": "", + "posPre": "\u00a4", + "posSuf": "" + } + ] + }, + "id": "en-us", + "localeID": "en_US", + "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;} +}); +}]); + + jqLite(function() { + angularInit(window.document, bootstrap); + }); + +})(window); + +!window.angular.$$csp().noInlineStyle && window.angular.element(document.head).prepend(''); + +/***/ }), +/* 250 */ +/***/ (function(module, exports) { + +/** + * @license AngularJS v1.7.8 + * (c) 2010-2018 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular) {'use strict'; + +var ELEMENT_NODE = 1; +var COMMENT_NODE = 8; + +var ADD_CLASS_SUFFIX = '-add'; +var REMOVE_CLASS_SUFFIX = '-remove'; +var EVENT_CLASS_PREFIX = 'ng-'; +var ACTIVE_CLASS_SUFFIX = '-active'; +var PREPARE_CLASS_SUFFIX = '-prepare'; + +var NG_ANIMATE_CLASSNAME = 'ng-animate'; +var NG_ANIMATE_CHILDREN_DATA = '$$ngAnimateChildren'; + +// Detect proper transitionend/animationend event names. +var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMATIONEND_EVENT; + +// If unprefixed events are not supported but webkit-prefixed are, use the latter. +// Otherwise, just use W3C names, browsers not supporting them at all will just ignore them. +// Note: Chrome implements `window.onwebkitanimationend` and doesn't implement `window.onanimationend` +// but at the same time dispatches the `animationend` event and not `webkitAnimationEnd`. +// Register both events in case `window.onanimationend` is not supported because of that, +// do the same for `transitionend` as Safari is likely to exhibit similar behavior. +// Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit +// therefore there is no reason to test anymore for other vendor prefixes: +// http://caniuse.com/#search=transition +if ((window.ontransitionend === undefined) && (window.onwebkittransitionend !== undefined)) { + CSS_PREFIX = '-webkit-'; + TRANSITION_PROP = 'WebkitTransition'; + TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend'; +} else { + TRANSITION_PROP = 'transition'; + TRANSITIONEND_EVENT = 'transitionend'; +} + +if ((window.onanimationend === undefined) && (window.onwebkitanimationend !== undefined)) { + CSS_PREFIX = '-webkit-'; + ANIMATION_PROP = 'WebkitAnimation'; + ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend'; +} else { + ANIMATION_PROP = 'animation'; + ANIMATIONEND_EVENT = 'animationend'; +} + +var DURATION_KEY = 'Duration'; +var PROPERTY_KEY = 'Property'; +var DELAY_KEY = 'Delay'; +var TIMING_KEY = 'TimingFunction'; +var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount'; +var ANIMATION_PLAYSTATE_KEY = 'PlayState'; +var SAFE_FAST_FORWARD_DURATION_VALUE = 9999; + +var ANIMATION_DELAY_PROP = ANIMATION_PROP + DELAY_KEY; +var ANIMATION_DURATION_PROP = ANIMATION_PROP + DURATION_KEY; +var TRANSITION_DELAY_PROP = TRANSITION_PROP + DELAY_KEY; +var TRANSITION_DURATION_PROP = TRANSITION_PROP + DURATION_KEY; + +var ngMinErr = angular.$$minErr('ng'); +function assertArg(arg, name, reason) { + if (!arg) { + throw ngMinErr('areq', 'Argument \'{0}\' is {1}', (name || '?'), (reason || 'required')); + } + return arg; +} + +function mergeClasses(a,b) { + if (!a && !b) return ''; + if (!a) return b; + if (!b) return a; + if (isArray(a)) a = a.join(' '); + if (isArray(b)) b = b.join(' '); + return a + ' ' + b; +} + +function packageStyles(options) { + var styles = {}; + if (options && (options.to || options.from)) { + styles.to = options.to; + styles.from = options.from; + } + return styles; +} + +function pendClasses(classes, fix, isPrefix) { + var className = ''; + classes = isArray(classes) + ? classes + : classes && isString(classes) && classes.length + ? classes.split(/\s+/) + : []; + forEach(classes, function(klass, i) { + if (klass && klass.length > 0) { + className += (i > 0) ? ' ' : ''; + className += isPrefix ? fix + klass + : klass + fix; + } + }); + return className; +} + +function removeFromArray(arr, val) { + var index = arr.indexOf(val); + if (val >= 0) { + arr.splice(index, 1); + } +} + +function stripCommentsFromElement(element) { + if (element instanceof jqLite) { + switch (element.length) { + case 0: + return element; + + case 1: + // there is no point of stripping anything if the element + // is the only element within the jqLite wrapper. + // (it's important that we retain the element instance.) + if (element[0].nodeType === ELEMENT_NODE) { + return element; + } + break; + + default: + return jqLite(extractElementNode(element)); + } + } + + if (element.nodeType === ELEMENT_NODE) { + return jqLite(element); + } +} + +function extractElementNode(element) { + if (!element[0]) return element; + for (var i = 0; i < element.length; i++) { + var elm = element[i]; + if (elm.nodeType === ELEMENT_NODE) { + return elm; + } + } +} + +function $$addClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.addClass(elm, className); + }); +} + +function $$removeClass($$jqLite, element, className) { + forEach(element, function(elm) { + $$jqLite.removeClass(elm, className); + }); +} + +function applyAnimationClassesFactory($$jqLite) { + return function(element, options) { + if (options.addClass) { + $$addClass($$jqLite, element, options.addClass); + options.addClass = null; + } + if (options.removeClass) { + $$removeClass($$jqLite, element, options.removeClass); + options.removeClass = null; + } + }; +} + +function prepareAnimationOptions(options) { + options = options || {}; + if (!options.$$prepared) { + var domOperation = options.domOperation || noop; + options.domOperation = function() { + options.$$domOperationFired = true; + domOperation(); + domOperation = noop; + }; + options.$$prepared = true; + } + return options; +} + +function applyAnimationStyles(element, options) { + applyAnimationFromStyles(element, options); + applyAnimationToStyles(element, options); +} + +function applyAnimationFromStyles(element, options) { + if (options.from) { + element.css(options.from); + options.from = null; + } +} + +function applyAnimationToStyles(element, options) { + if (options.to) { + element.css(options.to); + options.to = null; + } +} + +function mergeAnimationDetails(element, oldAnimation, newAnimation) { + var target = oldAnimation.options || {}; + var newOptions = newAnimation.options || {}; + + var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || ''); + var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || ''); + var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove); + + if (newOptions.preparationClasses) { + target.preparationClasses = concatWithSpace(newOptions.preparationClasses, target.preparationClasses); + delete newOptions.preparationClasses; + } + + // noop is basically when there is no callback; otherwise something has been set + var realDomOperation = target.domOperation !== noop ? target.domOperation : null; + + extend(target, newOptions); + + // TODO(matsko or sreeramu): proper fix is to maintain all animation callback in array and call at last,but now only leave has the callback so no issue with this. + if (realDomOperation) { + target.domOperation = realDomOperation; + } + + if (classes.addClass) { + target.addClass = classes.addClass; + } else { + target.addClass = null; + } + + if (classes.removeClass) { + target.removeClass = classes.removeClass; + } else { + target.removeClass = null; + } + + oldAnimation.addClass = target.addClass; + oldAnimation.removeClass = target.removeClass; + + return target; +} + +function resolveElementClasses(existing, toAdd, toRemove) { + var ADD_CLASS = 1; + var REMOVE_CLASS = -1; + + var flags = {}; + existing = splitClassesToLookup(existing); + + toAdd = splitClassesToLookup(toAdd); + forEach(toAdd, function(value, key) { + flags[key] = ADD_CLASS; + }); + + toRemove = splitClassesToLookup(toRemove); + forEach(toRemove, function(value, key) { + flags[key] = flags[key] === ADD_CLASS ? null : REMOVE_CLASS; + }); + + var classes = { + addClass: '', + removeClass: '' + }; + + forEach(flags, function(val, klass) { + var prop, allow; + if (val === ADD_CLASS) { + prop = 'addClass'; + allow = !existing[klass] || existing[klass + REMOVE_CLASS_SUFFIX]; + } else if (val === REMOVE_CLASS) { + prop = 'removeClass'; + allow = existing[klass] || existing[klass + ADD_CLASS_SUFFIX]; + } + if (allow) { + if (classes[prop].length) { + classes[prop] += ' '; + } + classes[prop] += klass; + } + }); + + function splitClassesToLookup(classes) { + if (isString(classes)) { + classes = classes.split(' '); + } + + var obj = {}; + forEach(classes, function(klass) { + // sometimes the split leaves empty string values + // incase extra spaces were applied to the options + if (klass.length) { + obj[klass] = true; + } + }); + return obj; + } + + return classes; +} + +function getDomNode(element) { + return (element instanceof jqLite) ? element[0] : element; +} + +function applyGeneratedPreparationClasses($$jqLite, element, event, options) { + var classes = ''; + if (event) { + classes = pendClasses(event, EVENT_CLASS_PREFIX, true); + } + if (options.addClass) { + classes = concatWithSpace(classes, pendClasses(options.addClass, ADD_CLASS_SUFFIX)); + } + if (options.removeClass) { + classes = concatWithSpace(classes, pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX)); + } + if (classes.length) { + options.preparationClasses = classes; + element.addClass(classes); + } +} + +function clearGeneratedClasses(element, options) { + if (options.preparationClasses) { + element.removeClass(options.preparationClasses); + options.preparationClasses = null; + } + if (options.activeClasses) { + element.removeClass(options.activeClasses); + options.activeClasses = null; + } +} + +function blockKeyframeAnimations(node, applyBlock) { + var value = applyBlock ? 'paused' : ''; + var key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY; + applyInlineStyle(node, [key, value]); + return [key, value]; +} + +function applyInlineStyle(node, styleTuple) { + var prop = styleTuple[0]; + var value = styleTuple[1]; + node.style[prop] = value; +} + +function concatWithSpace(a,b) { + if (!a) return b; + if (!b) return a; + return a + ' ' + b; +} + +var helpers = { + blockTransitions: function(node, duration) { + // we use a negative delay value since it performs blocking + // yet it doesn't kill any existing transitions running on the + // same element which makes this safe for class-based animations + var value = duration ? '-' + duration + 's' : ''; + applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]); + return [TRANSITION_DELAY_PROP, value]; + } +}; + +var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) { + var queue, cancelFn; + + function scheduler(tasks) { + // we make a copy since RAFScheduler mutates the state + // of the passed in array variable and this would be difficult + // to track down on the outside code + queue = queue.concat(tasks); + nextTick(); + } + + queue = scheduler.queue = []; + + /* waitUntilQuiet does two things: + * 1. It will run the FINAL `fn` value only when an uncanceled RAF has passed through + * 2. It will delay the next wave of tasks from running until the quiet `fn` has run. + * + * The motivation here is that animation code can request more time from the scheduler + * before the next wave runs. This allows for certain DOM properties such as classes to + * be resolved in time for the next animation to run. + */ + scheduler.waitUntilQuiet = function(fn) { + if (cancelFn) cancelFn(); + + cancelFn = $$rAF(function() { + cancelFn = null; + fn(); + nextTick(); + }); + }; + + return scheduler; + + function nextTick() { + if (!queue.length) return; + + var items = queue.shift(); + for (var i = 0; i < items.length; i++) { + items[i](); + } + + if (!cancelFn) { + $$rAF(function() { + if (!cancelFn) nextTick(); + }); + } + } +}]; + +/** + * @ngdoc directive + * @name ngAnimateChildren + * @restrict AE + * @element ANY + * + * @description + * + * ngAnimateChildren allows you to specify that children of this element should animate even if any + * of the children's parents are currently animating. By default, when an element has an active `enter`, `leave`, or `move` + * (structural) animation, child elements that also have an active structural animation are not animated. + * + * Note that even if `ngAnimateChildren` is set, no child animations will run when the parent element is removed from the DOM (`leave` animation). + * + * + * @param {string} ngAnimateChildren If the value is empty, `true` or `on`, + * then child animations are allowed. If the value is `false`, child animations are not allowed. + * + * @example + * + +
    + + +
    +
    +
    + List of items: +
    Item {{item}}
    +
    +
    +
    +
    + + + .container.ng-enter, + .container.ng-leave { + transition: all ease 1.5s; + } + + .container.ng-enter, + .container.ng-leave-active { + opacity: 0; + } + + .container.ng-leave, + .container.ng-enter-active { + opacity: 1; + } + + .item { + background: firebrick; + color: #FFF; + margin-bottom: 10px; + } + + .item.ng-enter, + .item.ng-leave { + transition: transform 1.5s ease; + } + + .item.ng-enter { + transform: translateX(50px); + } + + .item.ng-enter-active { + transform: translateX(0); + } + + + angular.module('ngAnimateChildren', ['ngAnimate']) + .controller('MainController', function MainController() { + this.animateChildren = false; + this.enterElement = false; + }); + +
    + */ +var $$AnimateChildrenDirective = ['$interpolate', function($interpolate) { + return { + link: function(scope, element, attrs) { + var val = attrs.ngAnimateChildren; + if (isString(val) && val.length === 0) { //empty attribute + element.data(NG_ANIMATE_CHILDREN_DATA, true); + } else { + // Interpolate and set the value, so that it is available to + // animations that run right after compilation + setData($interpolate(val)(scope)); + attrs.$observe('ngAnimateChildren', setData); + } + + function setData(value) { + value = value === 'on' || value === 'true'; + element.data(NG_ANIMATE_CHILDREN_DATA, value); + } + } + }; +}]; + +/* exported $AnimateCssProvider */ + +var ANIMATE_TIMER_KEY = '$$animateCss'; + +/** + * @ngdoc service + * @name $animateCss + * @kind object + * + * @description + * The `$animateCss` service is a useful utility to trigger customized CSS-based transitions/keyframes + * from a JavaScript-based animation or directly from a directive. The purpose of `$animateCss` is NOT + * to side-step how `$animate` and ngAnimate work, but the goal is to allow pre-existing animations or + * directives to create more complex animations that can be purely driven using CSS code. + * + * Note that only browsers that support CSS transitions and/or keyframe animations are capable of + * rendering animations triggered via `$animateCss` (bad news for IE9 and lower). + * + * ## General Use + * Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that + * is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however, + * any automatic control over cancelling animations and/or preventing animations from being run on + * child elements will not be handled by AngularJS. For this to work as expected, please use `$animate` to + * trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger + * the CSS animation. + * + * The example below shows how we can create a folding animation on an element using `ng-if`: + * + * ```html + * + *
    + * This element will go BOOM + *
    + * + * ``` + * + * Now we create the **JavaScript animation** that will trigger the CSS transition: + * + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * return $animateCss(element, { + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * } + * } + * }]); + * ``` + * + * ## More Advanced Uses + * + * `$animateCss` is the underlying code that ngAnimate uses to power **CSS-based animations** behind the scenes. Therefore CSS hooks + * like `.ng-EVENT`, `.ng-EVENT-active`, `.ng-EVENT-stagger` are all features that can be triggered using `$animateCss` via JavaScript code. + * + * This also means that just about any combination of adding classes, removing classes, setting styles, dynamically setting a keyframe animation, + * applying a hardcoded duration or delay value, changing the animation easing or applying a stagger animation are all options that work with + * `$animateCss`. The service itself is smart enough to figure out the combination of options and examine the element styling properties in order + * to provide a working animation that will run in CSS. + * + * The example below showcases a more advanced version of the `.fold-animation` from the example above: + * + * ```js + * ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) { + * return { + * enter: function(element, doneFn) { + * var height = element[0].offsetHeight; + * return $animateCss(element, { + * addClass: 'red large-text pulse-twice', + * easing: 'ease-out', + * from: { height:'0px' }, + * to: { height:height + 'px' }, + * duration: 1 // one second + * }); + * } + * } + * }]); + * ``` + * + * Since we're adding/removing CSS classes then the CSS transition will also pick those up: + * + * ```css + * /* since a hardcoded duration value of 1 was provided in the JavaScript animation code, + * the CSS classes below will be transitioned despite them being defined as regular CSS classes */ + * .red { background:red; } + * .large-text { font-size:20px; } + * + * /* we can also use a keyframe animation and $animateCss will make it work alongside the transition */ + * .pulse-twice { + * animation: 0.5s pulse linear 2; + * -webkit-animation: 0.5s pulse linear 2; + * } + * + * @keyframes pulse { + * from { transform: scale(0.5); } + * to { transform: scale(1.5); } + * } + * + * @-webkit-keyframes pulse { + * from { -webkit-transform: scale(0.5); } + * to { -webkit-transform: scale(1.5); } + * } + * ``` + * + * Given this complex combination of CSS classes, styles and options, `$animateCss` will figure everything out and make the animation happen. + * + * ## How the Options are handled + * + * `$animateCss` is very versatile and intelligent when it comes to figuring out what configurations to apply to the element to ensure the animation + * works with the options provided. Say for example we were adding a class that contained a keyframe value and we wanted to also animate some inline + * styles using the `from` and `to` properties. + * + * ```js + * var animator = $animateCss(element, { + * from: { background:'red' }, + * to: { background:'blue' } + * }); + * animator.start(); + * ``` + * + * ```css + * .rotating-animation { + * animation:0.5s rotate linear; + * -webkit-animation:0.5s rotate linear; + * } + * + * @keyframes rotate { + * from { transform: rotate(0deg); } + * to { transform: rotate(360deg); } + * } + * + * @-webkit-keyframes rotate { + * from { -webkit-transform: rotate(0deg); } + * to { -webkit-transform: rotate(360deg); } + * } + * ``` + * + * The missing pieces here are that we do not have a transition set (within the CSS code nor within the `$animateCss` options) and the duration of the animation is + * going to be detected from what the keyframe styles on the CSS class are. In this event, `$animateCss` will automatically create an inline transition + * style matching the duration detected from the keyframe style (which is present in the CSS class that is being added) and then prepare both the transition + * and keyframe animations to run in parallel on the element. Then when the animation is underway the provided `from` and `to` CSS styles will be applied + * and spread across the transition and keyframe animation. + * + * ## What is returned + * + * `$animateCss` works in two stages: a preparation phase and an animation phase. Therefore when `$animateCss` is first called it will NOT actually + * start the animation. All that is going on here is that the element is being prepared for the animation (which means that the generated CSS classes are + * added and removed on the element). Once `$animateCss` is called it will return an object with the following properties: + * + * ```js + * var animator = $animateCss(element, { ... }); + * ``` + * + * Now what do the contents of our `animator` variable look like: + * + * ```js + * { + * // starts the animation + * start: Function, + * + * // ends (aborts) the animation + * end: Function + * } + * ``` + * + * To actually start the animation we need to run `animation.start()` which will then return a promise that we can hook into to detect when the animation ends. + * If we choose not to run the animation then we MUST run `animation.end()` to perform a cleanup on the element (since some CSS classes and styles may have been + * applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties + * and that changing them will not reconfigure the parameters of the animation. + * + * ### runner.done() vs runner.then() + * It is documented that `animation.start()` will return a promise object and this is true, however, there is also an additional method available on the + * runner called `.done(callbackFn)`. The done method works the same as `.finally(callbackFn)`, however, it does **not trigger a digest to occur**. + * Therefore, for performance reasons, it's always best to use `runner.done(callback)` instead of `runner.then()`, `runner.catch()` or `runner.finally()` + * unless you really need a digest to kick off afterwards. + * + * Keep in mind that, to make this easier, ngAnimate has tweaked the JS animations API to recognize when a runner instance is returned from $animateCss + * (so there is no need to call `runner.done(doneFn)` inside of your JavaScript animation code). + * Check the {@link ngAnimate.$animateCss#usage animation code above} to see how this works. + * + * @param {DOMElement} element the element that will be animated + * @param {object} options the animation-related options that will be applied during the animation + * + * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied + * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.) + * * `structural` - Indicates that the `ng-` prefix will be added to the event class. Setting to `false` or omitting will turn `ng-EVENT` and + * `ng-EVENT-active` in `EVENT` and `EVENT-active`. Unused if `event` is omitted. + * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both). + * * `transitionStyle` - The raw CSS transition style that will be used (e.g. `1s linear all`). + * * `keyframeStyle` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`). + * * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation. + * * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition. + * * `addClass` - A space separated list of CSS classes that will be added to the element and spread across the animation. + * * `removeClass` - A space separated list of CSS classes that will be removed from the element and spread across the animation. + * * `duration` - A number value representing the total duration of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `0` + * is provided then the animation will be skipped entirely. + * * `delay` - A number value representing the total delay of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `true` is + * used then whatever delay value is detected from the CSS classes will be mirrored on the elements styles (e.g. by setting delay true then the style value + * of the element will be `transition-delay: DETECTED_VALUE`). Using `true` is useful when you want the CSS classes and inline styles to all share the same + * CSS delay value. + * * `stagger` - A numeric time value representing the delay between successively animated elements + * ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.}) + * * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a + * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`) + * * `applyClassesEarly` - Whether or not the classes being added or removed will be used when detecting the animation. This is set by `$animate` when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. (Note that this will prevent any transitions from occurring on the classes being added and removed.) + * * `cleanupStyles` - Whether or not the provided `from` and `to` styles will be removed once + * the animation is closed. This is useful for when the styles are used purely for the sake of + * the animation and do not have a lasting visual effect on the element (e.g. a collapse and open animation). + * By default this value is set to `false`. + * + * @return {object} an object with start and end methods and details about the animation. + * + * * `start` - The method to start the animation. This will return a `Promise` when called. + * * `end` - This method will cancel the animation and remove all applied CSS classes and styles. + */ +var ONE_SECOND = 1000; + +var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3; +var CLOSING_TIME_BUFFER = 1.5; + +var DETECT_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + transitionProperty: TRANSITION_PROP + PROPERTY_KEY, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP, + animationIterationCount: ANIMATION_PROP + ANIMATION_ITERATION_COUNT_KEY +}; + +var DETECT_STAGGER_CSS_PROPERTIES = { + transitionDuration: TRANSITION_DURATION_PROP, + transitionDelay: TRANSITION_DELAY_PROP, + animationDuration: ANIMATION_DURATION_PROP, + animationDelay: ANIMATION_DELAY_PROP +}; + +function getCssKeyframeDurationStyle(duration) { + return [ANIMATION_DURATION_PROP, duration + 's']; +} + +function getCssDelayStyle(delay, isKeyframeAnimation) { + var prop = isKeyframeAnimation ? ANIMATION_DELAY_PROP : TRANSITION_DELAY_PROP; + return [prop, delay + 's']; +} + +function computeCssStyles($window, element, properties) { + var styles = Object.create(null); + var detectedStyles = $window.getComputedStyle(element) || {}; + forEach(properties, function(formalStyleName, actualStyleName) { + var val = detectedStyles[formalStyleName]; + if (val) { + var c = val.charAt(0); + + // only numerical-based values have a negative sign or digit as the first value + if (c === '-' || c === '+' || c >= 0) { + val = parseMaxTime(val); + } + + // by setting this to null in the event that the delay is not set or is set directly as 0 + // then we can still allow for negative values to be used later on and not mistake this + // value for being greater than any other negative value. + if (val === 0) { + val = null; + } + styles[actualStyleName] = val; + } + }); + + return styles; +} + +function parseMaxTime(str) { + var maxValue = 0; + var values = str.split(/\s*,\s*/); + forEach(values, function(value) { + // it's always safe to consider only second values and omit `ms` values since + // getComputedStyle will always handle the conversion for us + if (value.charAt(value.length - 1) === 's') { + value = value.substring(0, value.length - 1); + } + value = parseFloat(value) || 0; + maxValue = maxValue ? Math.max(value, maxValue) : value; + }); + return maxValue; +} + +function truthyTimingValue(val) { + return val === 0 || val != null; +} + +function getCssTransitionDurationStyle(duration, applyOnlyDuration) { + var style = TRANSITION_PROP; + var value = duration + 's'; + if (applyOnlyDuration) { + style += DURATION_KEY; + } else { + value += ' linear all'; + } + return [style, value]; +} + +// we do not reassign an already present style value since +// if we detect the style property value again we may be +// detecting styles that were added via the `from` styles. +// We make use of `isDefined` here since an empty string +// or null value (which is what getPropertyValue will return +// for a non-existing style) will still be marked as a valid +// value for the style (a falsy value implies that the style +// is to be removed at the end of the animation). If we had a simple +// "OR" statement then it would not be enough to catch that. +function registerRestorableStyles(backup, node, properties) { + forEach(properties, function(prop) { + backup[prop] = isDefined(backup[prop]) + ? backup[prop] + : node.style.getPropertyValue(prop); + }); +} + +var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animateProvider) { + + this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', '$$animateCache', + '$$forceReflow', '$sniffer', '$$rAFScheduler', '$$animateQueue', + function($window, $$jqLite, $$AnimateRunner, $timeout, $$animateCache, + $$forceReflow, $sniffer, $$rAFScheduler, $$animateQueue) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + function computeCachedCssStyles(node, className, cacheKey, allowNoDuration, properties) { + var timings = $$animateCache.get(cacheKey); + + if (!timings) { + timings = computeCssStyles($window, node, properties); + if (timings.animationIterationCount === 'infinite') { + timings.animationIterationCount = 1; + } + } + + // if a css animation has no duration we + // should mark that so that repeated addClass/removeClass calls are skipped + var hasDuration = allowNoDuration || (timings.transitionDuration > 0 || timings.animationDuration > 0); + + // we keep putting this in multiple times even though the value and the cacheKey are the same + // because we're keeping an internal tally of how many duplicate animations are detected. + $$animateCache.put(cacheKey, timings, hasDuration); + + return timings; + } + + function computeCachedCssStaggerStyles(node, className, cacheKey, properties) { + var stagger; + var staggerCacheKey = 'stagger-' + cacheKey; + + // if we have one or more existing matches of matching elements + // containing the same parent + CSS styles (which is how cacheKey works) + // then staggering is possible + if ($$animateCache.count(cacheKey) > 0) { + stagger = $$animateCache.get(staggerCacheKey); + + if (!stagger) { + var staggerClassName = pendClasses(className, '-stagger'); + + $$jqLite.addClass(node, staggerClassName); + + stagger = computeCssStyles($window, node, properties); + + // force the conversion of a null value to zero incase not set + stagger.animationDuration = Math.max(stagger.animationDuration, 0); + stagger.transitionDuration = Math.max(stagger.transitionDuration, 0); + + $$jqLite.removeClass(node, staggerClassName); + + $$animateCache.put(staggerCacheKey, stagger, true); + } + } + + return stagger || {}; + } + + var rafWaitQueue = []; + function waitUntilQuiet(callback) { + rafWaitQueue.push(callback); + $$rAFScheduler.waitUntilQuiet(function() { + $$animateCache.flush(); + + // DO NOT REMOVE THIS LINE OR REFACTOR OUT THE `pageWidth` variable. + // PLEASE EXAMINE THE `$$forceReflow` service to understand why. + var pageWidth = $$forceReflow(); + + // we use a for loop to ensure that if the queue is changed + // during this looping then it will consider new requests + for (var i = 0; i < rafWaitQueue.length; i++) { + rafWaitQueue[i](pageWidth); + } + rafWaitQueue.length = 0; + }); + } + + function computeTimings(node, className, cacheKey, allowNoDuration) { + var timings = computeCachedCssStyles(node, className, cacheKey, allowNoDuration, DETECT_CSS_PROPERTIES); + var aD = timings.animationDelay; + var tD = timings.transitionDelay; + timings.maxDelay = aD && tD + ? Math.max(aD, tD) + : (aD || tD); + timings.maxDuration = Math.max( + timings.animationDuration * timings.animationIterationCount, + timings.transitionDuration); + + return timings; + } + + return function init(element, initialOptions) { + // all of the animation functions should create + // a copy of the options data, however, if a + // parent service has already created a copy then + // we should stick to using that + var options = initialOptions || {}; + if (!options.$$prepared) { + options = prepareAnimationOptions(copy(options)); + } + + var restoreStyles = {}; + var node = getDomNode(element); + if (!node + || !node.parentNode + || !$$animateQueue.enabled()) { + return closeAndReturnNoopAnimator(); + } + + var temporaryStyles = []; + var classes = element.attr('class'); + var styles = packageStyles(options); + var animationClosed; + var animationPaused; + var animationCompleted; + var runner; + var runnerHost; + var maxDelay; + var maxDelayTime; + var maxDuration; + var maxDurationTime; + var startTime; + var events = []; + + if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) { + return closeAndReturnNoopAnimator(); + } + + var method = options.event && isArray(options.event) + ? options.event.join(' ') + : options.event; + + var isStructural = method && options.structural; + var structuralClassName = ''; + var addRemoveClassName = ''; + + if (isStructural) { + structuralClassName = pendClasses(method, EVENT_CLASS_PREFIX, true); + } else if (method) { + structuralClassName = method; + } + + if (options.addClass) { + addRemoveClassName += pendClasses(options.addClass, ADD_CLASS_SUFFIX); + } + + if (options.removeClass) { + if (addRemoveClassName.length) { + addRemoveClassName += ' '; + } + addRemoveClassName += pendClasses(options.removeClass, REMOVE_CLASS_SUFFIX); + } + + // there may be a situation where a structural animation is combined together + // with CSS classes that need to resolve before the animation is computed. + // However this means that there is no explicit CSS code to block the animation + // from happening (by setting 0s none in the class name). If this is the case + // we need to apply the classes before the first rAF so we know to continue if + // there actually is a detected transition or keyframe animation + if (options.applyClassesEarly && addRemoveClassName.length) { + applyAnimationClasses(element, options); + } + + var preparationClasses = [structuralClassName, addRemoveClassName].join(' ').trim(); + var fullClassName = classes + ' ' + preparationClasses; + var hasToStyles = styles.to && Object.keys(styles.to).length > 0; + var containsKeyframeAnimation = (options.keyframeStyle || '').length > 0; + + // there is no way we can trigger an animation if no styles and + // no classes are being applied which would then trigger a transition, + // unless there a is raw keyframe value that is applied to the element. + if (!containsKeyframeAnimation + && !hasToStyles + && !preparationClasses) { + return closeAndReturnNoopAnimator(); + } + + var stagger, cacheKey = $$animateCache.cacheKey(node, method, options.addClass, options.removeClass); + if ($$animateCache.containsCachedAnimationWithoutDuration(cacheKey)) { + preparationClasses = null; + return closeAndReturnNoopAnimator(); + } + + if (options.stagger > 0) { + var staggerVal = parseFloat(options.stagger); + stagger = { + transitionDelay: staggerVal, + animationDelay: staggerVal, + transitionDuration: 0, + animationDuration: 0 + }; + } else { + stagger = computeCachedCssStaggerStyles(node, preparationClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES); + } + + if (!options.$$skipPreparationClasses) { + $$jqLite.addClass(element, preparationClasses); + } + + var applyOnlyDuration; + + if (options.transitionStyle) { + var transitionStyle = [TRANSITION_PROP, options.transitionStyle]; + applyInlineStyle(node, transitionStyle); + temporaryStyles.push(transitionStyle); + } + + if (options.duration >= 0) { + applyOnlyDuration = node.style[TRANSITION_PROP].length > 0; + var durationStyle = getCssTransitionDurationStyle(options.duration, applyOnlyDuration); + + // we set the duration so that it will be picked up by getComputedStyle later + applyInlineStyle(node, durationStyle); + temporaryStyles.push(durationStyle); + } + + if (options.keyframeStyle) { + var keyframeStyle = [ANIMATION_PROP, options.keyframeStyle]; + applyInlineStyle(node, keyframeStyle); + temporaryStyles.push(keyframeStyle); + } + + var itemIndex = stagger + ? options.staggerIndex >= 0 + ? options.staggerIndex + : $$animateCache.count(cacheKey) + : 0; + + var isFirst = itemIndex === 0; + + // this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY + // without causing any combination of transitions to kick in. By adding a negative delay value + // it forces the setup class' transition to end immediately. We later then remove the negative + // transition delay to allow for the transition to naturally do it's thing. The beauty here is + // that if there is no transition defined then nothing will happen and this will also allow + // other transitions to be stacked on top of each other without any chopping them out. + if (isFirst && !options.skipBlocking) { + helpers.blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE); + } + + var timings = computeTimings(node, fullClassName, cacheKey, !isStructural); + var relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + var flags = {}; + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; + flags.hasTransitionAll = flags.hasTransitions && timings.transitionProperty === 'all'; + flags.applyTransitionDuration = hasToStyles && ( + (flags.hasTransitions && !flags.hasTransitionAll) + || (flags.hasAnimations && !flags.hasTransitions)); + flags.applyAnimationDuration = options.duration && flags.hasAnimations; + flags.applyTransitionDelay = truthyTimingValue(options.delay) && (flags.applyTransitionDuration || flags.hasTransitions); + flags.applyAnimationDelay = truthyTimingValue(options.delay) && flags.hasAnimations; + flags.recalculateTimingStyles = addRemoveClassName.length > 0; + + if (flags.applyTransitionDuration || flags.applyAnimationDuration) { + maxDuration = options.duration ? parseFloat(options.duration) : maxDuration; + + if (flags.applyTransitionDuration) { + flags.hasTransitions = true; + timings.transitionDuration = maxDuration; + applyOnlyDuration = node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0; + temporaryStyles.push(getCssTransitionDurationStyle(maxDuration, applyOnlyDuration)); + } + + if (flags.applyAnimationDuration) { + flags.hasAnimations = true; + timings.animationDuration = maxDuration; + temporaryStyles.push(getCssKeyframeDurationStyle(maxDuration)); + } + } + + if (maxDuration === 0 && !flags.recalculateTimingStyles) { + return closeAndReturnNoopAnimator(); + } + + var activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX); + + if (options.delay != null) { + var delayStyle; + if (typeof options.delay !== 'boolean') { + delayStyle = parseFloat(options.delay); + // number in options.delay means we have to recalculate the delay for the closing timeout + maxDelay = Math.max(delayStyle, 0); + } + + if (flags.applyTransitionDelay) { + temporaryStyles.push(getCssDelayStyle(delayStyle)); + } + + if (flags.applyAnimationDelay) { + temporaryStyles.push(getCssDelayStyle(delayStyle, true)); + } + } + + // we need to recalculate the delay value since we used a pre-emptive negative + // delay value and the delay value is required for the final event checking. This + // property will ensure that this will happen after the RAF phase has passed. + if (options.duration == null && timings.transitionDuration > 0) { + flags.recalculateTimingStyles = flags.recalculateTimingStyles || isFirst; + } + + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; + if (!options.skipBlocking) { + flags.blockTransition = timings.transitionDuration > 0; + flags.blockKeyframeAnimation = timings.animationDuration > 0 && + stagger.animationDelay > 0 && + stagger.animationDuration === 0; + } + + if (options.from) { + if (options.cleanupStyles) { + registerRestorableStyles(restoreStyles, node, Object.keys(options.from)); + } + applyAnimationFromStyles(element, options); + } + + if (flags.blockTransition || flags.blockKeyframeAnimation) { + applyBlocking(maxDuration); + } else if (!options.skipBlocking) { + helpers.blockTransitions(node, false); + } + + // TODO(matsko): for 1.5 change this code to have an animator object for better debugging + return { + $$willAnimate: true, + end: endFn, + start: function() { + if (animationClosed) return; + + runnerHost = { + end: endFn, + cancel: cancelFn, + resume: null, //this will be set during the start() phase + pause: null + }; + + runner = new $$AnimateRunner(runnerHost); + + waitUntilQuiet(start); + + // we don't have access to pause/resume the animation + // since it hasn't run yet. AnimateRunner will therefore + // set noop functions for resume and pause and they will + // later be overridden once the animation is triggered + return runner; + } + }; + + function endFn() { + close(); + } + + function cancelFn() { + close(true); + } + + function close(rejected) { + // if the promise has been called already then we shouldn't close + // the animation again + if (animationClosed || (animationCompleted && animationPaused)) return; + animationClosed = true; + animationPaused = false; + + if (preparationClasses && !options.$$skipPreparationClasses) { + $$jqLite.removeClass(element, preparationClasses); + } + + if (activeClasses) { + $$jqLite.removeClass(element, activeClasses); + } + + blockKeyframeAnimations(node, false); + helpers.blockTransitions(node, false); + + forEach(temporaryStyles, function(entry) { + // There is only one way to remove inline style properties entirely from elements. + // By using `removeProperty` this works, but we need to convert camel-cased CSS + // styles down to hyphenated values. + node.style[entry[0]] = ''; + }); + + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + + if (Object.keys(restoreStyles).length) { + forEach(restoreStyles, function(value, prop) { + if (value) { + node.style.setProperty(prop, value); + } else { + node.style.removeProperty(prop); + } + }); + } + + // the reason why we have this option is to allow a synchronous closing callback + // that is fired as SOON as the animation ends (when the CSS is removed) or if + // the animation never takes off at all. A good example is a leave animation since + // the element must be removed just after the animation is over or else the element + // will appear on screen for one animation frame causing an overbearing flicker. + if (options.onDone) { + options.onDone(); + } + + if (events && events.length) { + // Remove the transitionend / animationend listener(s) + element.off(events.join(' '), onAnimationProgress); + } + + //Cancel the fallback closing timeout and remove the timer data + var animationTimerData = element.data(ANIMATE_TIMER_KEY); + if (animationTimerData) { + $timeout.cancel(animationTimerData[0].timer); + element.removeData(ANIMATE_TIMER_KEY); + } + + // if the preparation function fails then the promise is not setup + if (runner) { + runner.complete(!rejected); + } + } + + function applyBlocking(duration) { + if (flags.blockTransition) { + helpers.blockTransitions(node, duration); + } + + if (flags.blockKeyframeAnimation) { + blockKeyframeAnimations(node, !!duration); + } + } + + function closeAndReturnNoopAnimator() { + runner = new $$AnimateRunner({ + end: endFn, + cancel: cancelFn + }); + + // should flush the cache animation + waitUntilQuiet(noop); + close(); + + return { + $$willAnimate: false, + start: function() { + return runner; + }, + end: endFn + }; + } + + function onAnimationProgress(event) { + event.stopPropagation(); + var ev = event.originalEvent || event; + + if (ev.target !== node) { + // Since TransitionEvent / AnimationEvent bubble up, + // we have to ignore events by finished child animations + return; + } + + // we now always use `Date.now()` due to the recent changes with + // event.timeStamp in Firefox, Webkit and Chrome (see #13494 for more info) + var timeStamp = ev.$manualTimeStamp || Date.now(); + + /* Firefox (or possibly just Gecko) likes to not round values up + * when a ms measurement is used for the animation */ + var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES)); + + /* $manualTimeStamp is a mocked timeStamp value which is set + * within browserTrigger(). This is only here so that tests can + * mock animations properly. Real events fallback to event.timeStamp, + * or, if they don't, then a timeStamp is automatically created for them. + * We're checking to see if the timeStamp surpasses the expected delay, + * but we're using elapsedTime instead of the timeStamp on the 2nd + * pre-condition since animationPauseds sometimes close off early */ + if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) { + // we set this flag to ensure that if the transition is paused then, when resumed, + // the animation will automatically close itself since transitions cannot be paused. + animationCompleted = true; + close(); + } + } + + function start() { + if (animationClosed) return; + if (!node.parentNode) { + close(); + return; + } + + // even though we only pause keyframe animations here the pause flag + // will still happen when transitions are used. Only the transition will + // not be paused since that is not possible. If the animation ends when + // paused then it will not complete until unpaused or cancelled. + var playPause = function(playAnimation) { + if (!animationCompleted) { + animationPaused = !playAnimation; + if (timings.animationDuration) { + var value = blockKeyframeAnimations(node, animationPaused); + if (animationPaused) { + temporaryStyles.push(value); + } else { + removeFromArray(temporaryStyles, value); + } + } + } else if (animationPaused && playAnimation) { + animationPaused = false; + close(); + } + }; + + // checking the stagger duration prevents an accidentally cascade of the CSS delay style + // being inherited from the parent. If the transition duration is zero then we can safely + // rely that the delay value is an intentional stagger delay style. + var maxStagger = itemIndex > 0 + && ((timings.transitionDuration && stagger.transitionDuration === 0) || + (timings.animationDuration && stagger.animationDuration === 0)) + && Math.max(stagger.animationDelay, stagger.transitionDelay); + if (maxStagger) { + $timeout(triggerAnimationStart, + Math.floor(maxStagger * itemIndex * ONE_SECOND), + false); + } else { + triggerAnimationStart(); + } + + // this will decorate the existing promise runner with pause/resume methods + runnerHost.resume = function() { + playPause(true); + }; + + runnerHost.pause = function() { + playPause(false); + }; + + function triggerAnimationStart() { + // just incase a stagger animation kicks in when the animation + // itself was cancelled entirely + if (animationClosed) return; + + applyBlocking(false); + + forEach(temporaryStyles, function(entry) { + var key = entry[0]; + var value = entry[1]; + node.style[key] = value; + }); + + applyAnimationClasses(element, options); + $$jqLite.addClass(element, activeClasses); + + if (flags.recalculateTimingStyles) { + fullClassName = node.getAttribute('class') + ' ' + preparationClasses; + cacheKey = $$animateCache.cacheKey(node, method, options.addClass, options.removeClass); + + timings = computeTimings(node, fullClassName, cacheKey, false); + relativeDelay = timings.maxDelay; + maxDelay = Math.max(relativeDelay, 0); + maxDuration = timings.maxDuration; + + if (maxDuration === 0) { + close(); + return; + } + + flags.hasTransitions = timings.transitionDuration > 0; + flags.hasAnimations = timings.animationDuration > 0; + } + + if (flags.applyAnimationDelay) { + relativeDelay = typeof options.delay !== 'boolean' && truthyTimingValue(options.delay) + ? parseFloat(options.delay) + : relativeDelay; + + maxDelay = Math.max(relativeDelay, 0); + timings.animationDelay = relativeDelay; + delayStyle = getCssDelayStyle(relativeDelay, true); + temporaryStyles.push(delayStyle); + node.style[delayStyle[0]] = delayStyle[1]; + } + + maxDelayTime = maxDelay * ONE_SECOND; + maxDurationTime = maxDuration * ONE_SECOND; + + if (options.easing) { + var easeProp, easeVal = options.easing; + if (flags.hasTransitions) { + easeProp = TRANSITION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } + if (flags.hasAnimations) { + easeProp = ANIMATION_PROP + TIMING_KEY; + temporaryStyles.push([easeProp, easeVal]); + node.style[easeProp] = easeVal; + } + } + + if (timings.transitionDuration) { + events.push(TRANSITIONEND_EVENT); + } + + if (timings.animationDuration) { + events.push(ANIMATIONEND_EVENT); + } + + startTime = Date.now(); + var timerTime = maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime; + var endTime = startTime + timerTime; + + var animationsData = element.data(ANIMATE_TIMER_KEY) || []; + var setupFallbackTimer = true; + if (animationsData.length) { + var currentTimerData = animationsData[0]; + setupFallbackTimer = endTime > currentTimerData.expectedEndTime; + if (setupFallbackTimer) { + $timeout.cancel(currentTimerData.timer); + } else { + animationsData.push(close); + } + } + + if (setupFallbackTimer) { + var timer = $timeout(onAnimationExpired, timerTime, false); + animationsData[0] = { + timer: timer, + expectedEndTime: endTime + }; + animationsData.push(close); + element.data(ANIMATE_TIMER_KEY, animationsData); + } + + if (events.length) { + element.on(events.join(' '), onAnimationProgress); + } + + if (options.to) { + if (options.cleanupStyles) { + registerRestorableStyles(restoreStyles, node, Object.keys(options.to)); + } + applyAnimationToStyles(element, options); + } + } + + function onAnimationExpired() { + var animationsData = element.data(ANIMATE_TIMER_KEY); + + // this will be false in the event that the element was + // removed from the DOM (via a leave animation or something + // similar) + if (animationsData) { + for (var i = 1; i < animationsData.length; i++) { + animationsData[i](); + } + element.removeData(ANIMATE_TIMER_KEY); + } + } + } + }; + }]; +}]; + +var $$AnimateCssDriverProvider = ['$$animationProvider', /** @this */ function($$animationProvider) { + $$animationProvider.drivers.push('$$animateCssDriver'); + + var NG_ANIMATE_SHIM_CLASS_NAME = 'ng-animate-shim'; + var NG_ANIMATE_ANCHOR_CLASS_NAME = 'ng-anchor'; + + var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out'; + var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in'; + + function isDocumentFragment(node) { + return node.parentNode && node.parentNode.nodeType === 11; + } + + this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$sniffer', '$$jqLite', '$document', + function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $sniffer, $$jqLite, $document) { + + // only browsers that support these properties can render animations + if (!$sniffer.animations && !$sniffer.transitions) return noop; + + var bodyNode = $document[0].body; + var rootNode = getDomNode($rootElement); + + var rootBodyElement = jqLite( + // this is to avoid using something that exists outside of the body + // we also special case the doc fragment case because our unit test code + // appends the $rootElement to the body after the app has been bootstrapped + isDocumentFragment(rootNode) || bodyNode.contains(rootNode) ? rootNode : bodyNode + ); + + return function initDriverFn(animationDetails) { + return animationDetails.from && animationDetails.to + ? prepareFromToAnchorAnimation(animationDetails.from, + animationDetails.to, + animationDetails.classes, + animationDetails.anchors) + : prepareRegularAnimation(animationDetails); + }; + + function filterCssClasses(classes) { + //remove all the `ng-` stuff + return classes.replace(/\bng-\S+\b/g, ''); + } + + function getUniqueValues(a, b) { + if (isString(a)) a = a.split(' '); + if (isString(b)) b = b.split(' '); + return a.filter(function(val) { + return b.indexOf(val) === -1; + }).join(' '); + } + + function prepareAnchoredAnimation(classes, outAnchor, inAnchor) { + var clone = jqLite(getDomNode(outAnchor).cloneNode(true)); + var startingClasses = filterCssClasses(getClassVal(clone)); + + outAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.addClass(NG_ANIMATE_SHIM_CLASS_NAME); + + clone.addClass(NG_ANIMATE_ANCHOR_CLASS_NAME); + + rootBodyElement.append(clone); + + var animatorIn, animatorOut = prepareOutAnimation(); + + // the user may not end up using the `out` animation and + // only making use of the `in` animation or vice-versa. + // In either case we should allow this and not assume the + // animation is over unless both animations are not used. + if (!animatorOut) { + animatorIn = prepareInAnimation(); + if (!animatorIn) { + return end(); + } + } + + var startingAnimator = animatorOut || animatorIn; + + return { + start: function() { + var runner; + + var currentAnimation = startingAnimator.start(); + currentAnimation.done(function() { + currentAnimation = null; + if (!animatorIn) { + animatorIn = prepareInAnimation(); + if (animatorIn) { + currentAnimation = animatorIn.start(); + currentAnimation.done(function() { + currentAnimation = null; + end(); + runner.complete(); + }); + return currentAnimation; + } + } + // in the event that there is no `in` animation + end(); + runner.complete(); + }); + + runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn + }); + + return runner; + + function endFn() { + if (currentAnimation) { + currentAnimation.end(); + } + } + } + }; + + function calculateAnchorStyles(anchor) { + var styles = {}; + + var coords = getDomNode(anchor).getBoundingClientRect(); + + // we iterate directly since safari messes up and doesn't return + // all the keys for the coords object when iterated + forEach(['width','height','top','left'], function(key) { + var value = coords[key]; + switch (key) { + case 'top': + value += bodyNode.scrollTop; + break; + case 'left': + value += bodyNode.scrollLeft; + break; + } + styles[key] = Math.floor(value) + 'px'; + }); + return styles; + } + + function prepareOutAnimation() { + var animator = $animateCss(clone, { + addClass: NG_OUT_ANCHOR_CLASS_NAME, + delay: true, + from: calculateAnchorStyles(outAnchor) + }); + + // read the comment within `prepareRegularAnimation` to understand + // why this check is necessary + return animator.$$willAnimate ? animator : null; + } + + function getClassVal(element) { + return element.attr('class') || ''; + } + + function prepareInAnimation() { + var endingClasses = filterCssClasses(getClassVal(inAnchor)); + var toAdd = getUniqueValues(endingClasses, startingClasses); + var toRemove = getUniqueValues(startingClasses, endingClasses); + + var animator = $animateCss(clone, { + to: calculateAnchorStyles(inAnchor), + addClass: NG_IN_ANCHOR_CLASS_NAME + ' ' + toAdd, + removeClass: NG_OUT_ANCHOR_CLASS_NAME + ' ' + toRemove, + delay: true + }); + + // read the comment within `prepareRegularAnimation` to understand + // why this check is necessary + return animator.$$willAnimate ? animator : null; + } + + function end() { + clone.remove(); + outAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + inAnchor.removeClass(NG_ANIMATE_SHIM_CLASS_NAME); + } + } + + function prepareFromToAnchorAnimation(from, to, classes, anchors) { + var fromAnimation = prepareRegularAnimation(from, noop); + var toAnimation = prepareRegularAnimation(to, noop); + + var anchorAnimations = []; + forEach(anchors, function(anchor) { + var outElement = anchor['out']; + var inElement = anchor['in']; + var animator = prepareAnchoredAnimation(classes, outElement, inElement); + if (animator) { + anchorAnimations.push(animator); + } + }); + + // no point in doing anything when there are no elements to animate + if (!fromAnimation && !toAnimation && anchorAnimations.length === 0) return; + + return { + start: function() { + var animationRunners = []; + + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } + + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } + + forEach(anchorAnimations, function(animation) { + animationRunners.push(animation.start()); + }); + + var runner = new $$AnimateRunner({ + end: endFn, + cancel: endFn // CSS-driven animations cannot be cancelled, only ended + }); + + $$AnimateRunner.all(animationRunners, function(status) { + runner.complete(status); + }); + + return runner; + + function endFn() { + forEach(animationRunners, function(runner) { + runner.end(); + }); + } + } + }; + } + + function prepareRegularAnimation(animationDetails) { + var element = animationDetails.element; + var options = animationDetails.options || {}; + + if (animationDetails.structural) { + options.event = animationDetails.event; + options.structural = true; + options.applyClassesEarly = true; + + // we special case the leave animation since we want to ensure that + // the element is removed as soon as the animation is over. Otherwise + // a flicker might appear or the element may not be removed at all + if (animationDetails.event === 'leave') { + options.onDone = options.domOperation; + } + } + + // We assign the preparationClasses as the actual animation event since + // the internals of $animateCss will just suffix the event token values + // with `-active` to trigger the animation. + if (options.preparationClasses) { + options.event = concatWithSpace(options.event, options.preparationClasses); + } + + var animator = $animateCss(element, options); + + // the driver lookup code inside of $$animation attempts to spawn a + // driver one by one until a driver returns a.$$willAnimate animator object. + // $animateCss will always return an object, however, it will pass in + // a flag as a hint as to whether an animation was detected or not + return animator.$$willAnimate ? animator : null; + } + }]; +}]; + +// TODO(matsko): use caching here to speed things up for detection +// TODO(matsko): add documentation +// by the time... + +var $$AnimateJsProvider = ['$animateProvider', /** @this */ function($animateProvider) { + this.$get = ['$injector', '$$AnimateRunner', '$$jqLite', + function($injector, $$AnimateRunner, $$jqLite) { + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + // $animateJs(element, 'enter'); + return function(element, event, classes, options) { + var animationClosed = false; + + // the `classes` argument is optional and if it is not used + // then the classes will be resolved from the element's className + // property as well as options.addClass/options.removeClass. + if (arguments.length === 3 && isObject(classes)) { + options = classes; + classes = null; + } + + options = prepareAnimationOptions(options); + if (!classes) { + classes = element.attr('class') || ''; + if (options.addClass) { + classes += ' ' + options.addClass; + } + if (options.removeClass) { + classes += ' ' + options.removeClass; + } + } + + var classesToAdd = options.addClass; + var classesToRemove = options.removeClass; + + // the lookupAnimations function returns a series of animation objects that are + // matched up with one or more of the CSS classes. These animation objects are + // defined via the module.animation factory function. If nothing is detected then + // we don't return anything which then makes $animation query the next driver. + var animations = lookupAnimations(classes); + var before, after; + if (animations.length) { + var afterFn, beforeFn; + if (event === 'leave') { + beforeFn = 'leave'; + afterFn = 'afterLeave'; // TODO(matsko): get rid of this + } else { + beforeFn = 'before' + event.charAt(0).toUpperCase() + event.substr(1); + afterFn = event; + } + + if (event !== 'enter' && event !== 'move') { + before = packageAnimations(element, event, options, animations, beforeFn); + } + after = packageAnimations(element, event, options, animations, afterFn); + } + + // no matching animations + if (!before && !after) return; + + function applyOptions() { + options.domOperation(); + applyAnimationClasses(element, options); + } + + function close() { + animationClosed = true; + applyOptions(); + applyAnimationStyles(element, options); + } + + var runner; + + return { + $$willAnimate: true, + end: function() { + if (runner) { + runner.end(); + } else { + close(); + runner = new $$AnimateRunner(); + runner.complete(true); + } + return runner; + }, + start: function() { + if (runner) { + return runner; + } + + runner = new $$AnimateRunner(); + var closeActiveAnimations; + var chain = []; + + if (before) { + chain.push(function(fn) { + closeActiveAnimations = before(fn); + }); + } + + if (chain.length) { + chain.push(function(fn) { + applyOptions(); + fn(true); + }); + } else { + applyOptions(); + } + + if (after) { + chain.push(function(fn) { + closeActiveAnimations = after(fn); + }); + } + + runner.setHost({ + end: function() { + endAnimations(); + }, + cancel: function() { + endAnimations(true); + } + }); + + $$AnimateRunner.chain(chain, onComplete); + return runner; + + function onComplete(success) { + close(success); + runner.complete(success); + } + + function endAnimations(cancelled) { + if (!animationClosed) { + (closeActiveAnimations || noop)(cancelled); + onComplete(cancelled); + } + } + } + }; + + function executeAnimationFn(fn, element, event, options, onDone) { + var args; + switch (event) { + case 'animate': + args = [element, options.from, options.to, onDone]; + break; + + case 'setClass': + args = [element, classesToAdd, classesToRemove, onDone]; + break; + + case 'addClass': + args = [element, classesToAdd, onDone]; + break; + + case 'removeClass': + args = [element, classesToRemove, onDone]; + break; + + default: + args = [element, onDone]; + break; + } + + args.push(options); + + var value = fn.apply(fn, args); + if (value) { + if (isFunction(value.start)) { + value = value.start(); + } + + if (value instanceof $$AnimateRunner) { + value.done(onDone); + } else if (isFunction(value)) { + // optional onEnd / onCancel callback + return value; + } + } + + return noop; + } + + function groupEventedAnimations(element, event, options, animations, fnName) { + var operations = []; + forEach(animations, function(ani) { + var animation = ani[fnName]; + if (!animation) return; + + // note that all of these animations will run in parallel + operations.push(function() { + var runner; + var endProgressCb; + + var resolved = false; + var onAnimationComplete = function(rejected) { + if (!resolved) { + resolved = true; + (endProgressCb || noop)(rejected); + runner.complete(!rejected); + } + }; + + runner = new $$AnimateRunner({ + end: function() { + onAnimationComplete(); + }, + cancel: function() { + onAnimationComplete(true); + } + }); + + endProgressCb = executeAnimationFn(animation, element, event, options, function(result) { + var cancelled = result === false; + onAnimationComplete(cancelled); + }); + + return runner; + }); + }); + + return operations; + } + + function packageAnimations(element, event, options, animations, fnName) { + var operations = groupEventedAnimations(element, event, options, animations, fnName); + if (operations.length === 0) { + var a, b; + if (fnName === 'beforeSetClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'beforeRemoveClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'beforeAddClass'); + } else if (fnName === 'setClass') { + a = groupEventedAnimations(element, 'removeClass', options, animations, 'removeClass'); + b = groupEventedAnimations(element, 'addClass', options, animations, 'addClass'); + } + + if (a) { + operations = operations.concat(a); + } + if (b) { + operations = operations.concat(b); + } + } + + if (operations.length === 0) return; + + // TODO(matsko): add documentation + return function startAnimation(callback) { + var runners = []; + if (operations.length) { + forEach(operations, function(animateFn) { + runners.push(animateFn()); + }); + } + + if (runners.length) { + $$AnimateRunner.all(runners, callback); + } else { + callback(); + } + + return function endFn(reject) { + forEach(runners, function(runner) { + if (reject) { + runner.cancel(); + } else { + runner.end(); + } + }); + }; + }; + } + }; + + function lookupAnimations(classes) { + classes = isArray(classes) ? classes : classes.split(' '); + var matches = [], flagMap = {}; + for (var i = 0; i < classes.length; i++) { + var klass = classes[i], + animationFactory = $animateProvider.$$registeredAnimations[klass]; + if (animationFactory && !flagMap[klass]) { + matches.push($injector.get(animationFactory)); + flagMap[klass] = true; + } + } + return matches; + } + }]; +}]; + +var $$AnimateJsDriverProvider = ['$$animationProvider', /** @this */ function($$animationProvider) { + $$animationProvider.drivers.push('$$animateJsDriver'); + this.$get = ['$$animateJs', '$$AnimateRunner', function($$animateJs, $$AnimateRunner) { + return function initDriverFn(animationDetails) { + if (animationDetails.from && animationDetails.to) { + var fromAnimation = prepareAnimation(animationDetails.from); + var toAnimation = prepareAnimation(animationDetails.to); + if (!fromAnimation && !toAnimation) return; + + return { + start: function() { + var animationRunners = []; + + if (fromAnimation) { + animationRunners.push(fromAnimation.start()); + } + + if (toAnimation) { + animationRunners.push(toAnimation.start()); + } + + $$AnimateRunner.all(animationRunners, done); + + var runner = new $$AnimateRunner({ + end: endFnFactory(), + cancel: endFnFactory() + }); + + return runner; + + function endFnFactory() { + return function() { + forEach(animationRunners, function(runner) { + // at this point we cannot cancel animations for groups just yet. 1.5+ + runner.end(); + }); + }; + } + + function done(status) { + runner.complete(status); + } + } + }; + } else { + return prepareAnimation(animationDetails); + } + }; + + function prepareAnimation(animationDetails) { + // TODO(matsko): make sure to check for grouped animations and delegate down to normal animations + var element = animationDetails.element; + var event = animationDetails.event; + var options = animationDetails.options; + var classes = animationDetails.classes; + return $$animateJs(element, event, classes, options); + } + }]; +}]; + +var NG_ANIMATE_ATTR_NAME = 'data-ng-animate'; +var NG_ANIMATE_PIN_DATA = '$ngAnimatePin'; +var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animateProvider) { + var PRE_DIGEST_STATE = 1; + var RUNNING_STATE = 2; + var ONE_SPACE = ' '; + + var rules = this.rules = { + skip: [], + cancel: [], + join: [] + }; + + function getEventData(options) { + return { + addClass: options.addClass, + removeClass: options.removeClass, + from: options.from, + to: options.to + }; + } + + function makeTruthyCssClassMap(classString) { + if (!classString) { + return null; + } + + var keys = classString.split(ONE_SPACE); + var map = Object.create(null); + + forEach(keys, function(key) { + map[key] = true; + }); + return map; + } + + function hasMatchingClasses(newClassString, currentClassString) { + if (newClassString && currentClassString) { + var currentClassMap = makeTruthyCssClassMap(currentClassString); + return newClassString.split(ONE_SPACE).some(function(className) { + return currentClassMap[className]; + }); + } + } + + function isAllowed(ruleType, currentAnimation, previousAnimation) { + return rules[ruleType].some(function(fn) { + return fn(currentAnimation, previousAnimation); + }); + } + + function hasAnimationClasses(animation, and) { + var a = (animation.addClass || '').length > 0; + var b = (animation.removeClass || '').length > 0; + return and ? a && b : a || b; + } + + rules.join.push(function(newAnimation, currentAnimation) { + // if the new animation is class-based then we can just tack that on + return !newAnimation.structural && hasAnimationClasses(newAnimation); + }); + + rules.skip.push(function(newAnimation, currentAnimation) { + // there is no need to animate anything if no classes are being added and + // there is no structural animation that will be triggered + return !newAnimation.structural && !hasAnimationClasses(newAnimation); + }); + + rules.skip.push(function(newAnimation, currentAnimation) { + // why should we trigger a new structural animation if the element will + // be removed from the DOM anyway? + return currentAnimation.event === 'leave' && newAnimation.structural; + }); + + rules.skip.push(function(newAnimation, currentAnimation) { + // if there is an ongoing current animation then don't even bother running the class-based animation + return currentAnimation.structural && currentAnimation.state === RUNNING_STATE && !newAnimation.structural; + }); + + rules.cancel.push(function(newAnimation, currentAnimation) { + // there can never be two structural animations running at the same time + return currentAnimation.structural && newAnimation.structural; + }); + + rules.cancel.push(function(newAnimation, currentAnimation) { + // if the previous animation is already running, but the new animation will + // be triggered, but the new animation is structural + return currentAnimation.state === RUNNING_STATE && newAnimation.structural; + }); + + rules.cancel.push(function(newAnimation, currentAnimation) { + // cancel the animation if classes added / removed in both animation cancel each other out, + // but only if the current animation isn't structural + + if (currentAnimation.structural) return false; + + var nA = newAnimation.addClass; + var nR = newAnimation.removeClass; + var cA = currentAnimation.addClass; + var cR = currentAnimation.removeClass; + + // early detection to save the global CPU shortage :) + if ((isUndefined(nA) && isUndefined(nR)) || (isUndefined(cA) && isUndefined(cR))) { + return false; + } + + return hasMatchingClasses(nA, cR) || hasMatchingClasses(nR, cA); + }); + + this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$Map', + '$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite', '$$forceReflow', + '$$isDocumentHidden', + function($$rAF, $rootScope, $rootElement, $document, $$Map, + $$animation, $$AnimateRunner, $templateRequest, $$jqLite, $$forceReflow, + $$isDocumentHidden) { + + var activeAnimationsLookup = new $$Map(); + var disabledElementsLookup = new $$Map(); + var animationsEnabled = null; + + function removeFromDisabledElementsLookup(evt) { + disabledElementsLookup.delete(evt.target); + } + + function postDigestTaskFactory() { + var postDigestCalled = false; + return function(fn) { + // we only issue a call to postDigest before + // it has first passed. This prevents any callbacks + // from not firing once the animation has completed + // since it will be out of the digest cycle. + if (postDigestCalled) { + fn(); + } else { + $rootScope.$$postDigest(function() { + postDigestCalled = true; + fn(); + }); + } + }; + } + + // Wait until all directive and route-related templates are downloaded and + // compiled. The $templateRequest.totalPendingRequests variable keeps track of + // all of the remote templates being currently downloaded. If there are no + // templates currently downloading then the watcher will still fire anyway. + var deregisterWatch = $rootScope.$watch( + function() { return $templateRequest.totalPendingRequests === 0; }, + function(isEmpty) { + if (!isEmpty) return; + deregisterWatch(); + + // Now that all templates have been downloaded, $animate will wait until + // the post digest queue is empty before enabling animations. By having two + // calls to $postDigest calls we can ensure that the flag is enabled at the + // very end of the post digest queue. Since all of the animations in $animate + // use $postDigest, it's important that the code below executes at the end. + // This basically means that the page is fully downloaded and compiled before + // any animations are triggered. + $rootScope.$$postDigest(function() { + $rootScope.$$postDigest(function() { + // we check for null directly in the event that the application already called + // .enabled() with whatever arguments that it provided it with + if (animationsEnabled === null) { + animationsEnabled = true; + } + }); + }); + } + ); + + var callbackRegistry = Object.create(null); + + // remember that the `customFilter`/`classNameFilter` are set during the + // provider/config stage therefore we can optimize here and setup helper functions + var customFilter = $animateProvider.customFilter(); + var classNameFilter = $animateProvider.classNameFilter(); + var returnTrue = function() { return true; }; + + var isAnimatableByFilter = customFilter || returnTrue; + var isAnimatableClassName = !classNameFilter ? returnTrue : function(node, options) { + var className = [node.getAttribute('class'), options.addClass, options.removeClass].join(' '); + return classNameFilter.test(className); + }; + + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + function normalizeAnimationDetails(element, animation) { + return mergeAnimationDetails(element, animation, {}); + } + + // IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259. + var contains = window.Node.prototype.contains || /** @this */ function(arg) { + // eslint-disable-next-line no-bitwise + return this === arg || !!(this.compareDocumentPosition(arg) & 16); + }; + + function findCallbacks(targetParentNode, targetNode, event) { + var matches = []; + var entries = callbackRegistry[event]; + if (entries) { + forEach(entries, function(entry) { + if (contains.call(entry.node, targetNode)) { + matches.push(entry.callback); + } else if (event === 'leave' && contains.call(entry.node, targetParentNode)) { + matches.push(entry.callback); + } + }); + } + + return matches; + } + + function filterFromRegistry(list, matchContainer, matchCallback) { + var containerNode = extractElementNode(matchContainer); + return list.filter(function(entry) { + var isMatch = entry.node === containerNode && + (!matchCallback || entry.callback === matchCallback); + return !isMatch; + }); + } + + function cleanupEventListeners(phase, node) { + if (phase === 'close' && !node.parentNode) { + // If the element is not attached to a parentNode, it has been removed by + // the domOperation, and we can safely remove the event callbacks + $animate.off(node); + } + } + + var $animate = { + on: function(event, container, callback) { + var node = extractElementNode(container); + callbackRegistry[event] = callbackRegistry[event] || []; + callbackRegistry[event].push({ + node: node, + callback: callback + }); + + // Remove the callback when the element is removed from the DOM + jqLite(container).on('$destroy', function() { + var animationDetails = activeAnimationsLookup.get(node); + + if (!animationDetails) { + // If there's an animation ongoing, the callback calling code will remove + // the event listeners. If we'd remove here, the callbacks would be removed + // before the animation ends + $animate.off(event, container, callback); + } + }); + }, + + off: function(event, container, callback) { + if (arguments.length === 1 && !isString(arguments[0])) { + container = arguments[0]; + for (var eventType in callbackRegistry) { + callbackRegistry[eventType] = filterFromRegistry(callbackRegistry[eventType], container); + } + + return; + } + + var entries = callbackRegistry[event]; + if (!entries) return; + + callbackRegistry[event] = arguments.length === 1 + ? null + : filterFromRegistry(entries, container, callback); + }, + + pin: function(element, parentElement) { + assertArg(isElement(element), 'element', 'not an element'); + assertArg(isElement(parentElement), 'parentElement', 'not an element'); + element.data(NG_ANIMATE_PIN_DATA, parentElement); + }, + + push: function(element, event, options, domOperation) { + options = options || {}; + options.domOperation = domOperation; + return queueAnimation(element, event, options); + }, + + // this method has four signatures: + // () - global getter + // (bool) - global setter + // (element) - element getter + // (element, bool) - element setter + enabled: function(element, bool) { + var argCount = arguments.length; + + if (argCount === 0) { + // () - Global getter + bool = !!animationsEnabled; + } else { + var hasElement = isElement(element); + + if (!hasElement) { + // (bool) - Global setter + bool = animationsEnabled = !!element; + } else { + var node = getDomNode(element); + + if (argCount === 1) { + // (element) - Element getter + bool = !disabledElementsLookup.get(node); + } else { + // (element, bool) - Element setter + if (!disabledElementsLookup.has(node)) { + // The element is added to the map for the first time. + // Create a listener to remove it on `$destroy` (to avoid memory leak). + jqLite(element).on('$destroy', removeFromDisabledElementsLookup); + } + disabledElementsLookup.set(node, !bool); + } + } + } + + return bool; + } + }; + + return $animate; + + function queueAnimation(originalElement, event, initialOptions) { + // we always make a copy of the options since + // there should never be any side effects on + // the input data when running `$animateCss`. + var options = copy(initialOptions); + + var element = stripCommentsFromElement(originalElement); + var node = getDomNode(element); + var parentNode = node && node.parentNode; + + options = prepareAnimationOptions(options); + + // we create a fake runner with a working promise. + // These methods will become available after the digest has passed + var runner = new $$AnimateRunner(); + + // this is used to trigger callbacks in postDigest mode + var runInNextPostDigestOrNow = postDigestTaskFactory(); + + if (isArray(options.addClass)) { + options.addClass = options.addClass.join(' '); + } + + if (options.addClass && !isString(options.addClass)) { + options.addClass = null; + } + + if (isArray(options.removeClass)) { + options.removeClass = options.removeClass.join(' '); + } + + if (options.removeClass && !isString(options.removeClass)) { + options.removeClass = null; + } + + if (options.from && !isObject(options.from)) { + options.from = null; + } + + if (options.to && !isObject(options.to)) { + options.to = null; + } + + // If animations are hard-disabled for the whole application there is no need to continue. + // There are also situations where a directive issues an animation for a jqLite wrapper that + // contains only comment nodes. In this case, there is no way we can perform an animation. + if (!animationsEnabled || + !node || + !isAnimatableByFilter(node, event, initialOptions) || + !isAnimatableClassName(node, options)) { + close(); + return runner; + } + + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + var documentHidden = $$isDocumentHidden(); + + // This is a hard disable of all animations the element itself, therefore there is no need to + // continue further past this point if not enabled + // Animations are also disabled if the document is currently hidden (page is not visible + // to the user), because browsers slow down or do not flush calls to requestAnimationFrame + var skipAnimations = documentHidden || disabledElementsLookup.get(node); + var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {}; + var hasExistingAnimation = !!existingAnimation.state; + + // there is no point in traversing the same collection of parent ancestors if a followup + // animation will be run on the same element that already did all that checking work + if (!skipAnimations && (!hasExistingAnimation || existingAnimation.state !== PRE_DIGEST_STATE)) { + skipAnimations = !areAnimationsAllowed(node, parentNode, event); + } + + if (skipAnimations) { + // Callbacks should fire even if the document is hidden (regression fix for issue #14120) + if (documentHidden) notifyProgress(runner, event, 'start', getEventData(options)); + close(); + if (documentHidden) notifyProgress(runner, event, 'close', getEventData(options)); + return runner; + } + + if (isStructural) { + closeChildAnimations(node); + } + + var newAnimation = { + structural: isStructural, + element: element, + event: event, + addClass: options.addClass, + removeClass: options.removeClass, + close: close, + options: options, + runner: runner + }; + + if (hasExistingAnimation) { + var skipAnimationFlag = isAllowed('skip', newAnimation, existingAnimation); + if (skipAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + close(); + return runner; + } else { + mergeAnimationDetails(element, existingAnimation, newAnimation); + return existingAnimation.runner; + } + } + var cancelAnimationFlag = isAllowed('cancel', newAnimation, existingAnimation); + if (cancelAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + // this will end the animation right away and it is safe + // to do so since the animation is already running and the + // runner callback code will run in async + existingAnimation.runner.end(); + } else if (existingAnimation.structural) { + // this means that the animation is queued into a digest, but + // hasn't started yet. Therefore it is safe to run the close + // method which will call the runner methods in async. + existingAnimation.close(); + } else { + // this will merge the new animation options into existing animation options + mergeAnimationDetails(element, existingAnimation, newAnimation); + + return existingAnimation.runner; + } + } else { + // a joined animation means that this animation will take over the existing one + // so an example would involve a leave animation taking over an enter. Then when + // the postDigest kicks in the enter will be ignored. + var joinAnimationFlag = isAllowed('join', newAnimation, existingAnimation); + if (joinAnimationFlag) { + if (existingAnimation.state === RUNNING_STATE) { + normalizeAnimationDetails(element, newAnimation); + } else { + applyGeneratedPreparationClasses($$jqLite, element, isStructural ? event : null, options); + + event = newAnimation.event = existingAnimation.event; + options = mergeAnimationDetails(element, existingAnimation, newAnimation); + + //we return the same runner since only the option values of this animation will + //be fed into the `existingAnimation`. + return existingAnimation.runner; + } + } + } + } else { + // normalization in this case means that it removes redundant CSS classes that + // already exist (addClass) or do not exist (removeClass) on the element + normalizeAnimationDetails(element, newAnimation); + } + + // when the options are merged and cleaned up we may end up not having to do + // an animation at all, therefore we should check this before issuing a post + // digest callback. Structural animations will always run no matter what. + var isValidAnimation = newAnimation.structural; + if (!isValidAnimation) { + // animate (from/to) can be quickly checked first, otherwise we check if any classes are present + isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0) + || hasAnimationClasses(newAnimation); + } + + if (!isValidAnimation) { + close(); + clearElementAnimationState(node); + return runner; + } + + // the counter keeps track of cancelled animations + var counter = (existingAnimation.counter || 0) + 1; + newAnimation.counter = counter; + + markElementAnimationState(node, PRE_DIGEST_STATE, newAnimation); + + $rootScope.$$postDigest(function() { + // It is possible that the DOM nodes inside `originalElement` have been replaced. This can + // happen if the animated element is a transcluded clone and also has a `templateUrl` + // directive on it. Therefore, we must recreate `element` in order to interact with the + // actual DOM nodes. + // Note: We still need to use the old `node` for certain things, such as looking up in + // HashMaps where it was used as the key. + + element = stripCommentsFromElement(originalElement); + + var animationDetails = activeAnimationsLookup.get(node); + var animationCancelled = !animationDetails; + animationDetails = animationDetails || {}; + + // if addClass/removeClass is called before something like enter then the + // registered parent element may not be present. The code below will ensure + // that a final value for parent element is obtained + var parentElement = element.parent() || []; + + // animate/structural/class-based animations all have requirements. Otherwise there + // is no point in performing an animation. The parent node must also be set. + var isValidAnimation = parentElement.length > 0 + && (animationDetails.event === 'animate' + || animationDetails.structural + || hasAnimationClasses(animationDetails)); + + // this means that the previous animation was cancelled + // even if the follow-up animation is the same event + if (animationCancelled || animationDetails.counter !== counter || !isValidAnimation) { + // if another animation did not take over then we need + // to make sure that the domOperation and options are + // handled accordingly + if (animationCancelled) { + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + } + + // if the event changed from something like enter to leave then we do + // it, otherwise if it's the same then the end result will be the same too + if (animationCancelled || (isStructural && animationDetails.event !== event)) { + options.domOperation(); + runner.end(); + } + + // in the event that the element animation was not cancelled or a follow-up animation + // isn't allowed to animate from here then we need to clear the state of the element + // so that any future animations won't read the expired animation data. + if (!isValidAnimation) { + clearElementAnimationState(node); + } + + return; + } + + // this combined multiple class to addClass / removeClass into a setClass event + // so long as a structural event did not take over the animation + event = !animationDetails.structural && hasAnimationClasses(animationDetails, true) + ? 'setClass' + : animationDetails.event; + + markElementAnimationState(node, RUNNING_STATE); + var realRunner = $$animation(element, event, animationDetails.options); + + // this will update the runner's flow-control events based on + // the `realRunner` object. + runner.setHost(realRunner); + notifyProgress(runner, event, 'start', getEventData(options)); + + realRunner.done(function(status) { + close(!status); + var animationDetails = activeAnimationsLookup.get(node); + if (animationDetails && animationDetails.counter === counter) { + clearElementAnimationState(node); + } + notifyProgress(runner, event, 'close', getEventData(options)); + }); + }); + + return runner; + + function notifyProgress(runner, event, phase, data) { + runInNextPostDigestOrNow(function() { + var callbacks = findCallbacks(parentNode, node, event); + if (callbacks.length) { + // do not optimize this call here to RAF because + // we don't know how heavy the callback code here will + // be and if this code is buffered then this can + // lead to a performance regression. + $$rAF(function() { + forEach(callbacks, function(callback) { + callback(element, phase, data); + }); + cleanupEventListeners(phase, node); + }); + } else { + cleanupEventListeners(phase, node); + } + }); + runner.progress(event, phase, data); + } + + function close(reject) { + clearGeneratedClasses(element, options); + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + runner.complete(!reject); + } + } + + function closeChildAnimations(node) { + var children = node.querySelectorAll('[' + NG_ANIMATE_ATTR_NAME + ']'); + forEach(children, function(child) { + var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME), 10); + var animationDetails = activeAnimationsLookup.get(child); + if (animationDetails) { + switch (state) { + case RUNNING_STATE: + animationDetails.runner.end(); + /* falls through */ + case PRE_DIGEST_STATE: + activeAnimationsLookup.delete(child); + break; + } + } + }); + } + + function clearElementAnimationState(node) { + node.removeAttribute(NG_ANIMATE_ATTR_NAME); + activeAnimationsLookup.delete(node); + } + + /** + * This fn returns false if any of the following is true: + * a) animations on any parent element are disabled, and animations on the element aren't explicitly allowed + * b) a parent element has an ongoing structural animation, and animateChildren is false + * c) the element is not a child of the body + * d) the element is not a child of the $rootElement + */ + function areAnimationsAllowed(node, parentNode, event) { + var bodyNode = $document[0].body; + var rootNode = getDomNode($rootElement); + + var bodyNodeDetected = (node === bodyNode) || node.nodeName === 'HTML'; + var rootNodeDetected = (node === rootNode); + var parentAnimationDetected = false; + var elementDisabled = disabledElementsLookup.get(node); + var animateChildren; + + var parentHost = jqLite.data(node, NG_ANIMATE_PIN_DATA); + if (parentHost) { + parentNode = getDomNode(parentHost); + } + + while (parentNode) { + if (!rootNodeDetected) { + // AngularJS doesn't want to attempt to animate elements outside of the application + // therefore we need to ensure that the rootElement is an ancestor of the current element + rootNodeDetected = (parentNode === rootNode); + } + + if (parentNode.nodeType !== ELEMENT_NODE) { + // no point in inspecting the #document element + break; + } + + var details = activeAnimationsLookup.get(parentNode) || {}; + // either an enter, leave or move animation will commence + // therefore we can't allow any animations to take place + // but if a parent animation is class-based then that's ok + if (!parentAnimationDetected) { + var parentNodeDisabled = disabledElementsLookup.get(parentNode); + + if (parentNodeDisabled === true && elementDisabled !== false) { + // disable animations if the user hasn't explicitly enabled animations on the + // current element + elementDisabled = true; + // element is disabled via parent element, no need to check anything else + break; + } else if (parentNodeDisabled === false) { + elementDisabled = false; + } + parentAnimationDetected = details.structural; + } + + if (isUndefined(animateChildren) || animateChildren === true) { + var value = jqLite.data(parentNode, NG_ANIMATE_CHILDREN_DATA); + if (isDefined(value)) { + animateChildren = value; + } + } + + // there is no need to continue traversing at this point + if (parentAnimationDetected && animateChildren === false) break; + + if (!bodyNodeDetected) { + // we also need to ensure that the element is or will be a part of the body element + // otherwise it is pointless to even issue an animation to be rendered + bodyNodeDetected = (parentNode === bodyNode); + } + + if (bodyNodeDetected && rootNodeDetected) { + // If both body and root have been found, any other checks are pointless, + // as no animation data should live outside the application + break; + } + + if (!rootNodeDetected) { + // If `rootNode` is not detected, check if `parentNode` is pinned to another element + parentHost = jqLite.data(parentNode, NG_ANIMATE_PIN_DATA); + if (parentHost) { + // The pin target element becomes the next parent element + parentNode = getDomNode(parentHost); + continue; + } + } + + parentNode = parentNode.parentNode; + } + + var allowAnimation = (!parentAnimationDetected || animateChildren) && elementDisabled !== true; + return allowAnimation && rootNodeDetected && bodyNodeDetected; + } + + function markElementAnimationState(node, state, details) { + details = details || {}; + details.state = state; + + node.setAttribute(NG_ANIMATE_ATTR_NAME, state); + + var oldValue = activeAnimationsLookup.get(node); + var newValue = oldValue + ? extend(oldValue, details) + : details; + activeAnimationsLookup.set(node, newValue); + } + }]; +}]; + +/** @this */ +var $$AnimateCacheProvider = function() { + + var KEY = '$$ngAnimateParentKey'; + var parentCounter = 0; + var cache = Object.create(null); + + this.$get = [function() { + return { + cacheKey: function(node, method, addClass, removeClass) { + var parentNode = node.parentNode; + var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter); + var parts = [parentID, method, node.getAttribute('class')]; + if (addClass) { + parts.push(addClass); + } + if (removeClass) { + parts.push(removeClass); + } + return parts.join(' '); + }, + + containsCachedAnimationWithoutDuration: function(key) { + var entry = cache[key]; + + // nothing cached, so go ahead and animate + // otherwise it should be a valid animation + return (entry && !entry.isValid) || false; + }, + + flush: function() { + cache = Object.create(null); + }, + + count: function(key) { + var entry = cache[key]; + return entry ? entry.total : 0; + }, + + get: function(key) { + var entry = cache[key]; + return entry && entry.value; + }, + + put: function(key, value, isValid) { + if (!cache[key]) { + cache[key] = { total: 1, value: value, isValid: isValid }; + } else { + cache[key].total++; + cache[key].value = value; + } + } + }; + }]; +}; + +/* exported $$AnimationProvider */ + +var $$AnimationProvider = ['$animateProvider', /** @this */ function($animateProvider) { + var NG_ANIMATE_REF_ATTR = 'ng-animate-ref'; + + var drivers = this.drivers = []; + + var RUNNER_STORAGE_KEY = '$$animationRunner'; + var PREPARE_CLASSES_KEY = '$$animatePrepareClasses'; + + function setRunner(element, runner) { + element.data(RUNNER_STORAGE_KEY, runner); + } + + function removeRunner(element) { + element.removeData(RUNNER_STORAGE_KEY); + } + + function getRunner(element) { + return element.data(RUNNER_STORAGE_KEY); + } + + this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$Map', '$$rAFScheduler', '$$animateCache', + function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$Map, $$rAFScheduler, $$animateCache) { + + var animationQueue = []; + var applyAnimationClasses = applyAnimationClassesFactory($$jqLite); + + function sortAnimations(animations) { + var tree = { children: [] }; + var i, lookup = new $$Map(); + + // this is done first beforehand so that the map + // is filled with a list of the elements that will be animated + for (i = 0; i < animations.length; i++) { + var animation = animations[i]; + lookup.set(animation.domNode, animations[i] = { + domNode: animation.domNode, + element: animation.element, + fn: animation.fn, + children: [] + }); + } + + for (i = 0; i < animations.length; i++) { + processNode(animations[i]); + } + + return flatten(tree); + + function processNode(entry) { + if (entry.processed) return entry; + entry.processed = true; + + var elementNode = entry.domNode; + var parentNode = elementNode.parentNode; + lookup.set(elementNode, entry); + + var parentEntry; + while (parentNode) { + parentEntry = lookup.get(parentNode); + if (parentEntry) { + if (!parentEntry.processed) { + parentEntry = processNode(parentEntry); + } + break; + } + parentNode = parentNode.parentNode; + } + + (parentEntry || tree).children.push(entry); + return entry; + } + + function flatten(tree) { + var result = []; + var queue = []; + var i; + + for (i = 0; i < tree.children.length; i++) { + queue.push(tree.children[i]); + } + + var remainingLevelEntries = queue.length; + var nextLevelEntries = 0; + var row = []; + + for (i = 0; i < queue.length; i++) { + var entry = queue[i]; + if (remainingLevelEntries <= 0) { + remainingLevelEntries = nextLevelEntries; + nextLevelEntries = 0; + result.push(row); + row = []; + } + row.push(entry); + entry.children.forEach(function(childEntry) { + nextLevelEntries++; + queue.push(childEntry); + }); + remainingLevelEntries--; + } + + if (row.length) { + result.push(row); + } + + return result; + } + } + + // TODO(matsko): document the signature in a better way + return function(element, event, options) { + options = prepareAnimationOptions(options); + var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0; + + // there is no animation at the current moment, however + // these runner methods will get later updated with the + // methods leading into the driver's end/cancel methods + // for now they just stop the animation from starting + var runner = new $$AnimateRunner({ + end: function() { close(); }, + cancel: function() { close(true); } + }); + + if (!drivers.length) { + close(); + return runner; + } + + var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass)); + var tempClasses = options.tempClasses; + if (tempClasses) { + classes += ' ' + tempClasses; + options.tempClasses = null; + } + + if (isStructural) { + element.data(PREPARE_CLASSES_KEY, 'ng-' + event + PREPARE_CLASS_SUFFIX); + } + + setRunner(element, runner); + + animationQueue.push({ + // this data is used by the postDigest code and passed into + // the driver step function + element: element, + classes: classes, + event: event, + structural: isStructural, + options: options, + beforeStart: beforeStart, + close: close + }); + + element.on('$destroy', handleDestroyedElement); + + // we only want there to be one function called within the post digest + // block. This way we can group animations for all the animations that + // were apart of the same postDigest flush call. + if (animationQueue.length > 1) return runner; + + $rootScope.$$postDigest(function() { + var animations = []; + forEach(animationQueue, function(entry) { + // the element was destroyed early on which removed the runner + // form its storage. This means we can't animate this element + // at all and it already has been closed due to destruction. + if (getRunner(entry.element)) { + animations.push(entry); + } else { + entry.close(); + } + }); + + // now any future animations will be in another postDigest + animationQueue.length = 0; + + var groupedAnimations = groupAnimations(animations); + var toBeSortedAnimations = []; + + forEach(groupedAnimations, function(animationEntry) { + var element = animationEntry.from ? animationEntry.from.element : animationEntry.element; + var extraClasses = options.addClass; + + extraClasses = (extraClasses ? (extraClasses + ' ') : '') + NG_ANIMATE_CLASSNAME; + var cacheKey = $$animateCache.cacheKey(element[0], animationEntry.event, extraClasses, options.removeClass); + + toBeSortedAnimations.push({ + element: element, + domNode: getDomNode(element), + fn: function triggerAnimationStart() { + var startAnimationFn, closeFn = animationEntry.close; + + // in the event that we've cached the animation status for this element + // and it's in fact an invalid animation (something that has duration = 0) + // then we should skip all the heavy work from here on + if ($$animateCache.containsCachedAnimationWithoutDuration(cacheKey)) { + closeFn(); + return; + } + + // it's important that we apply the `ng-animate` CSS class and the + // temporary classes before we do any driver invoking since these + // CSS classes may be required for proper CSS detection. + animationEntry.beforeStart(); + + // in the event that the element was removed before the digest runs or + // during the RAF sequencing then we should not trigger the animation. + var targetElement = animationEntry.anchors + ? (animationEntry.from.element || animationEntry.to.element) + : animationEntry.element; + + if (getRunner(targetElement)) { + var operation = invokeFirstDriver(animationEntry); + if (operation) { + startAnimationFn = operation.start; + } + } + + if (!startAnimationFn) { + closeFn(); + } else { + var animationRunner = startAnimationFn(); + animationRunner.done(function(status) { + closeFn(!status); + }); + updateAnimationRunners(animationEntry, animationRunner); + } + } + }); + }); + + // we need to sort each of the animations in order of parent to child + // relationships. This ensures that the child classes are applied at the + // right time. + var finalAnimations = sortAnimations(toBeSortedAnimations); + for (var i = 0; i < finalAnimations.length; i++) { + var innerArray = finalAnimations[i]; + for (var j = 0; j < innerArray.length; j++) { + var entry = innerArray[j]; + var element = entry.element; + + // the RAFScheduler code only uses functions + finalAnimations[i][j] = entry.fn; + + // the first row of elements shouldn't have a prepare-class added to them + // since the elements are at the top of the animation hierarchy and they + // will be applied without a RAF having to pass... + if (i === 0) { + element.removeData(PREPARE_CLASSES_KEY); + continue; + } + + var prepareClassName = element.data(PREPARE_CLASSES_KEY); + if (prepareClassName) { + $$jqLite.addClass(element, prepareClassName); + } + } + } + + $$rAFScheduler(finalAnimations); + }); + + return runner; + + // TODO(matsko): change to reference nodes + function getAnchorNodes(node) { + var SELECTOR = '[' + NG_ANIMATE_REF_ATTR + ']'; + var items = node.hasAttribute(NG_ANIMATE_REF_ATTR) + ? [node] + : node.querySelectorAll(SELECTOR); + var anchors = []; + forEach(items, function(node) { + var attr = node.getAttribute(NG_ANIMATE_REF_ATTR); + if (attr && attr.length) { + anchors.push(node); + } + }); + return anchors; + } + + function groupAnimations(animations) { + var preparedAnimations = []; + var refLookup = {}; + forEach(animations, function(animation, index) { + var element = animation.element; + var node = getDomNode(element); + var event = animation.event; + var enterOrMove = ['enter', 'move'].indexOf(event) >= 0; + var anchorNodes = animation.structural ? getAnchorNodes(node) : []; + + if (anchorNodes.length) { + var direction = enterOrMove ? 'to' : 'from'; + + forEach(anchorNodes, function(anchor) { + var key = anchor.getAttribute(NG_ANIMATE_REF_ATTR); + refLookup[key] = refLookup[key] || {}; + refLookup[key][direction] = { + animationID: index, + element: jqLite(anchor) + }; + }); + } else { + preparedAnimations.push(animation); + } + }); + + var usedIndicesLookup = {}; + var anchorGroups = {}; + forEach(refLookup, function(operations, key) { + var from = operations.from; + var to = operations.to; + + if (!from || !to) { + // only one of these is set therefore we can't have an + // anchor animation since all three pieces are required + var index = from ? from.animationID : to.animationID; + var indexKey = index.toString(); + if (!usedIndicesLookup[indexKey]) { + usedIndicesLookup[indexKey] = true; + preparedAnimations.push(animations[index]); + } + return; + } + + var fromAnimation = animations[from.animationID]; + var toAnimation = animations[to.animationID]; + var lookupKey = from.animationID.toString(); + if (!anchorGroups[lookupKey]) { + var group = anchorGroups[lookupKey] = { + structural: true, + beforeStart: function() { + fromAnimation.beforeStart(); + toAnimation.beforeStart(); + }, + close: function() { + fromAnimation.close(); + toAnimation.close(); + }, + classes: cssClassesIntersection(fromAnimation.classes, toAnimation.classes), + from: fromAnimation, + to: toAnimation, + anchors: [] // TODO(matsko): change to reference nodes + }; + + // the anchor animations require that the from and to elements both have at least + // one shared CSS class which effectively marries the two elements together to use + // the same animation driver and to properly sequence the anchor animation. + if (group.classes.length) { + preparedAnimations.push(group); + } else { + preparedAnimations.push(fromAnimation); + preparedAnimations.push(toAnimation); + } + } + + anchorGroups[lookupKey].anchors.push({ + 'out': from.element, 'in': to.element + }); + }); + + return preparedAnimations; + } + + function cssClassesIntersection(a,b) { + a = a.split(' '); + b = b.split(' '); + var matches = []; + + for (var i = 0; i < a.length; i++) { + var aa = a[i]; + if (aa.substring(0,3) === 'ng-') continue; + + for (var j = 0; j < b.length; j++) { + if (aa === b[j]) { + matches.push(aa); + break; + } + } + } + + return matches.join(' '); + } + + function invokeFirstDriver(animationDetails) { + // we loop in reverse order since the more general drivers (like CSS and JS) + // may attempt more elements, but custom drivers are more particular + for (var i = drivers.length - 1; i >= 0; i--) { + var driverName = drivers[i]; + var factory = $injector.get(driverName); + var driver = factory(animationDetails); + if (driver) { + return driver; + } + } + } + + function beforeStart() { + tempClasses = (tempClasses ? (tempClasses + ' ') : '') + NG_ANIMATE_CLASSNAME; + $$jqLite.addClass(element, tempClasses); + + var prepareClassName = element.data(PREPARE_CLASSES_KEY); + if (prepareClassName) { + $$jqLite.removeClass(element, prepareClassName); + prepareClassName = null; + } + } + + function updateAnimationRunners(animation, newRunner) { + if (animation.from && animation.to) { + update(animation.from.element); + update(animation.to.element); + } else { + update(animation.element); + } + + function update(element) { + var runner = getRunner(element); + if (runner) runner.setHost(newRunner); + } + } + + function handleDestroyedElement() { + var runner = getRunner(element); + if (runner && (event !== 'leave' || !options.$$domOperationFired)) { + runner.end(); + } + } + + function close(rejected) { + element.off('$destroy', handleDestroyedElement); + removeRunner(element); + + applyAnimationClasses(element, options); + applyAnimationStyles(element, options); + options.domOperation(); + + if (tempClasses) { + $$jqLite.removeClass(element, tempClasses); + } + + runner.complete(!rejected); + } + }; + }]; +}]; + +/** + * @ngdoc directive + * @name ngAnimateSwap + * @restrict A + * @scope + * + * @description + * + * ngAnimateSwap is a animation-oriented directive that allows for the container to + * be removed and entered in whenever the associated expression changes. A + * common usecase for this directive is a rotating banner or slider component which + * contains one image being present at a time. When the active image changes + * then the old image will perform a `leave` animation and the new element + * will be inserted via an `enter` animation. + * + * @animations + * | Animation | Occurs | + * |----------------------------------|--------------------------------------| + * | {@link ng.$animate#enter enter} | when the new element is inserted to the DOM | + * | {@link ng.$animate#leave leave} | when the old element is removed from the DOM | + * + * @example + * + * + *
    + *
    + * {{ number }} + *
    + *
    + *
    + * + * angular.module('ngAnimateSwapExample', ['ngAnimate']) + * .controller('AppCtrl', ['$scope', '$interval', function($scope, $interval) { + * $scope.number = 0; + * $interval(function() { + * $scope.number++; + * }, 1000); + * + * var colors = ['red','blue','green','yellow','orange']; + * $scope.colorClass = function(number) { + * return colors[number % colors.length]; + * }; + * }]); + * + * + * .container { + * height:250px; + * width:250px; + * position:relative; + * overflow:hidden; + * border:2px solid black; + * } + * .container .cell { + * font-size:150px; + * text-align:center; + * line-height:250px; + * position:absolute; + * top:0; + * left:0; + * right:0; + * border-bottom:2px solid black; + * } + * .swap-animation.ng-enter, .swap-animation.ng-leave { + * transition:0.5s linear all; + * } + * .swap-animation.ng-enter { + * top:-250px; + * } + * .swap-animation.ng-enter-active { + * top:0px; + * } + * .swap-animation.ng-leave { + * top:0px; + * } + * .swap-animation.ng-leave-active { + * top:250px; + * } + * .red { background:red; } + * .green { background:green; } + * .blue { background:blue; } + * .yellow { background:yellow; } + * .orange { background:orange; } + * + *
    + */ +var ngAnimateSwapDirective = ['$animate', function($animate) { + return { + restrict: 'A', + transclude: 'element', + terminal: true, + priority: 550, // We use 550 here to ensure that the directive is caught before others, + // but after `ngIf` (at priority 600). + link: function(scope, $element, attrs, ctrl, $transclude) { + var previousElement, previousScope; + scope.$watchCollection(attrs.ngAnimateSwap || attrs['for'], function(value) { + if (previousElement) { + $animate.leave(previousElement); + } + if (previousScope) { + previousScope.$destroy(); + previousScope = null; + } + if (value || value === 0) { + $transclude(function(clone, childScope) { + previousElement = clone; + previousScope = childScope; + $animate.enter(clone, null, $element); + }); + } + }); + } + }; +}]; + +/** + * @ngdoc module + * @name ngAnimate + * @description + * + * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via + * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` the animation hooks are enabled for an AngularJS app. + * + * ## Usage + * Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based + * using CSS (by using matching CSS selectors/styles) and the latter triggers animations that are registered via `module.animation()`. For + * both CSS and JS animations the sole requirement is to have a matching `CSS class` that exists both in the registered animation and within + * the HTML element that the animation will be triggered on. + * + * ## Directive Support + * The following directives are "animation aware": + * + * | Directive | Supported Animations | + * |-------------------------------------------------------------------------------|---------------------------------------------------------------------------| + * | {@link ng.directive:form#animations form / ngForm} | add and remove ({@link ng.directive:form#css-classes various classes}) | + * | {@link ngAnimate.directive:ngAnimateSwap#animations ngAnimateSwap} | enter and leave | + * | {@link ng.directive:ngClass#animations ngClass / {{class}​}} | add and remove | + * | {@link ng.directive:ngClassEven#animations ngClassEven} | add and remove | + * | {@link ng.directive:ngClassOdd#animations ngClassOdd} | add and remove | + * | {@link ng.directive:ngHide#animations ngHide} | add and remove (the `ng-hide` class) | + * | {@link ng.directive:ngIf#animations ngIf} | enter and leave | + * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | + * | {@link module:ngMessages#animations ngMessage / ngMessageExp} | enter and leave | + * | {@link module:ngMessages#animations ngMessages} | add and remove (the `ng-active`/`ng-inactive` classes) | + * | {@link ng.directive:ngModel#animations ngModel} | add and remove ({@link ng.directive:ngModel#css-classes various classes}) | + * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave, and move | + * | {@link ng.directive:ngShow#animations ngShow} | add and remove (the `ng-hide` class) | + * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | + * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave | + * + * (More information can be found by visiting the documentation associated with each directive.) + * + * For a full breakdown of the steps involved during each animation event, refer to the + * {@link ng.$animate `$animate` API docs}. + * + * ## CSS-based Animations + * + * CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML + * and CSS code we can create an animation that will be picked up by AngularJS when an underlying directive performs an operation. + * + * The example below shows how an `enter` animation can be made possible on an element using `ng-if`: + * + * ```html + *
    + * Fade me in out + *
    + * + * + * ``` + * + * Notice the CSS class **fade**? We can now create the CSS transition code that references this class: + * + * ```css + * /* The starting CSS styles for the enter animation */ + * .fade.ng-enter { + * transition:0.5s linear all; + * opacity:0; + * } + * + * /* The finishing CSS styles for the enter animation */ + * .fade.ng-enter.ng-enter-active { + * opacity:1; + * } + * ``` + * + * The key thing to remember here is that, depending on the animation event (which each of the directives above trigger depending on what's going on) two + * generated CSS classes will be applied to the element; in the example above we have `.ng-enter` and `.ng-enter-active`. For CSS transitions, the transition + * code **must** be defined within the starting CSS class (in this case `.ng-enter`). The destination class is what the transition will animate towards. + * + * If for example we wanted to create animations for `leave` and `move` (ngRepeat triggers move) then we can do so using the same CSS naming conventions: + * + * ```css + * /* now the element will fade out before it is removed from the DOM */ + * .fade.ng-leave { + * transition:0.5s linear all; + * opacity:1; + * } + * .fade.ng-leave.ng-leave-active { + * opacity:0; + * } + * ``` + * + * We can also make use of **CSS Keyframes** by referencing the keyframe animation within the starting CSS class: + * + * ```css + * /* there is no need to define anything inside of the destination + * CSS class since the keyframe will take charge of the animation */ + * .fade.ng-leave { + * animation: my_fade_animation 0.5s linear; + * -webkit-animation: my_fade_animation 0.5s linear; + * } + * + * @keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } + * } + * + * @-webkit-keyframes my_fade_animation { + * from { opacity:1; } + * to { opacity:0; } + * } + * ``` + * + * Feel free also mix transitions and keyframes together as well as any other CSS classes on the same element. + * + * ### CSS Class-based Animations + * + * Class-based animations (animations that are triggered via `ngClass`, `ngShow`, `ngHide` and some other directives) have a slightly different + * naming convention. Class-based animations are basic enough that a standard transition or keyframe can be referenced on the class being added + * and removed. + * + * For example if we wanted to do a CSS animation for `ngHide` then we place an animation on the `.ng-hide` CSS class: + * + * ```html + *
    + * Show and hide me + *
    + * + * + * + * ``` + * + * All that is going on here with ngShow/ngHide behind the scenes is the `.ng-hide` class is added/removed (when the hidden state is valid). Since + * ngShow and ngHide are animation aware then we can match up a transition and ngAnimate handles the rest. + * + * In addition the addition and removal of the CSS class, ngAnimate also provides two helper methods that we can use to further decorate the animation + * with CSS styles. + * + * ```html + *
    + * Highlight this box + *
    + * + * + * + * ``` + * + * We can also make use of CSS keyframes by placing them within the CSS classes. + * + * + * ### CSS Staggering Animations + * A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a + * curtain-like effect. The ngAnimate module (versions >=1.2) supports staggering animations and the stagger effect can be + * performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for + * the animation. The style property expected within the stagger class can either be a **transition-delay** or an + * **animation-delay** property (or both if your animation contains both transitions and keyframe animations). + * + * ```css + * .my-animation.ng-enter { + * /* standard transition code */ + * transition: 1s linear all; + * opacity:0; + * } + * .my-animation.ng-enter-stagger { + * /* this will have a 100ms delay between each successive leave animation */ + * transition-delay: 0.1s; + * + * /* As of 1.4.4, this must always be set: it signals ngAnimate + * to not accidentally inherit a delay property from another CSS class */ + * transition-duration: 0s; + * + * /* if you are using animations instead of transitions you should configure as follows: + * animation-delay: 0.1s; + * animation-duration: 0s; */ + * } + * .my-animation.ng-enter.ng-enter-active { + * /* standard transition styles */ + * opacity:1; + * } + * ``` + * + * Staggering animations work by default in ngRepeat (so long as the CSS class is defined). Outside of ngRepeat, to use staggering animations + * on your own, they can be triggered by firing multiple calls to the same event on $animate. However, the restrictions surrounding this + * are that each of the elements must have the same CSS className value as well as the same parent element. A stagger operation + * will also be reset if one or more animation frames have passed since the multiple calls to `$animate` were fired. + * + * The following code will issue the **ng-leave-stagger** event on the element provided: + * + * ```js + * var kids = parent.children(); + * + * $animate.leave(kids[0]); //stagger index=0 + * $animate.leave(kids[1]); //stagger index=1 + * $animate.leave(kids[2]); //stagger index=2 + * $animate.leave(kids[3]); //stagger index=3 + * $animate.leave(kids[4]); //stagger index=4 + * + * window.requestAnimationFrame(function() { + * //stagger has reset itself + * $animate.leave(kids[5]); //stagger index=0 + * $animate.leave(kids[6]); //stagger index=1 + * + * $scope.$digest(); + * }); + * ``` + * + * Stagger animations are currently only supported within CSS-defined animations. + * + * ### The `ng-animate` CSS class + * + * When ngAnimate is animating an element it will apply the `ng-animate` CSS class to the element for the duration of the animation. + * This is a temporary CSS class and it will be removed once the animation is over (for both JavaScript and CSS-based animations). + * + * Therefore, animations can be applied to an element using this temporary class directly via CSS. + * + * ```css + * .zipper.ng-animate { + * transition:0.5s linear all; + * } + * .zipper.ng-enter { + * opacity:0; + * } + * .zipper.ng-enter.ng-enter-active { + * opacity:1; + * } + * .zipper.ng-leave { + * opacity:1; + * } + * .zipper.ng-leave.ng-leave-active { + * opacity:0; + * } + * ``` + * + * (Note that the `ng-animate` CSS class is reserved and it cannot be applied on an element directly since ngAnimate will always remove + * the CSS class once an animation has completed.) + * + * + * ### The `ng-[event]-prepare` class + * + * This is a special class that can be used to prevent unwanted flickering / flash of content before + * the actual animation starts. The class is added as soon as an animation is initialized, but removed + * before the actual animation starts (after waiting for a $digest). + * It is also only added for *structural* animations (`enter`, `move`, and `leave`). + * + * In practice, flickering can appear when nesting elements with structural animations such as `ngIf` + * into elements that have class-based animations such as `ngClass`. + * + * ```html + *
    + *
    + *
    + *
    + *
    + * ``` + * + * It is possible that during the `enter` animation, the `.message` div will be briefly visible before it starts animating. + * In that case, you can add styles to the CSS that make sure the element stays hidden before the animation starts: + * + * ```css + * .message.ng-enter-prepare { + * opacity: 0; + * } + * ``` + * + * ### Animating between value changes + * + * Sometimes you need to animate between different expression states, whose values + * don't necessary need to be known or referenced in CSS styles. + * Unless possible with another {@link ngAnimate#directive-support "animation aware" directive}, + * that specific use case can always be covered with {@link ngAnimate.directive:ngAnimateSwap} as + * can be seen in {@link ngAnimate.directive:ngAnimateSwap#examples this example}. + * + * Note that {@link ngAnimate.directive:ngAnimateSwap} is a *structural directive*, which means it + * creates a new instance of the element (including any other/child directives it may have) and + * links it to a new scope every time *swap* happens. In some cases this might not be desirable + * (e.g. for performance reasons, or when you wish to retain internal state on the original + * element instance). + * + * ## JavaScript-based Animations + * + * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared + * CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the + * `module.animation()` module function we can register the animation. + * + * Let's see an example of a enter/leave animation using `ngRepeat`: + * + * ```html + *
    + * {{ item }} + *
    + * ``` + * + * See the **slide** CSS class? Let's use that class to define an animation that we'll structure in our module code by using `module.animation`: + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * // make note that other events (like addClass/removeClass) + * // have different function input parameters + * enter: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * + * // remember to call doneFn so that AngularJS + * // knows that the animation has concluded + * }, + * + * move: function(element, doneFn) { + * jQuery(element).fadeIn(1000, doneFn); + * }, + * + * leave: function(element, doneFn) { + * jQuery(element).fadeOut(1000, doneFn); + * } + * } + * }]); + * ``` + * + * The nice thing about JS-based animations is that we can inject other services and make use of advanced animation libraries such as + * greensock.js and velocity.js. + * + * If our animation code class-based (meaning that something like `ngClass`, `ngHide` and `ngShow` triggers it) then we can still define + * our animations inside of the same registered animation, however, the function input arguments are a bit different: + * + * ```html + *
    + * this box is moody + *
    + * + * + * + * ``` + * + * ```js + * myModule.animation('.colorful', [function() { + * return { + * addClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * removeClass: function(element, className, doneFn) { + * // do some cool animation and call the doneFn + * }, + * setClass: function(element, addedClass, removedClass, doneFn) { + * // do some cool animation and call the doneFn + * } + * } + * }]); + * ``` + * + * ## CSS + JS Animations Together + * + * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of AngularJS, + * defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore the example below will only result in **JS animations taking + * charge of the animation**: + * + * ```html + *
    + * Slide in and out + *
    + * ``` + * + * ```js + * myModule.animation('.slide', [function() { + * return { + * enter: function(element, doneFn) { + * jQuery(element).slideIn(1000, doneFn); + * } + * } + * }]); + * ``` + * + * ```css + * .slide.ng-enter { + * transition:0.5s linear all; + * transform:translateY(-100px); + * } + * .slide.ng-enter.ng-enter-active { + * transform:translateY(0); + * } + * ``` + * + * Does this mean that CSS and JS animations cannot be used together? Do JS-based animations always have higher priority? We can make up for the + * lack of CSS animations by using the `$animateCss` service to trigger our own tweaked-out, CSS-based animations directly from + * our own JS-based animation code: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element) { +* // this will trigger `.slide.ng-enter` and `.slide.ng-enter-active`. + * return $animateCss(element, { + * event: 'enter', + * structural: true + * }); + * } + * } + * }]); + * ``` + * + * The nice thing here is that we can save bandwidth by sticking to our CSS-based animation code and we don't need to rely on a 3rd-party animation framework. + * + * The `$animateCss` service is very powerful since we can feed in all kinds of extra properties that will be evaluated and fed into a CSS transition or + * keyframe animation. For example if we wanted to animate the height of an element while adding and removing classes then we can do so by providing that + * data into `$animateCss` directly: + * + * ```js + * myModule.animation('.slide', ['$animateCss', function($animateCss) { + * return { + * enter: function(element) { + * return $animateCss(element, { + * event: 'enter', + * structural: true, + * addClass: 'maroon-setting', + * from: { height:0 }, + * to: { height: 200 } + * }); + * } + * } + * }]); + * ``` + * + * Now we can fill in the rest via our transition CSS code: + * + * ```css + * /* the transition tells ngAnimate to make the animation happen */ + * .slide.ng-enter { transition:0.5s linear all; } + * + * /* this extra CSS class will be absorbed into the transition + * since the $animateCss code is adding the class */ + * .maroon-setting { background:red; } + * ``` + * + * And `$animateCss` will figure out the rest. Just make sure to have the `done()` callback fire the `doneFn` function to signal when the animation is over. + * + * To learn more about what's possible be sure to visit the {@link ngAnimate.$animateCss $animateCss service}. + * + * ## Animation Anchoring (via `ng-animate-ref`) + * + * ngAnimate in AngularJS 1.4 comes packed with the ability to cross-animate elements between + * structural areas of an application (like views) by pairing up elements using an attribute + * called `ng-animate-ref`. + * + * Let's say for example we have two views that are managed by `ng-view` and we want to show + * that there is a relationship between two components situated in within these views. By using the + * `ng-animate-ref` attribute we can identify that the two components are paired together and we + * can then attach an animation, which is triggered when the view changes. + * + * Say for example we have the following template code: + * + * ```html + * + *
    + *
    + * + * + * + * + * + * + * + * + * ``` + * + * Now, when the view changes (once the link is clicked), ngAnimate will examine the + * HTML contents to see if there is a match reference between any components in the view + * that is leaving and the view that is entering. It will scan both the view which is being + * removed (leave) and inserted (enter) to see if there are any paired DOM elements that + * contain a matching ref value. + * + * The two images match since they share the same ref value. ngAnimate will now create a + * transport element (which is a clone of the first image element) and it will then attempt + * to animate to the position of the second image element in the next view. For the animation to + * work a special CSS class called `ng-anchor` will be added to the transported element. + * + * We can now attach a transition onto the `.banner.ng-anchor` CSS class and then + * ngAnimate will handle the entire transition for us as well as the addition and removal of + * any changes of CSS classes between the elements: + * + * ```css + * .banner.ng-anchor { + * /* this animation will last for 1 second since there are + * two phases to the animation (an `in` and an `out` phase) */ + * transition:0.5s linear all; + * } + * ``` + * + * We also **must** include animations for the views that are being entered and removed + * (otherwise anchoring wouldn't be possible since the new view would be inserted right away). + * + * ```css + * .view-animation.ng-enter, .view-animation.ng-leave { + * transition:0.5s linear all; + * position:fixed; + * left:0; + * top:0; + * width:100%; + * } + * .view-animation.ng-enter { + * transform:translateX(100%); + * } + * .view-animation.ng-leave, + * .view-animation.ng-enter.ng-enter-active { + * transform:translateX(0%); + * } + * .view-animation.ng-leave.ng-leave-active { + * transform:translateX(-100%); + * } + * ``` + * + * Now we can jump back to the anchor animation. When the animation happens, there are two stages that occur: + * an `out` and an `in` stage. The `out` stage happens first and that is when the element is animated away + * from its origin. Once that animation is over then the `in` stage occurs which animates the + * element to its destination. The reason why there are two animations is to give enough time + * for the enter animation on the new element to be ready. + * + * The example above sets up a transition for both the in and out phases, but we can also target the out or + * in phases directly via `ng-anchor-out` and `ng-anchor-in`. + * + * ```css + * .banner.ng-anchor-out { + * transition: 0.5s linear all; + * + * /* the scale will be applied during the out animation, + * but will be animated away when the in animation runs */ + * transform: scale(1.2); + * } + * + * .banner.ng-anchor-in { + * transition: 1s linear all; + * } + * ``` + * + * + * + * + * ### Anchoring Demo + * + + + Home +
    +
    +
    +
    +
    + + angular.module('anchoringExample', ['ngAnimate', 'ngRoute']) + .config(['$routeProvider', function($routeProvider) { + $routeProvider.when('/', { + templateUrl: 'home.html', + controller: 'HomeController as home' + }); + $routeProvider.when('/profile/:id', { + templateUrl: 'profile.html', + controller: 'ProfileController as profile' + }); + }]) + .run(['$rootScope', function($rootScope) { + $rootScope.records = [ + { id: 1, title: 'Miss Beulah Roob' }, + { id: 2, title: 'Trent Morissette' }, + { id: 3, title: 'Miss Ava Pouros' }, + { id: 4, title: 'Rod Pouros' }, + { id: 5, title: 'Abdul Rice' }, + { id: 6, title: 'Laurie Rutherford Sr.' }, + { id: 7, title: 'Nakia McLaughlin' }, + { id: 8, title: 'Jordon Blanda DVM' }, + { id: 9, title: 'Rhoda Hand' }, + { id: 10, title: 'Alexandrea Sauer' } + ]; + }]) + .controller('HomeController', [function() { + //empty + }]) + .controller('ProfileController', ['$rootScope', '$routeParams', + function ProfileController($rootScope, $routeParams) { + var index = parseInt($routeParams.id, 10); + var record = $rootScope.records[index - 1]; + + this.title = record.title; + this.id = record.id; + }]); + + +

    Welcome to the home page

    +

    Please click on an element

    + + {{ record.title }} + +
    + +
    + {{ profile.title }} +
    +
    + + .record { + display:block; + font-size:20px; + } + .profile { + background:black; + color:white; + font-size:100px; + } + .view-container { + position:relative; + } + .view-container > .view.ng-animate { + position:absolute; + top:0; + left:0; + width:100%; + min-height:500px; + } + .view.ng-enter, .view.ng-leave, + .record.ng-anchor { + transition:0.5s linear all; + } + .view.ng-enter { + transform:translateX(100%); + } + .view.ng-enter.ng-enter-active, .view.ng-leave { + transform:translateX(0%); + } + .view.ng-leave.ng-leave-active { + transform:translateX(-100%); + } + .record.ng-anchor-out { + background:red; + } + +
    + * + * ### How is the element transported? + * + * When an anchor animation occurs, ngAnimate will clone the starting element and position it exactly where the starting + * element is located on screen via absolute positioning. The cloned element will be placed inside of the root element + * of the application (where ng-app was defined) and all of the CSS classes of the starting element will be applied. The + * element will then animate into the `out` and `in` animations and will eventually reach the coordinates and match + * the dimensions of the destination element. During the entire animation a CSS class of `.ng-animate-shim` will be applied + * to both the starting and destination elements in order to hide them from being visible (the CSS styling for the class + * is: `visibility:hidden`). Once the anchor reaches its destination then it will be removed and the destination element + * will become visible since the shim class will be removed. + * + * ### How is the morphing handled? + * + * CSS Anchoring relies on transitions and keyframes and the internal code is intelligent enough to figure out + * what CSS classes differ between the starting element and the destination element. These different CSS classes + * will be added/removed on the anchor element and a transition will be applied (the transition that is provided + * in the anchor class). Long story short, ngAnimate will figure out what classes to add and remove which will + * make the transition of the element as smooth and automatic as possible. Be sure to use simple CSS classes that + * do not rely on DOM nesting structure so that the anchor element appears the same as the starting element (since + * the cloned element is placed inside of root element which is likely close to the body element). + * + * Note that if the root element is on the `` element then the cloned node will be placed inside of body. + * + * + * ## Using $animate in your directive code + * + * So far we've explored how to feed in animations into an AngularJS application, but how do we trigger animations within our own directives in our application? + * By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's + * imagine we have a greeting box that shows and hides itself when the data changes + * + * ```html + * Hi there + * ``` + * + * ```js + * ngModule.directive('greetingBox', ['$animate', function($animate) { + * return function(scope, element, attrs) { + * attrs.$observe('active', function(value) { + * value ? $animate.addClass(element, 'on') : $animate.removeClass(element, 'on'); + * }); + * }); + * }]); + * ``` + * + * Now the `on` CSS class is added and removed on the greeting box component. Now if we add a CSS class on top of the greeting box element + * in our HTML code then we can trigger a CSS or JS animation to happen. + * + * ```css + * /* normally we would create a CSS class to reference on the element */ + * greeting-box.on { transition:0.5s linear all; background:green; color:white; } + * ``` + * + * The `$animate` service contains a variety of other methods like `enter`, `leave`, `animate` and `setClass`. To learn more about what's + * possible be sure to visit the {@link ng.$animate $animate service API page}. + * + * + * ## Callbacks and Promises + * + * When `$animate` is called it returns a promise that can be used to capture when the animation has ended. Therefore if we were to trigger + * an animation (within our directive code) then we can continue performing directive and scope related activities after the animation has + * ended by chaining onto the returned promise that animation method returns. + * + * ```js + * // somewhere within the depths of the directive + * $animate.enter(element, parent).then(function() { + * //the animation has completed + * }); + * ``` + * + * (Note that earlier versions of AngularJS prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case + * anymore.) + * + * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering + * an event listener using the `$animate` service. Let's say for example that an animation was triggered on our view + * routing controller to hook into that: + * + * ```js + * ngModule.controller('HomePageController', ['$animate', function($animate) { + * $animate.on('enter', ngViewElement, function(element) { + * // the animation for this route has completed + * }]); + * }]) + * ``` + * + * (Note that you will need to trigger a digest within the callback to get AngularJS to notice any scope-related changes.) + */ + +var copy; +var extend; +var forEach; +var isArray; +var isDefined; +var isElement; +var isFunction; +var isObject; +var isString; +var isUndefined; +var jqLite; +var noop; + +/** + * @ngdoc service + * @name $animate + * @kind object + * + * @description + * The ngAnimate `$animate` service documentation is the same for the core `$animate` service. + * + * Click here {@link ng.$animate to learn more about animations with `$animate`}. + */ +angular.module('ngAnimate', [], function initAngularHelpers() { + // Access helpers from AngularJS core. + // Do it inside a `config` block to ensure `window.angular` is available. + noop = angular.noop; + copy = angular.copy; + extend = angular.extend; + jqLite = angular.element; + forEach = angular.forEach; + isArray = angular.isArray; + isString = angular.isString; + isObject = angular.isObject; + isUndefined = angular.isUndefined; + isDefined = angular.isDefined; + isFunction = angular.isFunction; + isElement = angular.isElement; +}) + .info({ angularVersion: '1.7.8' }) + .directive('ngAnimateSwap', ngAnimateSwapDirective) + + .directive('ngAnimateChildren', $$AnimateChildrenDirective) + .factory('$$rAFScheduler', $$rAFSchedulerFactory) + + .provider('$$animateQueue', $$AnimateQueueProvider) + .provider('$$animateCache', $$AnimateCacheProvider) + .provider('$$animation', $$AnimationProvider) + + .provider('$animateCss', $AnimateCssProvider) + .provider('$$animateCssDriver', $$AnimateCssDriverProvider) + + .provider('$$animateJs', $$AnimateJsProvider) + .provider('$$animateJsDriver', $$AnimateJsDriverProvider); + + +})(window, window.angular); + + +/***/ }), +/* 251 */ +/***/ (function(module, exports) { + +/** + * @license AngularJS v1.7.8 + * (c) 2010-2018 Google, Inc. http://angularjs.org + * License: MIT + */ +(function(window, angular) {'use strict'; + +/** + * @ngdoc module + * @name ngAria + * @description + * + * The `ngAria` module provides support for common + * [ARIA](http://www.w3.org/TR/wai-aria/) + * attributes that convey state or semantic information about the application for users + * of assistive technologies, such as screen readers. + * + * ## Usage + * + * For ngAria to do its magic, simply include the module `ngAria` as a dependency. The following + * directives are supported: + * `ngModel`, `ngChecked`, `ngReadonly`, `ngRequired`, `ngValue`, `ngDisabled`, `ngShow`, `ngHide`, + * `ngClick`, `ngDblClick`, and `ngMessages`. + * + * Below is a more detailed breakdown of the attributes handled by ngAria: + * + * | Directive | Supported Attributes | + * |---------------------------------------------|-----------------------------------------------------------------------------------------------------| + * | {@link ng.directive:ngModel ngModel} | aria-checked, aria-valuemin, aria-valuemax, aria-valuenow, aria-invalid, aria-required, input roles | + * | {@link ng.directive:ngDisabled ngDisabled} | aria-disabled | + * | {@link ng.directive:ngRequired ngRequired} | aria-required | + * | {@link ng.directive:ngChecked ngChecked} | aria-checked | + * | {@link ng.directive:ngReadonly ngReadonly} | aria-readonly | + * | {@link ng.directive:ngValue ngValue} | aria-checked | + * | {@link ng.directive:ngShow ngShow} | aria-hidden | + * | {@link ng.directive:ngHide ngHide} | aria-hidden | + * | {@link ng.directive:ngDblclick ngDblclick} | tabindex | + * | {@link module:ngMessages ngMessages} | aria-live | + * | {@link ng.directive:ngClick ngClick} | tabindex, keydown event, button role | + * + * Find out more information about each directive by reading the + * {@link guide/accessibility ngAria Developer Guide}. + * + * ## Example + * Using ngDisabled with ngAria: + * ```html + * + * ``` + * Becomes: + * ```html + * + * ``` + * + * ## Disabling Specific Attributes + * It is possible to disable individual attributes added by ngAria with the + * {@link ngAria.$ariaProvider#config config} method. For more details, see the + * {@link guide/accessibility Developer Guide}. + * + * ## Disabling `ngAria` on Specific Elements + * It is possible to make `ngAria` ignore a specific element, by adding the `ng-aria-disable` + * attribute on it. Note that only the element itself (and not its child elements) will be ignored. + */ +var ARIA_DISABLE_ATTR = 'ngAriaDisable'; + +var ngAriaModule = angular.module('ngAria', ['ng']). + info({ angularVersion: '1.7.8' }). + provider('$aria', $AriaProvider); + +/** +* Internal Utilities +*/ +var nodeBlackList = ['BUTTON', 'A', 'INPUT', 'TEXTAREA', 'SELECT', 'DETAILS', 'SUMMARY']; + +var isNodeOneOf = function(elem, nodeTypeArray) { + if (nodeTypeArray.indexOf(elem[0].nodeName) !== -1) { + return true; + } +}; +/** + * @ngdoc provider + * @name $ariaProvider + * @this + * + * @description + * + * Used for configuring the ARIA attributes injected and managed by ngAria. + * + * ```js + * angular.module('myApp', ['ngAria'], function config($ariaProvider) { + * $ariaProvider.config({ + * ariaValue: true, + * tabindex: false + * }); + * }); + *``` + * + * ## Dependencies + * Requires the {@link ngAria} module to be installed. + * + */ +function $AriaProvider() { + var config = { + ariaHidden: true, + ariaChecked: true, + ariaReadonly: true, + ariaDisabled: true, + ariaRequired: true, + ariaInvalid: true, + ariaValue: true, + tabindex: true, + bindKeydown: true, + bindRoleForClick: true + }; + + /** + * @ngdoc method + * @name $ariaProvider#config + * + * @param {object} config object to enable/disable specific ARIA attributes + * + * - **ariaHidden** – `{boolean}` – Enables/disables aria-hidden tags + * - **ariaChecked** – `{boolean}` – Enables/disables aria-checked tags + * - **ariaReadonly** – `{boolean}` – Enables/disables aria-readonly tags + * - **ariaDisabled** – `{boolean}` – Enables/disables aria-disabled tags + * - **ariaRequired** – `{boolean}` – Enables/disables aria-required tags + * - **ariaInvalid** – `{boolean}` – Enables/disables aria-invalid tags + * - **ariaValue** – `{boolean}` – Enables/disables aria-valuemin, aria-valuemax and + * aria-valuenow tags + * - **tabindex** – `{boolean}` – Enables/disables tabindex tags + * - **bindKeydown** – `{boolean}` – Enables/disables keyboard event binding on non-interactive + * elements (such as `div` or `li`) using ng-click, making them more accessible to users of + * assistive technologies + * - **bindRoleForClick** – `{boolean}` – Adds role=button to non-interactive elements (such as + * `div` or `li`) using ng-click, making them more accessible to users of assistive + * technologies + * + * @description + * Enables/disables various ARIA attributes + */ + this.config = function(newConfig) { + config = angular.extend(config, newConfig); + }; + + function watchExpr(attrName, ariaAttr, nodeBlackList, negate) { + return function(scope, elem, attr) { + if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return; + + var ariaCamelName = attr.$normalize(ariaAttr); + if (config[ariaCamelName] && !isNodeOneOf(elem, nodeBlackList) && !attr[ariaCamelName]) { + scope.$watch(attr[attrName], function(boolVal) { + // ensure boolean value + boolVal = negate ? !boolVal : !!boolVal; + elem.attr(ariaAttr, boolVal); + }); + } + }; + } + /** + * @ngdoc service + * @name $aria + * + * @description + * @priority 200 + * + * The $aria service contains helper methods for applying common + * [ARIA](http://www.w3.org/TR/wai-aria/) attributes to HTML directives. + * + * ngAria injects common accessibility attributes that tell assistive technologies when HTML + * elements are enabled, selected, hidden, and more. To see how this is performed with ngAria, + * let's review a code snippet from ngAria itself: + * + *```js + * ngAriaModule.directive('ngDisabled', ['$aria', function($aria) { + * return $aria.$$watchExpr('ngDisabled', 'aria-disabled', nodeBlackList, false); + * }]) + *``` + * Shown above, the ngAria module creates a directive with the same signature as the + * traditional `ng-disabled` directive. But this ngAria version is dedicated to + * solely managing accessibility attributes on custom elements. The internal `$aria` service is + * used to watch the boolean attribute `ngDisabled`. If it has not been explicitly set by the + * developer, `aria-disabled` is injected as an attribute with its value synchronized to the + * value in `ngDisabled`. + * + * Because ngAria hooks into the `ng-disabled` directive, developers do not have to do + * anything to enable this feature. The `aria-disabled` attribute is automatically managed + * simply as a silent side-effect of using `ng-disabled` with the ngAria module. + * + * The full list of directives that interface with ngAria: + * * **ngModel** + * * **ngChecked** + * * **ngReadonly** + * * **ngRequired** + * * **ngDisabled** + * * **ngValue** + * * **ngShow** + * * **ngHide** + * * **ngClick** + * * **ngDblclick** + * * **ngMessages** + * + * Read the {@link guide/accessibility ngAria Developer Guide} for a thorough explanation of each + * directive. + * + * + * ## Dependencies + * Requires the {@link ngAria} module to be installed. + */ + this.$get = function() { + return { + config: function(key) { + return config[key]; + }, + $$watchExpr: watchExpr + }; + }; +} + + +ngAriaModule.directive('ngShow', ['$aria', function($aria) { + return $aria.$$watchExpr('ngShow', 'aria-hidden', [], true); +}]) +.directive('ngHide', ['$aria', function($aria) { + return $aria.$$watchExpr('ngHide', 'aria-hidden', [], false); +}]) +.directive('ngValue', ['$aria', function($aria) { + return $aria.$$watchExpr('ngValue', 'aria-checked', nodeBlackList, false); +}]) +.directive('ngChecked', ['$aria', function($aria) { + return $aria.$$watchExpr('ngChecked', 'aria-checked', nodeBlackList, false); +}]) +.directive('ngReadonly', ['$aria', function($aria) { + return $aria.$$watchExpr('ngReadonly', 'aria-readonly', nodeBlackList, false); +}]) +.directive('ngRequired', ['$aria', function($aria) { + return $aria.$$watchExpr('ngRequired', 'aria-required', nodeBlackList, false); +}]) +.directive('ngModel', ['$aria', function($aria) { + + function shouldAttachAttr(attr, normalizedAttr, elem, allowBlacklistEls) { + return $aria.config(normalizedAttr) && + !elem.attr(attr) && + (allowBlacklistEls || !isNodeOneOf(elem, nodeBlackList)) && + (elem.attr('type') !== 'hidden' || elem[0].nodeName !== 'INPUT'); + } + + function shouldAttachRole(role, elem) { + // if element does not have role attribute + // AND element type is equal to role (if custom element has a type equaling shape) <-- remove? + // AND element is not in nodeBlackList + return !elem.attr('role') && (elem.attr('type') === role) && !isNodeOneOf(elem, nodeBlackList); + } + + function getShape(attr, elem) { + var type = attr.type, + role = attr.role; + + return ((type || role) === 'checkbox' || role === 'menuitemcheckbox') ? 'checkbox' : + ((type || role) === 'radio' || role === 'menuitemradio') ? 'radio' : + (type === 'range' || role === 'progressbar' || role === 'slider') ? 'range' : ''; + } + + return { + restrict: 'A', + require: 'ngModel', + priority: 200, //Make sure watches are fired after any other directives that affect the ngModel value + compile: function(elem, attr) { + if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return; + + var shape = getShape(attr, elem); + + return { + post: function(scope, elem, attr, ngModel) { + var needsTabIndex = shouldAttachAttr('tabindex', 'tabindex', elem, false); + + function ngAriaWatchModelValue() { + return ngModel.$modelValue; + } + + function getRadioReaction(newVal) { + // Strict comparison would cause a BC + // eslint-disable-next-line eqeqeq + var boolVal = (attr.value == ngModel.$viewValue); + elem.attr('aria-checked', boolVal); + } + + function getCheckboxReaction() { + elem.attr('aria-checked', !ngModel.$isEmpty(ngModel.$viewValue)); + } + + switch (shape) { + case 'radio': + case 'checkbox': + if (shouldAttachRole(shape, elem)) { + elem.attr('role', shape); + } + if (shouldAttachAttr('aria-checked', 'ariaChecked', elem, false)) { + scope.$watch(ngAriaWatchModelValue, shape === 'radio' ? + getRadioReaction : getCheckboxReaction); + } + if (needsTabIndex) { + elem.attr('tabindex', 0); + } + break; + case 'range': + if (shouldAttachRole(shape, elem)) { + elem.attr('role', 'slider'); + } + if ($aria.config('ariaValue')) { + var needsAriaValuemin = !elem.attr('aria-valuemin') && + (attr.hasOwnProperty('min') || attr.hasOwnProperty('ngMin')); + var needsAriaValuemax = !elem.attr('aria-valuemax') && + (attr.hasOwnProperty('max') || attr.hasOwnProperty('ngMax')); + var needsAriaValuenow = !elem.attr('aria-valuenow'); + + if (needsAriaValuemin) { + attr.$observe('min', function ngAriaValueMinReaction(newVal) { + elem.attr('aria-valuemin', newVal); + }); + } + if (needsAriaValuemax) { + attr.$observe('max', function ngAriaValueMinReaction(newVal) { + elem.attr('aria-valuemax', newVal); + }); + } + if (needsAriaValuenow) { + scope.$watch(ngAriaWatchModelValue, function ngAriaValueNowReaction(newVal) { + elem.attr('aria-valuenow', newVal); + }); + } + } + if (needsTabIndex) { + elem.attr('tabindex', 0); + } + break; + } + + if (!attr.hasOwnProperty('ngRequired') && ngModel.$validators.required + && shouldAttachAttr('aria-required', 'ariaRequired', elem, false)) { + // ngModel.$error.required is undefined on custom controls + attr.$observe('required', function() { + elem.attr('aria-required', !!attr['required']); + }); + } + + if (shouldAttachAttr('aria-invalid', 'ariaInvalid', elem, true)) { + scope.$watch(function ngAriaInvalidWatch() { + return ngModel.$invalid; + }, function ngAriaInvalidReaction(newVal) { + elem.attr('aria-invalid', !!newVal); + }); + } + } + }; + } + }; +}]) +.directive('ngDisabled', ['$aria', function($aria) { + return $aria.$$watchExpr('ngDisabled', 'aria-disabled', nodeBlackList, false); +}]) +.directive('ngMessages', function() { + return { + restrict: 'A', + require: '?ngMessages', + link: function(scope, elem, attr, ngMessages) { + if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return; + + if (!elem.attr('aria-live')) { + elem.attr('aria-live', 'assertive'); + } + } + }; +}) +.directive('ngClick',['$aria', '$parse', function($aria, $parse) { + return { + restrict: 'A', + compile: function(elem, attr) { + if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return; + + var fn = $parse(attr.ngClick); + return function(scope, elem, attr) { + + if (!isNodeOneOf(elem, nodeBlackList)) { + + if ($aria.config('bindRoleForClick') && !elem.attr('role')) { + elem.attr('role', 'button'); + } + + if ($aria.config('tabindex') && !elem.attr('tabindex')) { + elem.attr('tabindex', 0); + } + + if ($aria.config('bindKeydown') && !attr.ngKeydown && !attr.ngKeypress && !attr.ngKeyup) { + elem.on('keydown', function(event) { + var keyCode = event.which || event.keyCode; + + if (keyCode === 13 || keyCode === 32) { + // If the event is triggered on a non-interactive element ... + if (nodeBlackList.indexOf(event.target.nodeName) === -1 && !event.target.isContentEditable) { + // ... prevent the default browser behavior (e.g. scrolling when pressing spacebar) + // See https://github.com/angular/angular.js/issues/16664 + event.preventDefault(); + } + scope.$apply(callback); + } + + function callback() { + fn(scope, { $event: event }); + } + }); + } + } + }; + } + }; +}]) +.directive('ngDblclick', ['$aria', function($aria) { + return function(scope, elem, attr) { + if (attr.hasOwnProperty(ARIA_DISABLE_ATTR)) return; + + if ($aria.config('tabindex') && !elem.attr('tabindex') && !isNodeOneOf(elem, nodeBlackList)) { + elem.attr('tabindex', 0); + } + }; +}]); + + +})(window, window.angular); + + +/***/ }), +/* 252 */ +/***/ (function(module, exports, __webpack_require__) { + +// Should already be required, here for clarity +__webpack_require__(128); + +// Load Angular and dependent libs +__webpack_require__(129); +__webpack_require__(130); + +// Now load Angular Material +__webpack_require__(253); + +// Export namespace +module.exports = 'ngMaterial'; + + +/***/ }), +/* 253 */ +/***/ (function(module, exports) { + +/*! + * AngularJS Material Design + * https://github.com/angular/material + * @license MIT + * v1.1.19 + */ +(function( window, angular, undefined ){ +"use strict"; + +(function(){ +"use strict"; + +angular.module('ngMaterial', ["ng","ngAnimate","ngAria","material.core","material.core.animate","material.core.gestures","material.core.interaction","material.core.layout","material.core.meta","material.core.theming.palette","material.core.theming","material.components.autocomplete","material.components.backdrop","material.components.bottomSheet","material.components.button","material.components.card","material.components.checkbox","material.components.chips","material.components.colors","material.components.content","material.components.datepicker","material.components.dialog","material.components.divider","material.components.fabActions","material.components.fabShared","material.components.fabSpeedDial","material.components.fabToolbar","material.components.gridList","material.components.icon","material.components.input","material.components.list","material.components.menu","material.components.menuBar","material.components.navBar","material.components.panel","material.components.progressCircular","material.components.progressLinear","material.components.radioButton","material.components.select","material.components.showHide","material.components.sidenav","material.components.slider","material.components.sticky","material.components.subheader","material.components.swipe","material.components.switch","material.components.tabs","material.components.toast","material.components.toolbar","material.components.tooltip","material.components.truncate","material.components.virtualRepeat","material.components.whiteframe"]); +})(); +(function(){ +"use strict"; + +/** + * Initialization function that validates environment + * requirements. + */ +DetectNgTouch.$inject = ["$log", "$injector"]; +MdCoreConfigure.$inject = ["$provide", "$mdThemingProvider"]; +rAFDecorator.$inject = ["$delegate"]; +qDecorator.$inject = ["$delegate"]; +angular + .module('material.core', [ + 'ngAnimate', + 'material.core.animate', + 'material.core.layout', + 'material.core.interaction', + 'material.core.gestures', + 'material.core.theming' + ]) + .config(MdCoreConfigure) + .run(DetectNgTouch); + + +/** + * Detect if the ng-Touch module is also being used. + * Warn if detected. + * @ngInject + */ +function DetectNgTouch($log, $injector) { + if ($injector.has('$swipe')) { + var msg = "" + + "You are using the ngTouch module. \n" + + "AngularJS Material already has mobile click, tap, and swipe support... \n" + + "ngTouch is not supported with AngularJS Material!"; + $log.warn(msg); + } +} + +/** + * @ngInject + */ +function MdCoreConfigure($provide, $mdThemingProvider) { + + $provide.decorator('$$rAF', ['$delegate', rAFDecorator]); + $provide.decorator('$q', ['$delegate', qDecorator]); + + $mdThemingProvider.theme('default') + .primaryPalette('indigo') + .accentPalette('pink') + .warnPalette('deep-orange') + .backgroundPalette('grey'); +} + +/** + * @ngInject + */ +function rAFDecorator($delegate) { + /** + * Use this to throttle events that come in often. + * The throttled function will always use the *last* invocation before the + * coming frame. + * + * For example, window resize events that fire many times a second: + * If we set to use an raf-throttled callback on window resize, then + * our callback will only be fired once per frame, with the last resize + * event that happened before that frame. + * + * @param {function} callback function to debounce + */ + $delegate.throttle = function(cb) { + var queuedArgs, alreadyQueued, queueCb, context; + return function debounced() { + queuedArgs = arguments; + context = this; + queueCb = cb; + if (!alreadyQueued) { + alreadyQueued = true; + $delegate(function() { + queueCb.apply(context, Array.prototype.slice.call(queuedArgs)); + alreadyQueued = false; + }); + } + }; + }; + return $delegate; +} + +/** + * @ngInject + */ +function qDecorator($delegate) { + /** + * Adds a shim for $q.resolve for AngularJS version that don't have it, + * so we don't have to think about it. + * + * via https://github.com/angular/angular.js/pull/11987 + */ + + // TODO(crisbeto): this won't be necessary once we drop AngularJS 1.3 + if (!$delegate.resolve) { + $delegate.resolve = $delegate.when; + } + return $delegate; +} + +})(); +(function(){ +"use strict"; + + +MdAutofocusDirective.$inject = ["$parse"];angular.module('material.core') + .directive('mdAutofocus', MdAutofocusDirective) + + // Support the deprecated md-auto-focus and md-sidenav-focus as well + .directive('mdAutoFocus', MdAutofocusDirective) + .directive('mdSidenavFocus', MdAutofocusDirective); + +/** + * @ngdoc directive + * @name mdAutofocus + * @module material.core.util + * + * @description + * + * `[md-autofocus]` provides an optional way to identify the focused element when a `$mdDialog`, + * `$mdBottomSheet`, `$mdMenu` or `$mdSidenav` opens or upon page load for input-like elements. + * + * When one of these opens, it will find the first nested element with the `[md-autofocus]` + * attribute directive and optional expression. An expression may be specified as the directive + * value to enable conditional activation of the autofocus. + * + * @usage + * + * ### Dialog + * + * + *
    + * + * + * + * + *
    + *
    + *
    + * + * ### Bottomsheet + * + * + * Comment Actions + * + * + * + * + * + * {{ item.name }} + * + * + * + * + * + * + * + * ### Autocomplete + * + * + * {{item.display}} + * + * + * + * ### Sidenav + * + *
    + * + * Left Nav! + * + * + * + * Center Content + * + * Open Left Menu + * + * + * + * + *
    + * + * + * + * + *
    + *
    + *
    + *
    + **/ +function MdAutofocusDirective($parse) { + return { + restrict: 'A', + link: { + pre: preLink + } + }; + + function preLink(scope, element, attr) { + var attrExp = attr.mdAutoFocus || attr.mdAutofocus || attr.mdSidenavFocus; + + // Initially update the expression by manually parsing the expression as per $watch source. + updateExpression($parse(attrExp)(scope)); + + // Only watch the expression if it is not empty. + if (attrExp) { + scope.$watch(attrExp, updateExpression); + } + + /** + * Updates the autofocus class which is used to determine whether the attribute + * expression evaluates to true or false. + * @param {string|boolean} value Attribute Value + */ + function updateExpression(value) { + + // Rather than passing undefined to the jqLite toggle class function we explicitly set the + // value to true. Otherwise the class will be just toggled instead of being forced. + if (angular.isUndefined(value)) { + value = true; + } + + element.toggleClass('md-autofocus', !!value); + } + } + +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.core.colorUtil + * @description + * Color Util + */ +angular + .module('material.core') + .factory('$mdColorUtil', ColorUtilFactory); + +function ColorUtilFactory() { + /** + * Converts hex value to RGBA string + * @param color {string} + * @returns {string} + */ + function hexToRgba (color) { + var hex = color[ 0 ] === '#' ? color.substr(1) : color, + dig = hex.length / 3, + red = hex.substr(0, dig), + green = hex.substr(dig, dig), + blue = hex.substr(dig * 2); + if (dig === 1) { + red += red; + green += green; + blue += blue; + } + return 'rgba(' + parseInt(red, 16) + ',' + parseInt(green, 16) + ',' + parseInt(blue, 16) + ',0.1)'; + } + + /** + * Converts rgba value to hex string + * @param {string} color + * @returns {string} + */ + function rgbaToHex(color) { + color = color.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); + + var hex = (color && color.length === 4) ? "#" + + ("0" + parseInt(color[1],10).toString(16)).slice(-2) + + ("0" + parseInt(color[2],10).toString(16)).slice(-2) + + ("0" + parseInt(color[3],10).toString(16)).slice(-2) : ''; + + return hex.toUpperCase(); + } + + /** + * Converts an RGB color to RGBA + * @param {string} color + * @returns {string} + */ + function rgbToRgba (color) { + return color.replace(')', ', 0.1)').replace('(', 'a('); + } + + /** + * Converts an RGBA color to RGB + * @param {string} color + * @returns {string} + */ + function rgbaToRgb (color) { + return color + ? color.replace('rgba', 'rgb').replace(/,[^),]+\)/, ')') + : 'rgb(0,0,0)'; + } + + return { + rgbaToHex: rgbaToHex, + hexToRgba: hexToRgba, + rgbToRgba: rgbToRgba, + rgbaToRgb: rgbaToRgb + }; +} + +})(); +(function(){ +"use strict"; + +angular.module('material.core') +.factory('$mdConstant', MdConstantFactory); + +/** + * Factory function that creates the grab-bag $mdConstant service. + * @ngInject + */ +function MdConstantFactory() { + + var prefixTestEl = document.createElement('div'); + var vendorPrefix = getVendorPrefix(prefixTestEl); + var isWebkit = /webkit/i.test(vendorPrefix); + var SPECIAL_CHARS_REGEXP = /([:\-_]+(.))/g; + + function vendorProperty(name) { + // Add a dash between the prefix and name, to be able to transform the string into camelcase. + var prefixedName = vendorPrefix + '-' + name; + var ucPrefix = camelCase(prefixedName); + var lcPrefix = ucPrefix.charAt(0).toLowerCase() + ucPrefix.substring(1); + + return hasStyleProperty(prefixTestEl, name) ? name : // The current browser supports the un-prefixed property + hasStyleProperty(prefixTestEl, ucPrefix) ? ucPrefix : // The current browser only supports the prefixed property. + hasStyleProperty(prefixTestEl, lcPrefix) ? lcPrefix : name; // Some browsers are only supporting the prefix in lowercase. + } + + function hasStyleProperty(testElement, property) { + return angular.isDefined(testElement.style[property]); + } + + function camelCase(input) { + return input.replace(SPECIAL_CHARS_REGEXP, function(matches, separator, letter, offset) { + return offset ? letter.toUpperCase() : letter; + }); + } + + function getVendorPrefix(testElement) { + var prop, match; + var vendorRegex = /^(Moz|webkit|ms)(?=[A-Z])/; + + for (prop in testElement.style) { + if (match = vendorRegex.exec(prop)) { + return match[0]; + } + } + } + + var self = { + isInputKey : function(e) { return (e.keyCode >= 31 && e.keyCode <= 90); }, + isNumPadKey : function(e) { return (3 === e.location && e.keyCode >= 97 && e.keyCode <= 105); }, + isMetaKey: function(e) { return (e.keyCode >= 91 && e.keyCode <= 93); }, + isFnLockKey: function(e) { return (e.keyCode >= 112 && e.keyCode <= 145); }, + isNavigationKey : function(e) { + var kc = self.KEY_CODE, NAVIGATION_KEYS = [kc.SPACE, kc.ENTER, kc.UP_ARROW, kc.DOWN_ARROW]; + return (NAVIGATION_KEYS.indexOf(e.keyCode) != -1); + }, + hasModifierKey: function(e) { + return e.ctrlKey || e.metaKey || e.altKey; + }, + + /** + * Maximum size, in pixels, that can be explicitly set to an element. The actual value varies + * between browsers, but IE11 has the very lowest size at a mere 1,533,917px. Ideally we could + * compute this value, but Firefox always reports an element to have a size of zero if it + * goes over the max, meaning that we'd have to binary search for the value. + */ + ELEMENT_MAX_PIXELS: 1533917, + + /** + * Priority for a directive that should run before the directives from ngAria. + */ + BEFORE_NG_ARIA: 210, + + /** + * Common Keyboard actions and their associated keycode. + */ + KEY_CODE: { + COMMA: 188, + SEMICOLON : 186, + ENTER: 13, + ESCAPE: 27, + SPACE: 32, + PAGE_UP: 33, + PAGE_DOWN: 34, + END: 35, + HOME: 36, + LEFT_ARROW : 37, + UP_ARROW : 38, + RIGHT_ARROW : 39, + DOWN_ARROW : 40, + TAB : 9, + BACKSPACE: 8, + DELETE: 46 + }, + + /** + * Vendor prefixed CSS properties to be used to support the given functionality in older browsers + * as well. + */ + CSS: { + /* Constants */ + TRANSITIONEND: 'transitionend' + (isWebkit ? ' webkitTransitionEnd' : ''), + ANIMATIONEND: 'animationend' + (isWebkit ? ' webkitAnimationEnd' : ''), + + TRANSFORM: vendorProperty('transform'), + TRANSFORM_ORIGIN: vendorProperty('transformOrigin'), + TRANSITION: vendorProperty('transition'), + TRANSITION_DURATION: vendorProperty('transitionDuration'), + ANIMATION_PLAY_STATE: vendorProperty('animationPlayState'), + ANIMATION_DURATION: vendorProperty('animationDuration'), + ANIMATION_NAME: vendorProperty('animationName'), + ANIMATION_TIMING: vendorProperty('animationTimingFunction'), + ANIMATION_DIRECTION: vendorProperty('animationDirection') + }, + + /** + * As defined in core/style/variables.scss + * + * $layout-breakpoint-xs: 600px !default; + * $layout-breakpoint-sm: 960px !default; + * $layout-breakpoint-md: 1280px !default; + * $layout-breakpoint-lg: 1920px !default; + * + */ + MEDIA: { + 'xs' : '(max-width: 599px)' , + 'gt-xs' : '(min-width: 600px)' , + 'sm' : '(min-width: 600px) and (max-width: 959px)' , + 'gt-sm' : '(min-width: 960px)' , + 'md' : '(min-width: 960px) and (max-width: 1279px)' , + 'gt-md' : '(min-width: 1280px)' , + 'lg' : '(min-width: 1280px) and (max-width: 1919px)', + 'gt-lg' : '(min-width: 1920px)' , + 'xl' : '(min-width: 1920px)' , + 'landscape' : '(orientation: landscape)' , + 'portrait' : '(orientation: portrait)' , + 'print' : 'print' + }, + + MEDIA_PRIORITY: [ + 'xl', + 'gt-lg', + 'lg', + 'gt-md', + 'md', + 'gt-sm', + 'sm', + 'gt-xs', + 'xs', + 'landscape', + 'portrait', + 'print' + ] + }; + + return self; +} + +})(); +(function(){ +"use strict"; + + angular + .module('material.core') + .config(["$provide", function($provide){ + $provide.decorator('$mdUtil', ['$delegate', function ($delegate){ + /** + * Inject the iterator facade to easily support iteration and accessors + * @see iterator below + */ + $delegate.iterator = MdIterator; + + return $delegate; + } + ]); + }]); + + /** + * iterator is a list facade to easily support iteration and accessors + * + * @param items Array list which this iterator will enumerate + * @param reloop Boolean enables iterator to consider the list as an endless reloop + */ + function MdIterator(items, reloop) { + var trueFn = function() { return true; }; + + if (items && !angular.isArray(items)) { + items = Array.prototype.slice.call(items); + } + + reloop = !!reloop; + var _items = items || []; + + // Published API + return { + items: getItems, + count: count, + + inRange: inRange, + contains: contains, + indexOf: indexOf, + itemAt: itemAt, + + findBy: findBy, + + add: add, + remove: remove, + + first: first, + last: last, + next: angular.bind(null, findSubsequentItem, false), + previous: angular.bind(null, findSubsequentItem, true), + + hasPrevious: hasPrevious, + hasNext: hasNext + + }; + + /** + * Publish copy of the enumerable set + * @returns {Array|*} + */ + function getItems() { + return [].concat(_items); + } + + /** + * Determine length of the list + * @returns {Array.length|*|number} + */ + function count() { + return _items.length; + } + + /** + * Is the index specified valid + * @param index + * @returns {Array.length|*|number|boolean} + */ + function inRange(index) { + return _items.length && (index > -1) && (index < _items.length); + } + + /** + * Can the iterator proceed to the next item in the list; relative to + * the specified item. + * + * @param item + * @returns {Array.length|*|number|boolean} + */ + function hasNext(item) { + return item ? inRange(indexOf(item) + 1) : false; + } + + /** + * Can the iterator proceed to the previous item in the list; relative to + * the specified item. + * + * @param item + * @returns {Array.length|*|number|boolean} + */ + function hasPrevious(item) { + return item ? inRange(indexOf(item) - 1) : false; + } + + /** + * Get item at specified index/position + * @param index + * @returns {*} + */ + function itemAt(index) { + return inRange(index) ? _items[index] : null; + } + + /** + * Find all elements matching the key/value pair + * otherwise return null + * + * @param val + * @param key + * + * @return array + */ + function findBy(key, val) { + return _items.filter(function(item) { + return item[key] === val; + }); + } + + /** + * Add item to list + * @param item + * @param index + * @returns {*} + */ + function add(item, index) { + if (!item) return -1; + + if (!angular.isNumber(index)) { + index = _items.length; + } + + _items.splice(index, 0, item); + + return indexOf(item); + } + + /** + * Remove item from list... + * @param item + */ + function remove(item) { + if (contains(item)){ + _items.splice(indexOf(item), 1); + } + } + + /** + * Get the zero-based index of the target item + * @param item + * @returns {*} + */ + function indexOf(item) { + return _items.indexOf(item); + } + + /** + * Boolean existence check + * @param item + * @returns {boolean} + */ + function contains(item) { + return item && (indexOf(item) > -1); + } + + /** + * Return first item in the list + * @returns {*} + */ + function first() { + return _items.length ? _items[0] : null; + } + + /** + * Return last item in the list... + * @returns {*} + */ + function last() { + return _items.length ? _items[_items.length - 1] : null; + } + + /** + * Find the next item. If reloop is true and at the end of the list, it will go back to the + * first item. If given, the `validate` callback will be used to determine whether the next item + * is valid. If not valid, it will try to find the next item again. + * + * @param {boolean} backwards Specifies the direction of searching (forwards/backwards) + * @param {*} item The item whose subsequent item we are looking for + * @param {Function=} validate The `validate` function + * @param {integer=} limit The recursion limit + * + * @returns {*} The subsequent item or null + */ + function findSubsequentItem(backwards, item, validate, limit) { + validate = validate || trueFn; + + var curIndex = indexOf(item); + while (true) { + if (!inRange(curIndex)) return null; + + var nextIndex = curIndex + (backwards ? -1 : 1); + var foundItem = null; + if (inRange(nextIndex)) { + foundItem = _items[nextIndex]; + } else if (reloop) { + foundItem = backwards ? last() : first(); + nextIndex = indexOf(foundItem); + } + + if ((foundItem === null) || (nextIndex === limit)) return null; + if (validate(foundItem)) return foundItem; + + if (angular.isUndefined(limit)) limit = nextIndex; + + curIndex = nextIndex; + } + } + } + + +})(); +(function(){ +"use strict"; + + +mdMediaFactory.$inject = ["$mdConstant", "$rootScope", "$window"];angular.module('material.core') +.factory('$mdMedia', mdMediaFactory); + +/** + * @ngdoc service + * @name $mdMedia + * @module material.core + * + * @description + * `$mdMedia` is used to evaluate whether a given media query is true or false given the + * current device's screen / window size. The media query will be re-evaluated on resize, allowing + * you to register a watch. + * + * `$mdMedia` also has pre-programmed support for media queries that match the layout breakpoints: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    BreakpointmediaQuery
    xs(max-width: 599px)
    gt-xs(min-width: 600px)
    sm(min-width: 600px) and (max-width: 959px)
    gt-sm(min-width: 960px)
    md(min-width: 960px) and (max-width: 1279px)
    gt-md(min-width: 1280px)
    lg(min-width: 1280px) and (max-width: 1919px)
    gt-lg(min-width: 1920px)
    xl(min-width: 1920px)
    landscapelandscape
    portraitportrait
    printprint
    + * + * See Material Design's Layout - Adaptive UI for more details. + * + * + * + * + * + * @returns {boolean} a boolean representing whether or not the given media query is true or false. + * + * @usage + * + * app.controller('MyController', function($mdMedia, $scope) { + * $scope.$watch(function() { return $mdMedia('lg'); }, function(big) { + * $scope.bigScreen = big; + * }); + * + * $scope.screenIsSmall = $mdMedia('sm'); + * $scope.customQuery = $mdMedia('(min-width: 1234px)'); + * $scope.anotherCustom = $mdMedia('max-width: 300px'); + * }); + * + */ + +/* @ngInject */ +function mdMediaFactory($mdConstant, $rootScope, $window) { + var queries = {}; + var mqls = {}; + var results = {}; + var normalizeCache = {}; + + $mdMedia.getResponsiveAttribute = getResponsiveAttribute; + $mdMedia.getQuery = getQuery; + $mdMedia.watchResponsiveAttributes = watchResponsiveAttributes; + + return $mdMedia; + + function $mdMedia(query) { + var validated = queries[query]; + if (angular.isUndefined(validated)) { + validated = queries[query] = validate(query); + } + + var result = results[validated]; + if (angular.isUndefined(result)) { + result = add(validated); + } + + return result; + } + + function validate(query) { + return $mdConstant.MEDIA[query] || + ((query.charAt(0) !== '(') ? ('(' + query + ')') : query); + } + + function add(query) { + var result = mqls[query]; + if (!result) { + result = mqls[query] = $window.matchMedia(query); + } + + result.addListener(onQueryChange); + return (results[result.media] = !!result.matches); + } + + function onQueryChange(query) { + $rootScope.$evalAsync(function() { + results[query.media] = !!query.matches; + }); + } + + function getQuery(name) { + return mqls[name]; + } + + function getResponsiveAttribute(attrs, attrName) { + for (var i = 0; i < $mdConstant.MEDIA_PRIORITY.length; i++) { + var mediaName = $mdConstant.MEDIA_PRIORITY[i]; + if (!mqls[queries[mediaName]].matches) { + continue; + } + + var normalizedName = getNormalizedName(attrs, attrName + '-' + mediaName); + if (attrs[normalizedName]) { + return attrs[normalizedName]; + } + } + + // fallback on unprefixed + return attrs[getNormalizedName(attrs, attrName)]; + } + + function watchResponsiveAttributes(attrNames, attrs, watchFn) { + var unwatchFns = []; + attrNames.forEach(function(attrName) { + var normalizedName = getNormalizedName(attrs, attrName); + if (angular.isDefined(attrs[normalizedName])) { + unwatchFns.push( + attrs.$observe(normalizedName, angular.bind(void 0, watchFn, null))); + } + + for (var mediaName in $mdConstant.MEDIA) { + normalizedName = getNormalizedName(attrs, attrName + '-' + mediaName); + if (angular.isDefined(attrs[normalizedName])) { + unwatchFns.push( + attrs.$observe(normalizedName, angular.bind(void 0, watchFn, mediaName))); + } + } + }); + + return function unwatch() { + unwatchFns.forEach(function(fn) { fn(); }); + }; + } + + // Improves performance dramatically + function getNormalizedName(attrs, attrName) { + return normalizeCache[attrName] || + (normalizeCache[attrName] = attrs.$normalize(attrName)); + } +} + +})(); +(function(){ +"use strict"; + +angular + .module('material.core') + .config(["$provide", function($provide) { + $provide.decorator('$mdUtil', ['$delegate', function ($delegate) { + + // Inject the prefixer into our original $mdUtil service. + $delegate.prefixer = MdPrefixer; + + return $delegate; + }]); + }]); + +function MdPrefixer(initialAttributes, buildSelector) { + var PREFIXES = ['data', 'x']; + + if (initialAttributes) { + // The prefixer also accepts attributes as a parameter, and immediately builds a list or selector for + // the specified attributes. + return buildSelector ? _buildSelector(initialAttributes) : _buildList(initialAttributes); + } + + return { + buildList: _buildList, + buildSelector: _buildSelector, + hasAttribute: _hasAttribute, + removeAttribute: _removeAttribute + }; + + function _buildList(attributes) { + attributes = angular.isArray(attributes) ? attributes : [attributes]; + + attributes.forEach(function(item) { + PREFIXES.forEach(function(prefix) { + attributes.push(prefix + '-' + item); + }); + }); + + return attributes; + } + + function _buildSelector(attributes) { + attributes = angular.isArray(attributes) ? attributes : [attributes]; + + return _buildList(attributes) + .map(function(item) { + return '[' + item + ']'; + }) + .join(','); + } + + function _hasAttribute(element, attribute) { + element = _getNativeElement(element); + + if (!element) { + return false; + } + + var prefixedAttrs = _buildList(attribute); + + for (var i = 0; i < prefixedAttrs.length; i++) { + if (element.hasAttribute(prefixedAttrs[i])) { + return true; + } + } + + return false; + } + + function _removeAttribute(element, attribute) { + element = _getNativeElement(element); + + if (!element) { + return; + } + + _buildList(attribute).forEach(function(prefixedAttribute) { + element.removeAttribute(prefixedAttribute); + }); + } + + /** + * Transforms a jqLite or DOM element into a HTML element. + * This is useful when supporting jqLite elements and DOM elements at + * same time. + * @param element {JQLite|Element} Element to be parsed + * @returns {HTMLElement} Parsed HTMLElement + */ + function _getNativeElement(element) { + element = element[0] || element; + + if (element.nodeType) { + return element; + } + } + +} + +})(); +(function(){ +"use strict"; + +/* + * This var has to be outside the angular factory, otherwise when + * there are multiple material apps on the same page, each app + * will create its own instance of this array and the app's IDs + * will not be unique. + */ +UtilFactory.$inject = ["$document", "$timeout", "$compile", "$rootScope", "$$mdAnimate", "$interpolate", "$log", "$rootElement", "$window", "$$rAF"]; +var nextUniqueId = 0; + +/** + * @ngdoc module + * @name material.core.util + * @description + * Util + */ +angular +.module('material.core') +.factory('$mdUtil', UtilFactory); + +/** + * @ngInject + */ +function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $interpolate, $log, $rootElement, $window, $$rAF) { + // Setup some core variables for the processTemplate method + var startSymbol = $interpolate.startSymbol(), + endSymbol = $interpolate.endSymbol(), + usesStandardSymbols = ((startSymbol === '{{') && (endSymbol === '}}')); + + /** + * Checks if the target element has the requested style by key + * @param {DOMElement|JQLite} target Target element + * @param {string} key Style key + * @param {string=} expectedVal Optional expected value + * @returns {boolean} Whether the target element has the style or not + */ + var hasComputedStyle = function (target, key, expectedVal) { + var hasValue = false; + + if (target && target.length) { + var computedStyles = $window.getComputedStyle(target[0]); + hasValue = angular.isDefined(computedStyles[key]) && (expectedVal ? computedStyles[key] == expectedVal : true); + } + + return hasValue; + }; + + function validateCssValue(value) { + return !value ? '0' : + hasPx(value) || hasPercent(value) ? value : value + 'px'; + } + + function hasPx(value) { + return String(value).indexOf('px') > -1; + } + + function hasPercent(value) { + return String(value).indexOf('%') > -1; + + } + + var $mdUtil = { + dom: {}, + now: window.performance && window.performance.now ? + angular.bind(window.performance, window.performance.now) : Date.now || function() { + return new Date().getTime(); + }, + + /** + * Cross-version compatibility method to retrieve an option of a ngModel controller, + * which supports the breaking changes in the AngularJS snapshot (SHA 87a2ff76af5d0a9268d8eb84db5755077d27c84c). + * @param {!angular.ngModelCtrl} ngModelCtrl + * @param {!string} optionName + * @returns {Object|undefined} + */ + getModelOption: function (ngModelCtrl, optionName) { + if (!ngModelCtrl.$options) { + return; + } + + var $options = ngModelCtrl.$options; + + // The newer versions of AngularJS introduced a `getOption function and made the option values no longer + // visible on the $options object. + return $options.getOption ? $options.getOption(optionName) : $options[optionName]; + }, + + /** + * Bi-directional accessor/mutator used to easily update an element's + * property based on the current 'dir'ectional value. + */ + bidi : function(element, property, lValue, rValue) { + var ltr = !($document[0].dir == 'rtl' || $document[0].body.dir == 'rtl'); + + // If accessor + if (arguments.length == 0) return ltr ? 'ltr' : 'rtl'; + + // If mutator + var elem = angular.element(element); + + if (ltr && angular.isDefined(lValue)) { + elem.css(property, validateCssValue(lValue)); + } + else if (!ltr && angular.isDefined(rValue)) { + elem.css(property, validateCssValue(rValue)); + } + }, + + bidiProperty: function (element, lProperty, rProperty, value) { + var ltr = !($document[0].dir == 'rtl' || $document[0].body.dir == 'rtl'); + + var elem = angular.element(element); + + if (ltr && angular.isDefined(lProperty)) { + elem.css(lProperty, validateCssValue(value)); + elem.css(rProperty, ''); + } + else if (!ltr && angular.isDefined(rProperty)) { + elem.css(rProperty, validateCssValue(value)); + elem.css(lProperty, ''); + } + }, + + clientRect: function(element, offsetParent, isOffsetRect) { + var node = getNode(element); + offsetParent = getNode(offsetParent || node.offsetParent || document.body); + var nodeRect = node.getBoundingClientRect(); + + // The user can ask for an offsetRect: a rect relative to the offsetParent, + // or a clientRect: a rect relative to the page + var offsetRect = isOffsetRect ? + offsetParent.getBoundingClientRect() : + {left: 0, top: 0, width: 0, height: 0}; + return { + left: nodeRect.left - offsetRect.left, + top: nodeRect.top - offsetRect.top, + width: nodeRect.width, + height: nodeRect.height + }; + }, + offsetRect: function(element, offsetParent) { + return $mdUtil.clientRect(element, offsetParent, true); + }, + + // Annoying method to copy nodes to an array, thanks to IE + nodesToArray: function(nodes) { + nodes = nodes || []; + + var results = []; + for (var i = 0; i < nodes.length; ++i) { + results.push(nodes.item(i)); + } + return results; + }, + + /** + * Determines the absolute position of the viewport. + * Useful when making client rectangles absolute. + * @returns {number} + */ + getViewportTop: function() { + // If body scrolling is disabled, then use the cached viewport top value, otherwise get it + // fresh from the $window. + if ($mdUtil.disableScrollAround._count && $mdUtil.disableScrollAround._viewPortTop) { + return $mdUtil.disableScrollAround._viewPortTop; + } else { + return $window.scrollY || $window.pageYOffset || 0; + } + }, + + /** + * Finds the proper focus target by searching the DOM. + * + * @param containerEl + * @param attributeVal + * @returns {*} + */ + findFocusTarget: function(containerEl, attributeVal) { + var AUTO_FOCUS = this.prefixer('md-autofocus', true); + var elToFocus; + + elToFocus = scanForFocusable(containerEl, attributeVal || AUTO_FOCUS); + + if (!elToFocus && attributeVal != AUTO_FOCUS) { + // Scan for deprecated attribute + elToFocus = scanForFocusable(containerEl, this.prefixer('md-auto-focus', true)); + + if (!elToFocus) { + // Scan for fallback to 'universal' API + elToFocus = scanForFocusable(containerEl, AUTO_FOCUS); + } + } + + return elToFocus; + + /** + * Can target and nested children for specified Selector (attribute) + * whose value may be an expression that evaluates to True/False. + */ + function scanForFocusable(target, selector) { + var elFound, items = target[0].querySelectorAll(selector); + + // Find the last child element with the focus attribute + if (items && items.length){ + items.length && angular.forEach(items, function(it) { + it = angular.element(it); + + // Check the element for the md-autofocus class to ensure any associated expression + // evaluated to true. + var isFocusable = it.hasClass('md-autofocus'); + if (isFocusable) elFound = it; + }); + } + return elFound; + } + }, + + /** + * Disables scroll around the passed parent element. + * @param element Unused + * @param {!Element|!angular.JQLite} parent Element to disable scrolling within. + * Defaults to body if none supplied. + * @param options Object of options to modify functionality + * - disableScrollMask Boolean of whether or not to create a scroll mask element or + * use the passed parent element. + */ + disableScrollAround: function(element, parent, options) { + options = options || {}; + + $mdUtil.disableScrollAround._count = Math.max(0, $mdUtil.disableScrollAround._count || 0); + $mdUtil.disableScrollAround._count++; + + if ($mdUtil.disableScrollAround._restoreScroll) { + return $mdUtil.disableScrollAround._restoreScroll; + } + + var body = $document[0].body; + var restoreBody = disableBodyScroll(); + var restoreElement = disableElementScroll(parent); + + return $mdUtil.disableScrollAround._restoreScroll = function() { + if (--$mdUtil.disableScrollAround._count <= 0) { + delete $mdUtil.disableScrollAround._viewPortTop; + restoreBody(); + restoreElement(); + delete $mdUtil.disableScrollAround._restoreScroll; + } + }; + + /** + * Creates a virtual scrolling mask to prevent touchmove, keyboard, scrollbar clicking, + * and wheel events + */ + function disableElementScroll(element) { + element = angular.element(element || body); + + var scrollMask; + + if (options.disableScrollMask) { + scrollMask = element; + } else { + scrollMask = angular.element( + '
    ' + + '
    ' + + '
    '); + element.append(scrollMask); + } + + scrollMask.on('wheel', preventDefault); + scrollMask.on('touchmove', preventDefault); + + return function restoreElementScroll() { + scrollMask.off('wheel'); + scrollMask.off('touchmove'); + + if (!options.disableScrollMask && scrollMask[0].parentNode) { + scrollMask[0].parentNode.removeChild(scrollMask[0]); + } + }; + + function preventDefault(e) { + e.preventDefault(); + } + } + + // Converts the body to a position fixed block and translate it to the proper scroll position + function disableBodyScroll() { + var documentElement = $document[0].documentElement; + + var prevDocumentStyle = documentElement.style.cssText || ''; + var prevBodyStyle = body.style.cssText || ''; + + var viewportTop = $mdUtil.getViewportTop(); + $mdUtil.disableScrollAround._viewPortTop = viewportTop; + var clientWidth = body.clientWidth; + var hasVerticalScrollbar = body.scrollHeight > body.clientHeight + 1; + + // Scroll may be set on element (for example by overflow-y: scroll) + // but Chrome is reporting the scrollTop position always on . + // scrollElement will allow to restore the scrollTop position to proper target. + var scrollElement = documentElement.scrollTop > 0 ? documentElement : body; + + if (hasVerticalScrollbar) { + angular.element(body).css({ + position: 'fixed', + width: '100%', + top: -viewportTop + 'px' + }); + } + + if (body.clientWidth < clientWidth) { + body.style.overflow = 'hidden'; + } + + return function restoreScroll() { + // Reset the inline style CSS to the previous. + body.style.cssText = prevBodyStyle; + documentElement.style.cssText = prevDocumentStyle; + + // The scroll position while being fixed + scrollElement.scrollTop = viewportTop; + }; + } + + }, + + enableScrolling: function() { + var restoreFn = this.disableScrollAround._restoreScroll; + restoreFn && restoreFn(); + }, + + floatingScrollbars: function() { + if (this.floatingScrollbars.cached === undefined) { + var tempNode = angular.element('
    ').css({ + width: '100%', + 'z-index': -1, + position: 'absolute', + height: '35px', + 'overflow-y': 'scroll' + }); + tempNode.children().css('height', '60px'); + + $document[0].body.appendChild(tempNode[0]); + this.floatingScrollbars.cached = (tempNode[0].offsetWidth == tempNode[0].childNodes[0].offsetWidth); + tempNode.remove(); + } + return this.floatingScrollbars.cached; + }, + + // Mobile safari only allows you to set focus in click event listeners... + forceFocus: function(element) { + var node = element[0] || element; + + document.addEventListener('click', function focusOnClick(ev) { + if (ev.target === node && ev.$focus) { + node.focus(); + ev.stopImmediatePropagation(); + ev.preventDefault(); + node.removeEventListener('click', focusOnClick); + } + }, true); + + var newEvent = document.createEvent('MouseEvents'); + newEvent.initMouseEvent('click', false, true, window, {}, 0, 0, 0, 0, + false, false, false, false, 0, null); + newEvent.$material = true; + newEvent.$focus = true; + node.dispatchEvent(newEvent); + }, + + /** + * facade to build md-backdrop element with desired styles + * NOTE: Use $compile to trigger backdrop postLink function + */ + createBackdrop: function(scope, addClass) { + return $compile($mdUtil.supplant('', [addClass]))(scope); + }, + + /** + * supplant() method from Crockford's `Remedial Javascript` + * Equivalent to use of $interpolate; without dependency on + * interpolation symbols and scope. Note: the '{}' can + * be property names, property chains, or array indices. + */ + supplant: function(template, values, pattern) { + pattern = pattern || /\{([^{}]*)\}/g; + return template.replace(pattern, function(a, b) { + var p = b.split('.'), + r = values; + try { + for (var s in p) { + if (p.hasOwnProperty(s)) { + r = r[p[s]]; + } + } + } catch (e) { + r = a; + } + return (typeof r === 'string' || typeof r === 'number') ? r : a; + }); + }, + + fakeNgModel: function() { + return { + $fake: true, + $setTouched: angular.noop, + $setViewValue: function(value) { + this.$viewValue = value; + this.$render(value); + this.$viewChangeListeners.forEach(function(cb) { + cb(); + }); + }, + $isEmpty: function(value) { + return ('' + value).length === 0; + }, + $parsers: [], + $formatters: [], + $viewChangeListeners: [], + $render: angular.noop + }; + }, + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. + // @param wait Integer value of msecs to delay (since last debounce reset); default value 10 msecs + // @param invokeApply should the $timeout trigger $digest() dirty checking + debounce: function(func, wait, scope, invokeApply) { + var timer; + + return function debounced() { + var context = scope, + args = Array.prototype.slice.call(arguments); + + $timeout.cancel(timer); + timer = $timeout(function() { + + timer = undefined; + func.apply(context, args); + + }, wait || 10, invokeApply); + }; + }, + + // Returns a function that can only be triggered every `delay` milliseconds. + // In other words, the function will not be called unless it has been more + // than `delay` milliseconds since the last call. + throttle: function throttle(func, delay) { + var recent; + return function throttled() { + var context = this; + var args = arguments; + var now = $mdUtil.now(); + + if (!recent || (now - recent > delay)) { + func.apply(context, args); + recent = now; + } + }; + }, + + /** + * Measures the number of milliseconds taken to run the provided callback + * function. Uses a high-precision timer if available. + */ + time: function time(cb) { + var start = $mdUtil.now(); + cb(); + return $mdUtil.now() - start; + }, + + /** + * Create an implicit getter that caches its `getter()` + * lookup value + */ + valueOnUse : function (scope, key, getter) { + var value = null, args = Array.prototype.slice.call(arguments); + var params = (args.length > 3) ? args.slice(3) : []; + + Object.defineProperty(scope, key, { + get: function () { + if (value === null) value = getter.apply(scope, params); + return value; + } + }); + }, + + /** + * Get a unique ID. + * + * @returns {string} an unique numeric string + */ + nextUid: function() { + return '' + nextUniqueId++; + }, + + // Stop watchers and events from firing on a scope without destroying it, + // by disconnecting it from its parent and its siblings' linked lists. + disconnectScope: function disconnectScope(scope) { + if (!scope) return; + + // we can't destroy the root scope or a scope that has been already destroyed + if (scope.$root === scope) return; + if (scope.$$destroyed) return; + + var parent = scope.$parent; + scope.$$disconnected = true; + + // See Scope.$destroy + if (parent.$$childHead === scope) parent.$$childHead = scope.$$nextSibling; + if (parent.$$childTail === scope) parent.$$childTail = scope.$$prevSibling; + if (scope.$$prevSibling) scope.$$prevSibling.$$nextSibling = scope.$$nextSibling; + if (scope.$$nextSibling) scope.$$nextSibling.$$prevSibling = scope.$$prevSibling; + + scope.$$nextSibling = scope.$$prevSibling = null; + + }, + + // Undo the effects of disconnectScope above. + reconnectScope: function reconnectScope(scope) { + if (!scope) return; + + // we can't disconnect the root node or scope already disconnected + if (scope.$root === scope) return; + if (!scope.$$disconnected) return; + + var child = scope; + + var parent = child.$parent; + child.$$disconnected = false; + // See Scope.$new for this logic... + child.$$prevSibling = parent.$$childTail; + if (parent.$$childHead) { + parent.$$childTail.$$nextSibling = child; + parent.$$childTail = child; + } else { + parent.$$childHead = parent.$$childTail = child; + } + }, + + /** + * getClosest replicates jQuery.closest() to walk up the DOM tree until it finds a matching + * nodeName. + * + * @param {Node} el Element to start walking the DOM from + * @param {string|function} validateWith If a string is passed, it will be evaluated against + * each of the parent nodes' tag name. If a function is passed, the loop will call it with each + * of the parents and will use the return value to determine whether the node is a match. + * @param {boolean=} onlyParent Only start checking from the parent element, not `el`. + * @returns {Node|null} closest matching parent Node or null if not found + */ + getClosest: function getClosest(el, validateWith, onlyParent) { + if (angular.isString(validateWith)) { + var tagName = validateWith.toUpperCase(); + validateWith = function(el) { + return el.nodeName.toUpperCase() === tagName; + }; + } + + if (el instanceof angular.element) el = el[0]; + if (onlyParent) el = el.parentNode; + if (!el) return null; + + do { + if (validateWith(el)) { + return el; + } + } while (el = el.parentNode); + + return null; + }, + + /** + * Build polyfill for the Node.contains feature (if needed) + * @param {Node} node + * @param {Node} child + * @returns {Node} + */ + elementContains: function(node, child) { + var hasContains = (window.Node && window.Node.prototype && Node.prototype.contains); + var findFn = hasContains ? angular.bind(node, node.contains) : angular.bind(node, function(arg) { + // compares the positions of two nodes and returns a bitmask + return (node === child) || !!(this.compareDocumentPosition(arg) & 16); + }); + + return findFn(child); + }, + + /** + * Functional equivalent for $element.filter(‘md-bottom-sheet’) + * useful with interimElements where the element and its container are important... + * + * @param {angular.JQLite} element to scan + * @param {string} nodeName of node to find (e.g. 'md-dialog') + * @param {boolean=} scanDeep optional flag to allow deep scans; defaults to 'false'. + * @param {boolean=} warnNotFound optional flag to enable log warnings; defaults to false + */ + extractElementByName: function(element, nodeName, scanDeep, warnNotFound) { + var found = scanTree(element); + if (!found && !!warnNotFound) { + $log.warn($mdUtil.supplant("Unable to find node '{0}' in element '{1}'.",[nodeName, element[0].outerHTML])); + } + + return angular.element(found || element); + + /** + * Breadth-First tree scan for element with matching `nodeName` + */ + function scanTree(element) { + return scanLevel(element) || (scanDeep ? scanChildren(element) : null); + } + + /** + * Case-insensitive scan of current elements only (do not descend). + */ + function scanLevel(element) { + if (element) { + for (var i = 0, len = element.length; i < len; i++) { + if (element[i].nodeName.toLowerCase() === nodeName) { + return element[i]; + } + } + } + return null; + } + + /** + * Scan children of specified node + */ + function scanChildren(element) { + var found; + if (element) { + for (var i = 0, len = element.length; i < len; i++) { + var target = element[i]; + if (!found) { + for (var j = 0, numChild = target.childNodes.length; j < numChild; j++) { + found = found || scanTree([target.childNodes[j]]); + } + } + } + } + return found; + } + + }, + + /** + * Give optional properties with no value a boolean true if attr provided or false otherwise + */ + initOptionalProperties: function(scope, attr, defaults) { + defaults = defaults || {}; + angular.forEach(scope.$$isolateBindings, function(binding, key) { + if (binding.optional && angular.isUndefined(scope[key])) { + var attrIsDefined = angular.isDefined(attr[binding.attrName]); + scope[key] = angular.isDefined(defaults[key]) ? defaults[key] : attrIsDefined; + } + }); + }, + + /** + * Alternative to $timeout calls with 0 delay. + * nextTick() coalesces all calls within a single frame + * to minimize $digest thrashing + * + * @param {Function} callback function to be called after the tick + * @param {boolean} digest true to call $rootScope.$digest() after callback + * @param scope scope associated with callback. If the scope is destroyed, the callback will + * be skipped. + * @returns {*} + */ + nextTick: function(callback, digest, scope) { + // grab function reference for storing state details + var nextTick = $mdUtil.nextTick; + var timeout = nextTick.timeout; + var queue = nextTick.queue || []; + + // add callback to the queue + queue.push({scope: scope, callback: callback}); + + // set default value for digest + if (digest == null) digest = true; + + // store updated digest/queue values + nextTick.digest = nextTick.digest || digest; + nextTick.queue = queue; + + // either return existing timeout or create a new one + return timeout || (nextTick.timeout = $timeout(processQueue, 0, false)); + + /** + * Grab a copy of the current queue + * Clear the queue for future use + * Process the existing queue + * Trigger digest if necessary + */ + function processQueue() { + var queue = nextTick.queue; + var digest = nextTick.digest; + + nextTick.queue = []; + nextTick.timeout = null; + nextTick.digest = false; + + queue.forEach(function(queueItem) { + var skip = queueItem.scope && queueItem.scope.$$destroyed; + if (!skip) { + queueItem.callback(); + } + }); + + if (digest) $rootScope.$digest(); + } + }, + + /** + * Processes a template and replaces the start/end symbols if the application has + * overridden them. + * + * @param template The template to process whose start/end tags may be replaced. + * @returns {*} + */ + processTemplate: function(template) { + if (usesStandardSymbols) { + return template; + } else { + if (!template || !angular.isString(template)) return template; + return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); + } + }, + + /** + * Scan up dom hierarchy for enabled parent; + */ + getParentWithPointerEvents: function (element) { + var parent = element.parent(); + + // jqLite might return a non-null, but still empty, parent; so check for parent and length + while (hasComputedStyle(parent, 'pointer-events', 'none')) { + parent = parent.parent(); + } + + return parent; + }, + + getNearestContentElement: function (element) { + var current = element.parent()[0]; + // Look for the nearest parent md-content, stopping at the rootElement. + while (current && current !== $rootElement[0] && current !== document.body && current.nodeName.toUpperCase() !== 'MD-CONTENT') { + current = current.parentNode; + } + return current; + }, + + /** + * Checks if the current browser is natively supporting the `sticky` position. + * @returns {string} supported sticky property name + */ + checkStickySupport: function() { + var stickyProp; + var testEl = angular.element('
    '); + $document[0].body.appendChild(testEl[0]); + + var stickyProps = ['sticky', '-webkit-sticky']; + for (var i = 0; i < stickyProps.length; ++i) { + testEl.css({ + position: stickyProps[i], + top: 0, + 'z-index': 2 + }); + + if (testEl.css('position') == stickyProps[i]) { + stickyProp = stickyProps[i]; + break; + } + } + + testEl.remove(); + + return stickyProp; + }, + + /** + * Parses an attribute value, mostly a string. + * By default checks for negated values and returns `false´ if present. + * Negated values are: (native falsy) and negative strings like: + * `false` or `0`. + * @param value Attribute value which should be parsed. + * @param negatedCheck When set to false, won't check for negated values. + * @returns {boolean} + */ + parseAttributeBoolean: function(value, negatedCheck) { + return value === '' || !!value && (negatedCheck === false || value !== 'false' && value !== '0'); + }, + + hasComputedStyle: hasComputedStyle, + + /** + * Returns true if the parent form of the element has been submitted. + * + * @param element An AngularJS or HTML5 element. + * + * @returns {boolean} + */ + isParentFormSubmitted: function(element) { + var parent = $mdUtil.getClosest(element, 'form'); + var form = parent ? angular.element(parent).controller('form') : null; + + return form ? form.$submitted : false; + }, + + /** + * Animate the requested element's scrollTop to the requested scrollPosition with basic easing. + * + * @param {!Element} element The element to scroll. + * @param {number} scrollEnd The new/final scroll position. + * @param {number=} duration Duration of the scroll. Default is 1000ms. + */ + animateScrollTo: function(element, scrollEnd, duration) { + var scrollStart = element.scrollTop; + var scrollChange = scrollEnd - scrollStart; + var scrollingDown = scrollStart < scrollEnd; + var startTime = $mdUtil.now(); + + $$rAF(scrollChunk); + + function scrollChunk() { + var newPosition = calculateNewPosition(); + + element.scrollTop = newPosition; + + if (scrollingDown ? newPosition < scrollEnd : newPosition > scrollEnd) { + $$rAF(scrollChunk); + } + } + + function calculateNewPosition() { + var easeDuration = duration || 1000; + var currentTime = $mdUtil.now() - startTime; + + return ease(currentTime, scrollStart, scrollChange, easeDuration); + } + + function ease(currentTime, start, change, duration) { + // If the duration has passed (which can occur if our app loses focus due to $$rAF), jump + // straight to the proper position + if (currentTime > duration) { + return start + change; + } + + var ts = (currentTime /= duration) * currentTime; + var tc = ts * currentTime; + + return start + change * (-2 * tc + 3 * ts); + } + }, + + /** + * Provides an easy mechanism for removing duplicates from an array. + * + * var myArray = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]; + * + * $mdUtil.uniq(myArray) => [1, 2, 3, 4] + * + * @param {array} array The array whose unique values should be returned. + * + * @returns {array} A copy of the array containing only unique values. + */ + uniq: function(array) { + if (!array) { return; } + + return array.filter(function(value, index, self) { + return self.indexOf(value) === index; + }); + }, + + /** + * Gets the inner HTML content of the given HTMLElement. + * Only intended for use with SVG or Symbol elements in IE11. + * @param {Element} element + * @returns {string} the inner HTML of the element passed in + */ + getInnerHTML: function(element) { + // For SVG or Symbol elements, innerHTML returns `undefined` in IE. + // Reference: https://stackoverflow.com/q/28129956/633107 + // The XMLSerializer API is supported on IE11 and is the recommended workaround. + var serializer = new XMLSerializer(); + + return Array.prototype.map.call(element.childNodes, function (child) { + return serializer.serializeToString(child); + }).join(''); + }, + + /** + * Gets the outer HTML content of the given HTMLElement. + * Only intended for use with SVG or Symbol elements in IE11. + * @param {Element} element + * @returns {string} the outer HTML of the element passed in + */ + getOuterHTML: function(element) { + // For SVG or Symbol elements, outerHTML returns `undefined` in IE. + // Reference: https://stackoverflow.com/q/29888050/633107 + // The XMLSerializer API is supported on IE11 and is the recommended workaround. + var serializer = new XMLSerializer(); + return serializer.serializeToString(element); + }, + + /** + * Support: IE 9-11 only + * documentMode is an IE-only property + * http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx + */ + msie: window.document.documentMode + }; + + // Instantiate other namespace utility methods + + $mdUtil.dom.animator = $$mdAnimate($mdUtil); + + return $mdUtil; + + function getNode(el) { + return el[0] || el; + } +} + +/* + * Since removing jQuery from the demos, some code that uses `element.focus()` is broken. + * We need to add `element.focus()`, because it's testable unlike `element[0].focus`. + */ + +angular.element.prototype.focus = angular.element.prototype.focus || function() { + if (this.length) { + this[0].focus(); + } + return this; +}; +angular.element.prototype.blur = angular.element.prototype.blur || function() { + if (this.length) { + this[0].blur(); + } + return this; +}; + +})(); +(function(){ +"use strict"; + +// Polyfill angular < 1.4 (provide $animateCss) +angular + .module('material.core') + .factory('$$mdAnimate', ["$q", "$timeout", "$mdConstant", "$animateCss", function($q, $timeout, $mdConstant, $animateCss){ + + // Since $$mdAnimate is injected into $mdUtil... use a wrapper function + // to subsequently inject $mdUtil as an argument to the AnimateDomUtils + + return function($mdUtil) { + return AnimateDomUtils($mdUtil, $q, $timeout, $mdConstant, $animateCss); + }; + }]); + +/** + * Factory function that requires special injections + */ +function AnimateDomUtils($mdUtil, $q, $timeout, $mdConstant, $animateCss) { + var self; + return self = { + /** + * + */ + translate3d : function(target, from, to, options) { + return $animateCss(target, { + from: from, + to: to, + addClass: options.transitionInClass, + removeClass: options.transitionOutClass, + duration: options.duration + }) + .start() + .then(function(){ + // Resolve with reverser function... + return reverseTranslate; + }); + + /** + * Specific reversal of the request translate animation above... + */ + function reverseTranslate (newFrom) { + return $animateCss(target, { + to: newFrom || from, + addClass: options.transitionOutClass, + removeClass: options.transitionInClass, + duration: options.duration + }).start(); + + } + }, + + /** + * Listen for transitionEnd event (with optional timeout) + * Announce completion or failure via promise handlers + */ + waitTransitionEnd: function (element, opts) { + var TIMEOUT = 3000; // fallback is 3 secs + + return $q(function(resolve, reject){ + opts = opts || { }; + + // If there is no transition is found, resolve immediately + // + // NOTE: using $mdUtil.nextTick() causes delays/issues + if (noTransitionFound(opts.cachedTransitionStyles)) { + TIMEOUT = 0; + } + + var timer = $timeout(finished, opts.timeout || TIMEOUT); + element.on($mdConstant.CSS.TRANSITIONEND, finished); + + /** + * Upon timeout or transitionEnd, reject or resolve (respectively) this promise. + * NOTE: Make sure this transitionEnd didn't bubble up from a child + */ + function finished(ev) { + if (ev && ev.target !== element[0]) return; + + if (ev) $timeout.cancel(timer); + element.off($mdConstant.CSS.TRANSITIONEND, finished); + + // Never reject since ngAnimate may cause timeouts due missed transitionEnd events + resolve(); + + } + + /** + * Checks whether or not there is a transition. + * + * @param styles The cached styles to use for the calculation. If null, getComputedStyle() + * will be used. + * + * @returns {boolean} True if there is no transition/duration; false otherwise. + */ + function noTransitionFound(styles) { + styles = styles || window.getComputedStyle(element[0]); + + return styles.transitionDuration == '0s' || (!styles.transition && !styles.transitionProperty); + } + + }); + }, + + calculateTransformValues: function (element, originator) { + var origin = originator.element; + var bounds = originator.bounds; + + if (origin || bounds) { + var originBnds = origin ? self.clientRect(origin) || currentBounds() : self.copyRect(bounds); + var dialogRect = self.copyRect(element[0].getBoundingClientRect()); + var dialogCenterPt = self.centerPointFor(dialogRect); + var originCenterPt = self.centerPointFor(originBnds); + + return { + centerX: originCenterPt.x - dialogCenterPt.x, + centerY: originCenterPt.y - dialogCenterPt.y, + scaleX: Math.round(100 * Math.min(0.5, originBnds.width / dialogRect.width)) / 100, + scaleY: Math.round(100 * Math.min(0.5, originBnds.height / dialogRect.height)) / 100 + }; + } + return {centerX: 0, centerY: 0, scaleX: 0.5, scaleY: 0.5}; + + /** + * This is a fallback if the origin information is no longer valid, then the + * origin bounds simply becomes the current bounds for the dialogContainer's parent + */ + function currentBounds() { + var cntr = element ? element.parent() : null; + var parent = cntr ? cntr.parent() : null; + + return parent ? self.clientRect(parent) : null; + } + }, + + /** + * Calculate the zoom transform from dialog to origin. + * + * We use this to set the dialog position immediately; + * then the md-transition-in actually translates back to + * `translate3d(0,0,0) scale(1.0)`... + * + * NOTE: all values are rounded to the nearest integer + */ + calculateZoomToOrigin: function (element, originator) { + var zoomTemplate = "translate3d( {centerX}px, {centerY}px, 0 ) scale( {scaleX}, {scaleY} )"; + var buildZoom = angular.bind(null, $mdUtil.supplant, zoomTemplate); + + return buildZoom(self.calculateTransformValues(element, originator)); + }, + + /** + * Calculate the slide transform from panel to origin. + * NOTE: all values are rounded to the nearest integer + */ + calculateSlideToOrigin: function (element, originator) { + var slideTemplate = "translate3d( {centerX}px, {centerY}px, 0 )"; + var buildSlide = angular.bind(null, $mdUtil.supplant, slideTemplate); + + return buildSlide(self.calculateTransformValues(element, originator)); + }, + + /** + * Enhance raw values to represent valid css stylings... + */ + toCss : function(raw) { + var css = { }; + var lookups = 'left top right bottom width height x y min-width min-height max-width max-height'; + + angular.forEach(raw, function(value,key) { + if (angular.isUndefined(value)) return; + + if (lookups.indexOf(key) >= 0) { + css[key] = value + 'px'; + } else { + switch (key) { + case 'transition': + convertToVendor(key, $mdConstant.CSS.TRANSITION, value); + break; + case 'transform': + convertToVendor(key, $mdConstant.CSS.TRANSFORM, value); + break; + case 'transformOrigin': + convertToVendor(key, $mdConstant.CSS.TRANSFORM_ORIGIN, value); + break; + case 'font-size': + css['font-size'] = value; // font sizes aren't always in px + break; + } + } + }); + + return css; + + function convertToVendor(key, vendor, value) { + angular.forEach(vendor.split(' '), function (key) { + css[key] = value; + }); + } + }, + + /** + * Convert the translate CSS value to key/value pair(s). + */ + toTransformCss: function (transform, addTransition, transition) { + var css = {}; + angular.forEach($mdConstant.CSS.TRANSFORM.split(' '), function (key) { + css[key] = transform; + }); + + if (addTransition) { + transition = transition || "all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1) !important"; + css.transition = transition; + } + + return css; + }, + + /** + * Clone the Rect and calculate the height/width if needed + */ + copyRect: function (source, destination) { + if (!source) return null; + + destination = destination || {}; + + angular.forEach('left top right bottom width height'.split(' '), function (key) { + destination[key] = Math.round(source[key]); + }); + + destination.width = destination.width || (destination.right - destination.left); + destination.height = destination.height || (destination.bottom - destination.top); + + return destination; + }, + + /** + * Calculate ClientRect of element; return null if hidden or zero size + */ + clientRect: function (element) { + var bounds = angular.element(element)[0].getBoundingClientRect(); + var isPositiveSizeClientRect = function (rect) { + return rect && (rect.width > 0) && (rect.height > 0); + }; + + // If the event origin element has zero size, it has probably been hidden. + return isPositiveSizeClientRect(bounds) ? self.copyRect(bounds) : null; + }, + + /** + * Calculate 'rounded' center point of Rect + */ + centerPointFor: function (targetRect) { + return targetRect ? { + x: Math.round(targetRect.left + (targetRect.width / 2)), + y: Math.round(targetRect.top + (targetRect.height / 2)) + } : { x : 0, y : 0 }; + } + + }; +} + + +})(); +(function(){ +"use strict"; + +if (angular.version.minor >= 4) { + angular.module('material.core.animate', []); +} else { +(function() { + "use strict"; + + var forEach = angular.forEach; + + var WEBKIT = angular.isDefined(document.documentElement.style.WebkitAppearance); + var TRANSITION_PROP = WEBKIT ? 'WebkitTransition' : 'transition'; + var ANIMATION_PROP = WEBKIT ? 'WebkitAnimation' : 'animation'; + var PREFIX = WEBKIT ? '-webkit-' : ''; + + var TRANSITION_EVENTS = (WEBKIT ? 'webkitTransitionEnd ' : '') + 'transitionend'; + var ANIMATION_EVENTS = (WEBKIT ? 'webkitAnimationEnd ' : '') + 'animationend'; + + var $$ForceReflowFactory = ['$document', function($document) { + return function() { + return $document[0].body.clientWidth + 1; + }; + }]; + + var $$rAFMutexFactory = ['$$rAF', function($$rAF) { + return function() { + var passed = false; + $$rAF(function() { + passed = true; + }); + return function(fn) { + passed ? fn() : $$rAF(fn); + }; + }; + }]; + + var $$AnimateRunnerFactory = ['$q', '$$rAFMutex', function($q, $$rAFMutex) { + var INITIAL_STATE = 0; + var DONE_PENDING_STATE = 1; + var DONE_COMPLETE_STATE = 2; + + function AnimateRunner(host) { + this.setHost(host); + + this._doneCallbacks = []; + this._runInAnimationFrame = $$rAFMutex(); + this._state = 0; + } + + AnimateRunner.prototype = { + setHost: function(host) { + this.host = host || {}; + }, + + done: function(fn) { + if (this._state === DONE_COMPLETE_STATE) { + fn(); + } else { + this._doneCallbacks.push(fn); + } + }, + + progress: angular.noop, + + getPromise: function() { + if (!this.promise) { + var self = this; + this.promise = $q(function(resolve, reject) { + self.done(function(status) { + status === false ? reject() : resolve(); + }); + }); + } + return this.promise; + }, + + then: function(resolveHandler, rejectHandler) { + return this.getPromise().then(resolveHandler, rejectHandler); + }, + + 'catch': function(handler) { + return this.getPromise()['catch'](handler); + }, + + 'finally': function(handler) { + return this.getPromise()['finally'](handler); + }, + + pause: function() { + if (this.host.pause) { + this.host.pause(); + } + }, + + resume: function() { + if (this.host.resume) { + this.host.resume(); + } + }, + + end: function() { + if (this.host.end) { + this.host.end(); + } + this._resolve(true); + }, + + cancel: function() { + if (this.host.cancel) { + this.host.cancel(); + } + this._resolve(false); + }, + + complete: function(response) { + var self = this; + if (self._state === INITIAL_STATE) { + self._state = DONE_PENDING_STATE; + self._runInAnimationFrame(function() { + self._resolve(response); + }); + } + }, + + _resolve: function(response) { + if (this._state !== DONE_COMPLETE_STATE) { + forEach(this._doneCallbacks, function(fn) { + fn(response); + }); + this._doneCallbacks.length = 0; + this._state = DONE_COMPLETE_STATE; + } + } + }; + + // Polyfill AnimateRunner.all which is used by input animations + AnimateRunner.all = function(runners, callback) { + var count = 0; + var status = true; + forEach(runners, function(runner) { + runner.done(onProgress); + }); + + function onProgress(response) { + status = status && response; + if (++count === runners.length) { + callback(status); + } + } + }; + + return AnimateRunner; + }]; + + angular + .module('material.core.animate', []) + .factory('$$forceReflow', $$ForceReflowFactory) + .factory('$$AnimateRunner', $$AnimateRunnerFactory) + .factory('$$rAFMutex', $$rAFMutexFactory) + .factory('$animateCss', ['$window', '$$rAF', '$$AnimateRunner', '$$forceReflow', '$$jqLite', '$timeout', '$animate', + function($window, $$rAF, $$AnimateRunner, $$forceReflow, $$jqLite, $timeout, $animate) { + + function init(element, options) { + + var temporaryStyles = []; + var node = getDomNode(element); + var areAnimationsAllowed = node && $animate.enabled(); + + var hasCompleteStyles = false; + var hasCompleteClasses = false; + + if (areAnimationsAllowed) { + if (options.transitionStyle) { + temporaryStyles.push([PREFIX + 'transition', options.transitionStyle]); + } + + if (options.keyframeStyle) { + temporaryStyles.push([PREFIX + 'animation', options.keyframeStyle]); + } + + if (options.delay) { + temporaryStyles.push([PREFIX + 'transition-delay', options.delay + 's']); + } + + if (options.duration) { + temporaryStyles.push([PREFIX + 'transition-duration', options.duration + 's']); + } + + hasCompleteStyles = options.keyframeStyle || + (options.to && (options.duration > 0 || options.transitionStyle)); + hasCompleteClasses = !!options.addClass || !!options.removeClass; + + blockTransition(element, true); + } + + var hasCompleteAnimation = areAnimationsAllowed && (hasCompleteStyles || hasCompleteClasses); + + applyAnimationFromStyles(element, options); + + var animationClosed = false; + var events, eventFn; + + return { + close: $window.close, + start: function() { + var runner = new $$AnimateRunner(); + waitUntilQuiet(function() { + blockTransition(element, false); + if (!hasCompleteAnimation) { + return close(); + } + + forEach(temporaryStyles, function(entry) { + var key = entry[0]; + var value = entry[1]; + node.style[camelCase(key)] = value; + }); + + applyClasses(element, options); + + var timings = computeTimings(element); + if (timings.duration === 0) { + return close(); + } + + var moreStyles = []; + + if (options.easing) { + if (timings.transitionDuration) { + moreStyles.push([PREFIX + 'transition-timing-function', options.easing]); + } + if (timings.animationDuration) { + moreStyles.push([PREFIX + 'animation-timing-function', options.easing]); + } + } + + if (options.delay && timings.animationDelay) { + moreStyles.push([PREFIX + 'animation-delay', options.delay + 's']); + } + + if (options.duration && timings.animationDuration) { + moreStyles.push([PREFIX + 'animation-duration', options.duration + 's']); + } + + forEach(moreStyles, function(entry) { + var key = entry[0]; + var value = entry[1]; + node.style[camelCase(key)] = value; + temporaryStyles.push(entry); + }); + + var maxDelay = timings.delay; + var maxDelayTime = maxDelay * 1000; + var maxDuration = timings.duration; + var maxDurationTime = maxDuration * 1000; + var startTime = Date.now(); + + events = []; + if (timings.transitionDuration) { + events.push(TRANSITION_EVENTS); + } + if (timings.animationDuration) { + events.push(ANIMATION_EVENTS); + } + events = events.join(' '); + eventFn = function(event) { + event.stopPropagation(); + var ev = event.originalEvent || event; + var timeStamp = ev.timeStamp || Date.now(); + var elapsedTime = parseFloat(ev.elapsedTime.toFixed(3)); + if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) { + close(); + } + }; + element.on(events, eventFn); + + applyAnimationToStyles(element, options); + + $timeout(close, maxDelayTime + maxDurationTime * 1.5, false); + }); + + return runner; + + function close() { + if (animationClosed) return; + animationClosed = true; + + if (events && eventFn) { + element.off(events, eventFn); + } + applyClasses(element, options); + applyAnimationStyles(element, options); + forEach(temporaryStyles, function(entry) { + node.style[camelCase(entry[0])] = ''; + }); + runner.complete(true); + return runner; + } + } + }; + } + + function applyClasses(element, options) { + if (options.addClass) { + $$jqLite.addClass(element, options.addClass); + options.addClass = null; + } + if (options.removeClass) { + $$jqLite.removeClass(element, options.removeClass); + options.removeClass = null; + } + } + + function computeTimings(element) { + var node = getDomNode(element); + var cs = $window.getComputedStyle(node); + var tdr = parseMaxTime(cs[prop('transitionDuration')]); + var adr = parseMaxTime(cs[prop('animationDuration')]); + var tdy = parseMaxTime(cs[prop('transitionDelay')]); + var ady = parseMaxTime(cs[prop('animationDelay')]); + + adr *= (parseInt(cs[prop('animationIterationCount')], 10) || 1); + var duration = Math.max(adr, tdr); + var delay = Math.max(ady, tdy); + + return { + duration: duration, + delay: delay, + animationDuration: adr, + transitionDuration: tdr, + animationDelay: ady, + transitionDelay: tdy + }; + + function prop(key) { + return WEBKIT ? 'Webkit' + key.charAt(0).toUpperCase() + key.substr(1) + : key; + } + } + + function parseMaxTime(str) { + var maxValue = 0; + var values = (str || "").split(/\s*,\s*/); + forEach(values, function(value) { + // it's always safe to consider only second values and omit `ms` values since + // getComputedStyle will always handle the conversion for us + if (value.charAt(value.length - 1) == 's') { + value = value.substring(0, value.length - 1); + } + value = parseFloat(value) || 0; + maxValue = maxValue ? Math.max(value, maxValue) : value; + }); + return maxValue; + } + + var cancelLastRAFRequest; + var rafWaitQueue = []; + function waitUntilQuiet(callback) { + if (cancelLastRAFRequest) { + cancelLastRAFRequest(); // cancels the request + } + rafWaitQueue.push(callback); + cancelLastRAFRequest = $$rAF(function() { + cancelLastRAFRequest = null; + + // DO NOT REMOVE THIS LINE OR REFACTOR OUT THE `pageWidth` variable. + // PLEASE EXAMINE THE `$$forceReflow` service to understand why. + var pageWidth = $$forceReflow(); + + // we use a for loop to ensure that if the queue is changed + // during this looping then it will consider new requests + for (var i = 0; i < rafWaitQueue.length; i++) { + rafWaitQueue[i](pageWidth); + } + rafWaitQueue.length = 0; + }); + } + + function applyAnimationStyles(element, options) { + applyAnimationFromStyles(element, options); + applyAnimationToStyles(element, options); + } + + function applyAnimationFromStyles(element, options) { + if (options.from) { + element.css(options.from); + options.from = null; + } + } + + function applyAnimationToStyles(element, options) { + if (options.to) { + element.css(options.to); + options.to = null; + } + } + + function getDomNode(element) { + for (var i = 0; i < element.length; i++) { + if (element[i].nodeType === 1) return element[i]; + } + } + + function blockTransition(element, bool) { + var node = getDomNode(element); + var key = camelCase(PREFIX + 'transition-delay'); + node.style[key] = bool ? '-9999s' : ''; + } + + return init; + }]); + + /** + * Older browsers [FF31] expect camelCase + * property keys. + * e.g. + * animation-duration --> animationDuration + */ + function camelCase(str) { + return str.replace(/-[a-z]/g, function(str) { + return str.charAt(1).toUpperCase(); + }); + } + +})(); + +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.core.aria + * @description + * Aria Expectations for AngularJS Material components. + */ +MdAriaService.$inject = ["$$rAF", "$log", "$window", "$interpolate"]; +angular + .module('material.core') + .provider('$mdAria', MdAriaProvider); + +/** + * @ngdoc service + * @name $mdAriaProvider + * @module material.core.aria + * + * @description + * + * Modify options of the `$mdAria` service, which will be used by most of the AngularJS Material + * components. + * + * You are able to disable `$mdAria` warnings, by using the following markup. + * + * + * app.config(function($mdAriaProvider) { + * // Globally disables all ARIA warnings. + * $mdAriaProvider.disableWarnings(); + * }); + * + * + */ +function MdAriaProvider() { + + var config = { + /** Whether we should show ARIA warnings in the console if labels are missing on the element */ + showWarnings: true + }; + + return { + disableWarnings: disableWarnings, + $get: ["$$rAF", "$log", "$window", "$interpolate", function($$rAF, $log, $window, $interpolate) { + return MdAriaService.apply(config, arguments); + }] + }; + + /** + * @ngdoc method + * @name $mdAriaProvider#disableWarnings + * @description Disables all ARIA warnings generated by AngularJS Material. + */ + function disableWarnings() { + config.showWarnings = false; + } +} + +/* + * @ngInject + */ +function MdAriaService($$rAF, $log, $window, $interpolate) { + + // Load the showWarnings option from the current context and store it inside of a scope variable, + // because the context will be probably lost in some function calls. + var showWarnings = this.showWarnings; + + return { + expect: expect, + expectAsync: expectAsync, + expectWithText: expectWithText, + expectWithoutText: expectWithoutText, + getText: getText, + hasAriaLabel: hasAriaLabel, + parentHasAriaLabel: parentHasAriaLabel + }; + + /** + * Check if expected attribute has been specified on the target element or child + * @param element + * @param attrName + * @param {optional} defaultValue What to set the attr to if no value is found + */ + function expect(element, attrName, defaultValue) { + + var node = angular.element(element)[0] || element; + + // if node exists and neither it nor its children have the attribute + if (node && + ((!node.hasAttribute(attrName) || + node.getAttribute(attrName).length === 0) && + !childHasAttribute(node, attrName))) { + + defaultValue = angular.isString(defaultValue) ? defaultValue.trim() : ''; + if (defaultValue.length) { + element.attr(attrName, defaultValue); + } else if (showWarnings) { + $log.warn('ARIA: Attribute "', attrName, '", required for accessibility, is missing on node:', node); + } + + } + } + + function expectAsync(element, attrName, defaultValueGetter) { + // Problem: when retrieving the element's contents synchronously to find the label, + // the text may not be defined yet in the case of a binding. + // There is a higher chance that a binding will be defined if we wait one frame. + $$rAF(function() { + expect(element, attrName, defaultValueGetter()); + }); + } + + function expectWithText(element, attrName) { + var content = getText(element) || ""; + var hasBinding = content.indexOf($interpolate.startSymbol()) > -1; + + if (hasBinding) { + expectAsync(element, attrName, function() { + return getText(element); + }); + } else { + expect(element, attrName, content); + } + } + + function expectWithoutText(element, attrName) { + var content = getText(element); + var hasBinding = content.indexOf($interpolate.startSymbol()) > -1; + + if (!hasBinding && !content) { + expect(element, attrName, content); + } + } + + function getText(element) { + element = element[0] || element; + var walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, false); + var text = ''; + + var node; + while (node = walker.nextNode()) { + if (!isAriaHiddenNode(node)) { + text += node.textContent; + } + } + + return text.trim() || ''; + + function isAriaHiddenNode(node) { + while (node.parentNode && (node = node.parentNode) !== element) { + if (node.getAttribute && node.getAttribute('aria-hidden') === 'true') { + return true; + } + } + } + } + + function childHasAttribute(node, attrName) { + var hasChildren = node.hasChildNodes(), + hasAttr = false; + + function isHidden(el) { + var style = el.currentStyle ? el.currentStyle : $window.getComputedStyle(el); + return (style.display === 'none'); + } + + if (hasChildren) { + var children = node.childNodes; + for (var i=0; i < children.length; i++) { + var child = children[i]; + if (child.nodeType === 1 && child.hasAttribute(attrName)) { + if (!isHidden(child)) { + hasAttr = true; + } + } + } + } + return hasAttr; + } + + /** + * Check if expected element has aria label attribute + * @param element + */ + function hasAriaLabel(element) { + var node = angular.element(element)[0] || element; + + /* Check if compatible node type (ie: not HTML Document node) */ + if (!node.hasAttribute) { + return false; + } + + /* Check label or description attributes */ + return node.hasAttribute('aria-label') || node.hasAttribute('aria-labelledby') || node.hasAttribute('aria-describedby'); + } + + /** + * Check if expected element's parent has aria label attribute and has valid role and tagName + * @param element + * @param {optional} level Number of levels deep search should be performed + */ + function parentHasAriaLabel(element, level) { + level = level || 1; + var node = angular.element(element)[0] || element; + if (!node.parentNode) { + return false; + } + if (performCheck(node.parentNode)) { + return true; + } + level--; + if (level) { + return parentHasAriaLabel(node.parentNode, level); + } + return false; + + function performCheck(parentNode) { + if (!hasAriaLabel(parentNode)) { + return false; + } + /* Perform role blacklist check */ + if (parentNode.hasAttribute('role')) { + switch (parentNode.getAttribute('role').toLowerCase()) { + case 'command': + case 'definition': + case 'directory': + case 'grid': + case 'list': + case 'listitem': + case 'log': + case 'marquee': + case 'menu': + case 'menubar': + case 'note': + case 'presentation': + case 'separator': + case 'scrollbar': + case 'status': + case 'tablist': + return false; + } + } + /* Perform tagName blacklist check */ + switch (parentNode.tagName.toLowerCase()) { + case 'abbr': + case 'acronym': + case 'address': + case 'applet': + case 'audio': + case 'b': + case 'bdi': + case 'bdo': + case 'big': + case 'blockquote': + case 'br': + case 'canvas': + case 'caption': + case 'center': + case 'cite': + case 'code': + case 'col': + case 'data': + case 'dd': + case 'del': + case 'dfn': + case 'dir': + case 'div': + case 'dl': + case 'em': + case 'embed': + case 'fieldset': + case 'figcaption': + case 'font': + case 'h1': + case 'h2': + case 'h3': + case 'h4': + case 'h5': + case 'h6': + case 'hgroup': + case 'html': + case 'i': + case 'ins': + case 'isindex': + case 'kbd': + case 'keygen': + case 'label': + case 'legend': + case 'li': + case 'map': + case 'mark': + case 'menu': + case 'object': + case 'ol': + case 'output': + case 'pre': + case 'presentation': + case 'q': + case 'rt': + case 'ruby': + case 'samp': + case 'small': + case 'source': + case 'span': + case 'status': + case 'strike': + case 'strong': + case 'sub': + case 'sup': + case 'svg': + case 'tbody': + case 'td': + case 'th': + case 'thead': + case 'time': + case 'tr': + case 'track': + case 'tt': + case 'ul': + case 'var': + return false; + } + return true; + } + } +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.core.compiler + * @description + * AngularJS Material template and element compiler. + */ +angular + .module('material.core') + .provider('$mdCompiler', MdCompilerProvider); + +/** + * @ngdoc service + * @name $mdCompilerProvider + * @module material.core.compiler + * @description + * The `$mdCompiler` is able to respect the AngularJS `$compileProvider.preAssignBindingsEnabled` + * state when using AngularJS versions greater than or equal to 1.5.10 and less than 1.7.0. + * See the [AngularJS documentation for `$compileProvider.preAssignBindingsEnabled` + * ](https://code.angularjs.org/1.6.10/docs/api/ng/provider/$compileProvider#preAssignBindingsEnabled) + * for more information. + * + * To enable/disable whether the controllers of dynamic AngularJS Material components + * (i.e. dialog, panel, toast, bottomsheet) respect the AngularJS + * `$compileProvider.preAssignBindingsEnabled` flag, call the AngularJS Material method: + * `$mdCompilerProvider.respectPreAssignBindingsEnabled(boolean)`. + * + * This AngularJS Material *flag* doesn't affect directives/components created via regular + * AngularJS methods. These constitute the majority of AngularJS Material and user-created + * components. Only dynamic construction of elements such as Dialogs, Panels, Toasts, BottomSheets, + * etc. may be affected. Invoking `$mdCompilerProvider.respectPreAssignBindingsEnabled(true)` + * will effect **bindings** in controllers created by AngularJS Material's services like + * `$mdDialog`, `$mdPanel`, `$mdToast`, or `$mdBottomSheet`. + * + * See [$mdCompilerProvider.respectPreAssignBindingsEnabled](#mdcompilerprovider-respectpreassignbindingsenabled-respected) + * for the details of how the different versions and settings of AngularJS affect this behavior. + * + * @usage + * + * Respect the AngularJS Compiler Setting + * + * + * app.config(function($mdCompilerProvider) { + * $mdCompilerProvider.respectPreAssignBindingsEnabled(true); + * }); + * + * + * @example + * Using the default (backwards compatible) values for AngularJS 1.6 + * - AngularJS' `$compileProvider.preAssignBindingsEnabled(false)` + * - AngularJS Material's `$mdCompilerProvider.respectPreAssignBindingsEnabled(false)` + *

    + * + * + * $mdDialog.show({ + * locals: { + * myVar: true + * }, + * controller: MyController, + * bindToController: true + * } + * + * function MyController() { + * // Locals from Angular Material are available. e.g myVar is true. + * } + * + * MyController.prototype.$onInit = function() { + * // Bindings are also available in the $onInit lifecycle hook. + * } + * + * + * Recommended Settings for AngularJS 1.6 + * - AngularJS' `$compileProvider.preAssignBindingsEnabled(false)` + * - AngularJS Material's `$mdCompilerProvider.respectPreAssignBindingsEnabled(true)` + *

    + * + * + * $mdDialog.show({ + * locals: { + * myVar: true + * }, + * controller: MyController, + * bindToController: true + * } + * + * function MyController() { + * // No locals from Angular Material are available. e.g myVar is undefined. + * } + * + * MyController.prototype.$onInit = function() { + * // Bindings are now available in the $onInit lifecycle hook. + * } + * + * + */ +MdCompilerProvider.$inject = ['$compileProvider']; +function MdCompilerProvider($compileProvider) { + + var provider = this; + + /** + * @ngdoc method + * @name $mdCompilerProvider#respectPreAssignBindingsEnabled + * + * @param {boolean=} respected update the `respectPreAssignBindingsEnabled` state if provided, + * otherwise just return the current Material `respectPreAssignBindingsEnabled` state. + * @returns {boolean|MdCompilerProvider} current value, if used as a getter, or itself (chaining) + * if used as a setter. + * + * @description + * Call this method to enable/disable whether Material-specific (dialog/panel/toast/bottomsheet) + * controllers respect the AngularJS `$compileProvider.preAssignBindingsEnabled` flag. Note that + * this doesn't affect directives/components created via regular AngularJS methods which + * constitute most Material and user-created components. + * + * If disabled (`false`), the compiler assigns the value of each of the bindings to the + * properties of the controller object before the constructor of this object is called. + * The ability to disable this settings is **deprecated** and will be removed in + * AngularJS Material 1.2.0. + * + * If enabled (`true`) the behavior depends on the AngularJS version used: + * + * - `<1.5.10` + * - Bindings are pre-assigned. + * - `>=1.5.10 <1.7` + * - Respects whatever `$compileProvider.preAssignBindingsEnabled()` reports. If the + * `preAssignBindingsEnabled` flag wasn't set manually, it defaults to pre-assigning bindings + * with AngularJS `1.5` and to calling the constructor first with AngularJS `1.6`. + * - `>=1.7` + * - The compiler calls the constructor first before assigning bindings and + * `$compileProvider.preAssignBindingsEnabled()` no longer exists. + * + * Defaults + * - The default value is `false` in AngularJS 1.6 and earlier. + * - It is planned to fix this value to `true` and not allow the `false` value in + * AngularJS Material 1.2.0. + * + * It is recommended to set this flag to `true` when using AngularJS Material 1.1.x with + * AngularJS versions >= 1.5.10. The only reason it's not set that way by default is backwards + * compatibility. + * + * By not setting the flag to `true` when AngularJS' `$compileProvider.preAssignBindingsEnabled()` + * is set to `false` (i.e. default behavior in AngularJS 1.6 or newer), unit testing of + * Material Dialog/Panel/Toast/BottomSheet controllers using the `$controller` helper + * is problematic as it always follows AngularJS' `$compileProvider.preAssignBindingsEnabled()` + * value. + */ + var respectPreAssignBindingsEnabled = false; + this.respectPreAssignBindingsEnabled = function(respected) { + if (angular.isDefined(respected)) { + respectPreAssignBindingsEnabled = respected; + return this; + } + + return respectPreAssignBindingsEnabled; + }; + + /** + * @private + * @description + * This function returns `true` if AngularJS Material-specific (dialog/panel/toast/bottomsheet) + * controllers have bindings pre-assigned in controller constructors and `false` otherwise. + * + * Note that this doesn't affect directives/components created via regular AngularJS methods + * which constitute most Material and user-created components; their behavior can be checked via + * `$compileProvider.preAssignBindingsEnabled()` in AngularJS `>=1.5.10 <1.7.0`. + * + * @returns {*} current preAssignBindingsEnabled state + */ + function getPreAssignBindingsEnabled() { + if (!respectPreAssignBindingsEnabled) { + // respectPreAssignBindingsEnabled === false + // We're ignoring the AngularJS `$compileProvider.preAssignBindingsEnabled()` value in this case. + return true; + } + + // respectPreAssignBindingsEnabled === true + + // This check is needed because $compileProvider.preAssignBindingsEnabled does not exist prior + // to AngularJS 1.5.10, is deprecated in AngularJS 1.6.x, and removed in AngularJS 1.7.x. + if (typeof $compileProvider.preAssignBindingsEnabled === 'function') { + return $compileProvider.preAssignBindingsEnabled(); + } + + // Flag respected but not present => apply logic based on AngularJS version used. + if (angular.version.major === 1 && angular.version.minor < 6) { + // AngularJS <1.5.10 + return true; + } + + // AngularJS >=1.7.0 + return false; + } + + this.$get = ["$q", "$templateRequest", "$injector", "$compile", "$controller", + function($q, $templateRequest, $injector, $compile, $controller) { + return new MdCompilerService($q, $templateRequest, $injector, $compile, $controller); + }]; + + /** + * @ngdoc service + * @name $mdCompiler + * @module material.core.compiler + * @description + * The $mdCompiler service is an abstraction of AngularJS's compiler, that allows developers + * to easily compile an element with options like in a Directive Definition Object. + * + * > The compiler powers a lot of components inside of AngularJS Material. + * > Like the `$mdPanel` or `$mdDialog`. + * + * @usage + * + * Basic Usage with a template + * + * + * $mdCompiler.compile({ + * templateUrl: 'modal.html', + * controller: 'ModalCtrl', + * locals: { + * modal: myModalInstance; + * } + * }).then(function (compileData) { + * compileData.element; // Compiled DOM element + * compileData.link(myScope); // Instantiate controller and link element to scope. + * }); + * + * + * Example with a content element + * + * + * + * // Create a virtual element and link it manually. + * // The compiler doesn't need to recompile the element each time. + * var myElement = $compile('Test')(myScope); + * + * $mdCompiler.compile({ + * contentElement: myElement + * }).then(function (compileData) { + * compileData.element // Content Element (same as above) + * compileData.link // This does nothing when using a contentElement. + * }); + * + * + * > Content Element is a significant performance improvement when the developer already knows that the + * > compiled element will be always the same and the scope will not change either. + * + * The `contentElement` option also supports DOM elements which will be temporary removed and restored + * at its old position. + * + * + * var domElement = document.querySelector('#myElement'); + * + * $mdCompiler.compile({ + * contentElement: myElement + * }).then(function (compileData) { + * compileData.element // Content Element (same as above) + * compileData.link // This does nothing when using a contentElement. + * }); + * + * + * The `$mdCompiler` can also query for the element in the DOM itself. + * + * + * $mdCompiler.compile({ + * contentElement: '#myElement' + * }).then(function (compileData) { + * compileData.element // Content Element (same as above) + * compileData.link // This does nothing when using a contentElement. + * }); + * + * + */ + function MdCompilerService($q, $templateRequest, $injector, $compile, $controller) { + + /** @private @const {!angular.$q} */ + this.$q = $q; + + /** @private @const {!angular.$templateRequest} */ + this.$templateRequest = $templateRequest; + + /** @private @const {!angular.$injector} */ + this.$injector = $injector; + + /** @private @const {!angular.$compile} */ + this.$compile = $compile; + + /** @private @const {!angular.$controller} */ + this.$controller = $controller; + } + + /** + * @ngdoc method + * @name $mdCompiler#compile + * @description + * + * A method to compile a HTML template with the AngularJS compiler. + * The `$mdCompiler` is wrapper around the AngularJS compiler and provides extra functionality + * like controller instantiation or async resolves. + * + * @param {!Object} options An options object, with the following properties: + * + * - `controller` - `{string|function}` Controller fn that should be associated with + * newly created scope or the name of a registered controller if passed as a string. + * - `controllerAs` - `{string=}` A controller alias name. If present the controller will be + * published to scope under the `controllerAs` name. + * - `contentElement` - `{string|Element}`: Instead of using a template, which will be + * compiled each time, you can also use a DOM element.
    + * - `template` - `{string=}` An html template as a string. + * - `templateUrl` - `{string=}` A path to an html template. + * - `transformTemplate` - `{function(template)=}` A function which transforms the template after + * it is loaded. It will be given the template string as a parameter, and should + * return a a new string representing the transformed template. + * - `resolve` - `{Object.=}` - An optional map of dependencies which should + * be injected into the controller. If any of these dependencies are promises, the compiler + * will wait for them all to be resolved, or if one is rejected before the controller is + * instantiated `compile()` will fail.. + * * `key` - `{string}`: a name of a dependency to be injected into the controller. + * * `factory` - `{string|function}`: If `string` then it is an alias for a service. + * Otherwise if function, then it is injected and the return value is treated as the + * dependency. If the result is a promise, it is resolved before its value is + * injected into the controller. + * + * @returns {Object} promise A promise, which will be resolved with a `compileData` object. + * `compileData` has the following properties: + * + * - `element` - `{Element}`: an uncompiled element matching the provided template. + * - `link` - `{function(scope)}`: A link function, which, when called, will compile + * the element and instantiate the provided controller (if given). + * - `locals` - `{Object}`: The locals which will be passed into the controller once `link` is + * called. If `bindToController` is true, they will be copied to the ctrl instead + */ + MdCompilerService.prototype.compile = function(options) { + + if (options.contentElement) { + return this._prepareContentElement(options); + } else { + return this._compileTemplate(options); + } + + }; + + /** + * Instead of compiling any template, the compiler just fetches an existing HTML element from the DOM and + * provides a restore function to put the element back it old DOM position. + * @param {!Object} options Options to be used for the compiler. + */ + MdCompilerService.prototype._prepareContentElement = function(options) { + + var contentElement = this._fetchContentElement(options); + + return this.$q.resolve({ + element: contentElement.element, + cleanup: contentElement.restore, + locals: {}, + link: function() { + return contentElement.element; + } + }); + + }; + + /** + * Compiles a template by considering all options and waiting for all resolves to be ready. + * @param {!Object} options Compile options + * @returns {!Object} Compile data with link function. + */ + MdCompilerService.prototype._compileTemplate = function(options) { + + var self = this; + var templateUrl = options.templateUrl; + var template = options.template || ''; + var resolve = angular.extend({}, options.resolve); + var locals = angular.extend({}, options.locals); + var transformTemplate = options.transformTemplate || angular.identity; + + // Take resolve values and invoke them. + // Resolves can either be a string (value: 'MyRegisteredAngularConst'), + // or an invokable 'factory' of sorts: (value: function ValueGetter($dependency) {}) + angular.forEach(resolve, function(value, key) { + if (angular.isString(value)) { + resolve[key] = self.$injector.get(value); + } else { + resolve[key] = self.$injector.invoke(value); + } + }); + + // Add the locals, which are just straight values to inject + // eg locals: { three: 3 }, will inject three into the controller + angular.extend(resolve, locals); + + if (templateUrl) { + resolve.$$ngTemplate = this.$templateRequest(templateUrl); + } else { + resolve.$$ngTemplate = this.$q.when(template); + } + + + // Wait for all the resolves to finish if they are promises + return this.$q.all(resolve).then(function(locals) { + + var template = transformTemplate(locals.$$ngTemplate, options); + var element = options.element || angular.element('
    ').html(template.trim()).contents(); + + return self._compileElement(locals, element, options); + }); + + }; + + /** + * Method to compile an element with the given options. + * @param {!Object} locals Locals to be injected to the controller if present + * @param {!JQLite} element Element to be compiled and linked + * @param {!Object} options Options to be used for linking. + * @returns {!Object} Compile data with link function. + */ + MdCompilerService.prototype._compileElement = function(locals, element, options) { + var self = this; + var ngLinkFn = this.$compile(element); + + var compileData = { + element: element, + cleanup: element.remove.bind(element), + locals: locals, + link: linkFn + }; + + function linkFn(scope) { + locals.$scope = scope; + + // Instantiate controller if the developer provided one. + if (options.controller) { + + var injectLocals = angular.extend({}, locals, { + $element: element + }); + + // Create the specified controller instance. + var ctrl = self._createController(options, injectLocals, locals); + + // Unique identifier for AngularJS Route ngView controllers. + element.data('$ngControllerController', ctrl); + element.children().data('$ngControllerController', ctrl); + + // Expose the instantiated controller to the compile data + compileData.controller = ctrl; + } + + // Invoke the AngularJS $compile link function. + return ngLinkFn(scope); + } + + return compileData; + + }; + + /** + * Creates and instantiates a new controller with the specified options. + * @param {!Object} options Options that include the controller function or string. + * @param {!Object} injectLocals Locals to to be provided in the controller DI. + * @param {!Object} locals Locals to be injected to the controller. + * @returns {!Object} Created controller instance. + */ + MdCompilerService.prototype._createController = function(options, injectLocals, locals) { + var ctrl; + var preAssignBindingsEnabled = getPreAssignBindingsEnabled(); + // The third argument to $controller is considered private and undocumented: + // https://github.com/angular/angular.js/blob/v1.6.10/src/ng/controller.js#L102-L109. + // TODO remove the use of this third argument in AngularJS Material 1.2.0. + // Passing `true` as the third argument causes `$controller` to return a function that + // gets the controller instance instead of returning the instance directly. When the + // controller is defined as a function, `invokeCtrl.instance` is the *same instance* as + // `invokeCtrl()`. However, when the controller is an ES6 class, `invokeCtrl.instance` is a + // *different instance* from `invokeCtrl()`. + if (preAssignBindingsEnabled) { + var invokeCtrl = this.$controller(options.controller, injectLocals, true); + + if (options.bindToController) { + angular.extend(invokeCtrl.instance, locals); + } + + // Use the private API callback to instantiate and initialize the specified controller. + ctrl = invokeCtrl(); + } else { + // If we don't need to pre-assign bindings, avoid using the private API third argument and + // related callback. + ctrl = this.$controller(options.controller, injectLocals); + + if (options.bindToController) { + angular.extend(ctrl, locals); + } + } + + if (options.controllerAs) { + injectLocals.$scope[options.controllerAs] = ctrl; + } + + // Call the $onInit hook if it's present on the controller. + angular.isFunction(ctrl.$onInit) && ctrl.$onInit(); + + return ctrl; + }; + + /** + * Fetches an element removing it from the DOM and using it temporary for the compiler. + * Elements which were fetched will be restored after use. + * @param {!Object} options Options to be used for the compilation. + * @returns {{element: !JQLite, restore: !function}} + */ + MdCompilerService.prototype._fetchContentElement = function(options) { + + var contentEl = options.contentElement; + var restoreFn = null; + + if (angular.isString(contentEl)) { + contentEl = document.querySelector(contentEl); + restoreFn = createRestoreFn(contentEl); + } else { + contentEl = contentEl[0] || contentEl; + + // When the element is visible in the DOM, then we restore it at close of the dialog. + // Otherwise it will be removed from the DOM after close. + if (document.contains(contentEl)) { + restoreFn = createRestoreFn(contentEl); + } else { + restoreFn = function() { + if (contentEl.parentNode) { + contentEl.parentNode.removeChild(contentEl); + } + }; + } + } + + return { + element: angular.element(contentEl), + restore: restoreFn + }; + + function createRestoreFn(element) { + var parent = element.parentNode; + var nextSibling = element.nextElementSibling; + + return function() { + if (!nextSibling) { + // When the element didn't had any sibling, then it can be simply appended to the + // parent, because it plays no role, which index it had before. + parent.appendChild(element); + } else { + // When the element had a sibling, which marks the previous position of the element + // in the DOM, we insert it correctly before the sibling, to have the same index as + // before. + parent.insertBefore(element, nextSibling); + } + }; + } + }; +} + + +})(); +(function(){ +"use strict"; + + +MdGesture.$inject = ["$$MdGestureHandler", "$$rAF", "$timeout"]; +attachToDocument.$inject = ["$mdGesture", "$$MdGestureHandler"];var HANDLERS = {}; + +/** + * The state of the current 'pointer'. The pointer represents the state of the current touch. + * It contains normalized x and y coordinates from DOM events, + * as well as other information abstracted from the DOM. + */ +var pointer, lastPointer, maxClickDistance = 6; +var forceSkipClickHijack = false, disableAllGestures = false; + +/** + * The position of the most recent click if that click was on a label element. + * @type {{x: number, y: number}|null} + */ +var lastLabelClickPos = null; + +// Used to attach event listeners once when multiple ng-apps are running. +var isInitialized = false; + +var userAgent = navigator.userAgent || navigator.vendor || window.opera; +var isIos = userAgent.match(/ipad|iphone|ipod/i); +var isAndroid = userAgent.match(/android/i); + +/** + * @ngdoc module + * @name material.core.gestures + * @description + * AngularJS Material Gesture handling for touch devices. This module replaced the usage of the hammerjs library. + */ +angular + .module('material.core.gestures', []) + .provider('$mdGesture', MdGestureProvider) + .factory('$$MdGestureHandler', MdGestureHandler) + .run(attachToDocument); + +/** + * @ngdoc service + * @name $mdGestureProvider + * @module material.core.gestures + * + * @description + * In some scenarios on mobile devices (without jQuery), the click events should NOT be hijacked. + * `$mdGestureProvider` is used to configure the Gesture module to ignore or skip click hijacking on mobile + * devices. + * + * You can also change the max click distance, `6px` by default, if you have issues on some touch screens. + * + * + * app.config(function($mdGestureProvider) { + * + * // For mobile devices without jQuery loaded, do not + * // intercept click events during the capture phase. + * $mdGestureProvider.skipClickHijack(); + * + * // If hijacking clicks, you may want to change the default click distance + * $mdGestureProvider.setMaxClickDistance(12); + * }); + * + * + */ +function MdGestureProvider() { } + +MdGestureProvider.prototype = { + + /** + * @ngdoc method + * @name $mdGestureProvider#disableAll + * + * @description + * Disable all gesture detection. This can be beneficial to application performance + * and memory usage. + */ + disableAll: function () { + disableAllGestures = true; + }, + + // Publish access to setter to configure a variable BEFORE the + // $mdGesture service is instantiated... + /** + * @ngdoc method + * @name $mdGestureProvider#skipClickHijack + * + * @description + * Tell the AngularJS Material Gesture module to skip (or ignore) click hijacking on mobile devices. + */ + skipClickHijack: function() { + return forceSkipClickHijack = true; + }, + + /** + * @ngdoc method + * @name $mdGestureProvider#setMaxClickDistance + * @param clickDistance {string} Distance in pixels. I.e. `12px`. + * @description + * Set the max distance from the origin of the touch event to trigger touch handlers. + */ + setMaxClickDistance: function(clickDistance) { + maxClickDistance = parseInt(clickDistance); + }, + + /** + * $get is used to build an instance of $mdGesture + * @ngInject + */ + $get : ["$$MdGestureHandler", "$$rAF", "$timeout", function($$MdGestureHandler, $$rAF, $timeout) { + return new MdGesture($$MdGestureHandler, $$rAF, $timeout); + }] +}; + + + +/** + * MdGesture factory construction function + * @ngInject + */ +function MdGesture($$MdGestureHandler, $$rAF, $timeout) { + var touchActionProperty = getTouchAction(); + var hasJQuery = (typeof window.jQuery !== 'undefined') && (angular.element === window.jQuery); + + var self = { + handler: addHandler, + register: register, + isAndroid: isAndroid, + isIos: isIos, + // On mobile w/out jQuery, we normally intercept clicks. Should we skip that? + isHijackingClicks: (isIos || isAndroid) && !hasJQuery && !forceSkipClickHijack + }; + + if (self.isHijackingClicks) { + self.handler('click', { + options: { + maxDistance: maxClickDistance + }, + onEnd: checkDistanceAndEmit('click') + }); + + self.handler('focus', { + options: { + maxDistance: maxClickDistance + }, + onEnd: function(ev, pointer) { + if (pointer.distance < this.state.options.maxDistance && canFocus(ev.target)) { + this.dispatchEvent(ev, 'focus', pointer); + ev.target.focus(); + } + } + }); + + self.handler('mouseup', { + options: { + maxDistance: maxClickDistance + }, + onEnd: checkDistanceAndEmit('mouseup') + }); + + self.handler('mousedown', { + onStart: function(ev) { + this.dispatchEvent(ev, 'mousedown'); + } + }); + } + + function checkDistanceAndEmit(eventName) { + return function(ev, pointer) { + if (pointer.distance < this.state.options.maxDistance) { + this.dispatchEvent(ev, eventName, pointer); + } + }; + } + + /** + * Register an element to listen for a handler. + * This allows an element to override the default options for a handler. + * Additionally, some handlers like drag and hold only dispatch events if + * the domEvent happens inside an element that's registered to listen for these events. + * + * @see GestureHandler for how overriding of default options works. + * @example $mdGesture.register(myElement, 'drag', { minDistance: 20, horizontal: false }) + */ + function register(element, handlerName, options) { + var handler = HANDLERS[handlerName.replace(/^\$md./, '')]; + if (!handler) { + throw new Error('Failed to register element with handler ' + handlerName + '. ' + + 'Available handlers: ' + Object.keys(HANDLERS).join(', ')); + } + return handler.registerElement(element, options); + } + + /* + * add a handler to $mdGesture. see below. + */ + function addHandler(name, definition) { + var handler = new $$MdGestureHandler(name); + angular.extend(handler, definition); + HANDLERS[name] = handler; + + return self; + } + + /** + * Register handlers. These listen to touch/start/move events, interpret them, + * and dispatch gesture events depending on options & conditions. These are all + * instances of GestureHandler. + * @see GestureHandler + */ + return self + /* + * The press handler dispatches an event on touchdown/touchend. + * It's a simple abstraction of touch/mouse/pointer start and end. + */ + .handler('press', { + onStart: function (ev, pointer) { + this.dispatchEvent(ev, '$md.pressdown'); + }, + onEnd: function (ev, pointer) { + this.dispatchEvent(ev, '$md.pressup'); + } + }) + + /* + * The hold handler dispatches an event if the user keeps their finger within + * the same area for ms. + * The hold handler will only run if a parent of the touch target is registered + * to listen for hold events through $mdGesture.register() + */ + .handler('hold', { + options: { + maxDistance: 6, + delay: 500 + }, + onCancel: function () { + $timeout.cancel(this.state.timeout); + }, + onStart: function (ev, pointer) { + // For hold, require a parent to be registered with $mdGesture.register() + // Because we prevent scroll events, this is necessary. + if (!this.state.registeredParent) return this.cancel(); + + this.state.pos = {x: pointer.x, y: pointer.y}; + this.state.timeout = $timeout(angular.bind(this, function holdDelayFn() { + this.dispatchEvent(ev, '$md.hold'); + this.cancel(); // we're done! + }), this.state.options.delay, false); + }, + onMove: function (ev, pointer) { + // Don't scroll while waiting for hold. + // If we don't preventDefault touchmove events here, Android will assume we don't + // want to listen to anymore touch events. It will start scrolling and stop sending + // touchmove events. + if (!touchActionProperty && ev.type === 'touchmove') ev.preventDefault(); + + // If the user moves greater than pixels, stop the hold timer + // set in onStart + var dx = this.state.pos.x - pointer.x; + var dy = this.state.pos.y - pointer.y; + if (Math.sqrt(dx * dx + dy * dy) > this.options.maxDistance) { + this.cancel(); + } + }, + onEnd: function () { + this.onCancel(); + } + }) + + /* + * The drag handler dispatches a drag event if the user holds and moves his finger greater than + * px in the x or y direction, depending on options.horizontal. + * The drag will be cancelled if the user moves his finger greater than * in + * the perpendicular direction. Eg if the drag is horizontal and the user moves his finger * + * pixels vertically, this handler won't consider the move part of a drag. + */ + .handler('drag', { + options: { + minDistance: 6, + horizontal: true, + cancelMultiplier: 1.5 + }, + onSetup: function(element, options) { + if (touchActionProperty) { + // We check for horizontal to be false, because otherwise we would overwrite the default opts. + this.oldTouchAction = element[0].style[touchActionProperty]; + element[0].style[touchActionProperty] = options.horizontal ? 'pan-y' : 'pan-x'; + } + }, + onCleanup: function(element) { + if (this.oldTouchAction) { + element[0].style[touchActionProperty] = this.oldTouchAction; + } + }, + onStart: function (ev) { + // For drag, require a parent to be registered with $mdGesture.register() + if (!this.state.registeredParent) this.cancel(); + }, + onMove: function (ev, pointer) { + var shouldStartDrag, shouldCancel; + // Don't scroll while deciding if this touchmove qualifies as a drag event. + // If we don't preventDefault touchmove events here, Android will assume we don't + // want to listen to anymore touch events. It will start scrolling and stop sending + // touchmove events. + if (!touchActionProperty && ev.type === 'touchmove') ev.preventDefault(); + + if (!this.state.dragPointer) { + if (this.state.options.horizontal) { + shouldStartDrag = Math.abs(pointer.distanceX) > this.state.options.minDistance; + shouldCancel = Math.abs(pointer.distanceY) > this.state.options.minDistance * this.state.options.cancelMultiplier; + } else { + shouldStartDrag = Math.abs(pointer.distanceY) > this.state.options.minDistance; + shouldCancel = Math.abs(pointer.distanceX) > this.state.options.minDistance * this.state.options.cancelMultiplier; + } + + if (shouldStartDrag) { + // Create a new pointer representing this drag, starting at this point where the drag started. + this.state.dragPointer = makeStartPointer(ev); + updatePointerState(ev, this.state.dragPointer); + this.dispatchEvent(ev, '$md.dragstart', this.state.dragPointer); + + } else if (shouldCancel) { + this.cancel(); + } + } else { + this.dispatchDragMove(ev); + } + }, + // Only dispatch dragmove events every frame; any more is unnecessary + dispatchDragMove: $$rAF.throttle(function (ev) { + // Make sure the drag didn't stop while waiting for the next frame + if (this.state.isRunning) { + updatePointerState(ev, this.state.dragPointer); + this.dispatchEvent(ev, '$md.drag', this.state.dragPointer); + } + }), + onEnd: function (ev, pointer) { + if (this.state.dragPointer) { + updatePointerState(ev, this.state.dragPointer); + this.dispatchEvent(ev, '$md.dragend', this.state.dragPointer); + } + } + }) + + /* + * The swipe handler will dispatch a swipe event if, on the end of a touch, + * the velocity and distance were high enough. + */ + .handler('swipe', { + options: { + minVelocity: 0.65, + minDistance: 10 + }, + onEnd: function (ev, pointer) { + var eventType; + + if (Math.abs(pointer.velocityX) > this.state.options.minVelocity && + Math.abs(pointer.distanceX) > this.state.options.minDistance) { + eventType = pointer.directionX == 'left' ? '$md.swipeleft' : '$md.swiperight'; + this.dispatchEvent(ev, eventType); + } + else if (Math.abs(pointer.velocityY) > this.state.options.minVelocity && + Math.abs(pointer.distanceY) > this.state.options.minDistance) { + eventType = pointer.directionY == 'up' ? '$md.swipeup' : '$md.swipedown'; + this.dispatchEvent(ev, eventType); + } + } + }); + + function getTouchAction() { + var testEl = document.createElement('div'); + var vendorPrefixes = ['', 'webkit', 'Moz', 'MS', 'ms', 'o']; + + for (var i = 0; i < vendorPrefixes.length; i++) { + var prefix = vendorPrefixes[i]; + var property = prefix ? prefix + 'TouchAction' : 'touchAction'; + if (angular.isDefined(testEl.style[property])) { + return property; + } + } + } + +} + +/** + * MdGestureHandler + * A GestureHandler is an object which is able to dispatch custom dom events + * based on native dom {touch,pointer,mouse}{start,move,end} events. + * + * A gesture will manage its lifecycle through the start,move,end, and cancel + * functions, which are called by native dom events. + * + * A gesture has the concept of 'options' (eg a swipe's required velocity), which can be + * overridden by elements registering through $mdGesture.register() + */ +function GestureHandler (name) { + this.name = name; + this.state = {}; +} + +function MdGestureHandler() { + var hasJQuery = (typeof window.jQuery !== 'undefined') && (angular.element === window.jQuery); + + GestureHandler.prototype = { + options: {}, + // jQuery listeners don't work with custom DOMEvents, so we have to dispatch events + // differently when jQuery is loaded + dispatchEvent: hasJQuery ? jQueryDispatchEvent : nativeDispatchEvent, + + // These are overridden by the registered handler + onSetup: angular.noop, + onCleanup: angular.noop, + onStart: angular.noop, + onMove: angular.noop, + onEnd: angular.noop, + onCancel: angular.noop, + + // onStart sets up a new state for the handler, which includes options from the + // nearest registered parent element of ev.target. + start: function (ev, pointer) { + if (this.state.isRunning) return; + var parentTarget = this.getNearestParent(ev.target); + // Get the options from the nearest registered parent + var parentTargetOptions = parentTarget && parentTarget.$mdGesture[this.name] || {}; + + this.state = { + isRunning: true, + // Override the default options with the nearest registered parent's options + options: angular.extend({}, this.options, parentTargetOptions), + // Pass in the registered parent node to the state so the onStart listener can use + registeredParent: parentTarget + }; + this.onStart(ev, pointer); + }, + move: function (ev, pointer) { + if (!this.state.isRunning) return; + this.onMove(ev, pointer); + }, + end: function (ev, pointer) { + if (!this.state.isRunning) return; + this.onEnd(ev, pointer); + this.state.isRunning = false; + }, + cancel: function (ev, pointer) { + this.onCancel(ev, pointer); + this.state = {}; + }, + + // Find and return the nearest parent element that has been registered to + // listen for this handler via $mdGesture.register(element, 'handlerName'). + getNearestParent: function (node) { + var current = node; + while (current) { + if ((current.$mdGesture || {})[this.name]) { + return current; + } + current = current.parentNode; + } + return null; + }, + + // Called from $mdGesture.register when an element registers itself with a handler. + // Store the options the user gave on the DOMElement itself. These options will + // be retrieved with getNearestParent when the handler starts. + registerElement: function (element, options) { + var self = this; + element[0].$mdGesture = element[0].$mdGesture || {}; + element[0].$mdGesture[this.name] = options || {}; + element.on('$destroy', onDestroy); + + self.onSetup(element, options || {}); + + return onDestroy; + + function onDestroy() { + delete element[0].$mdGesture[self.name]; + element.off('$destroy', onDestroy); + + self.onCleanup(element, options || {}); + } + } + }; + + return GestureHandler; + + /** + * Dispatch an event with jQuery + * TODO: Make sure this sends bubbling events + * + * @param srcEvent the original DOM touch event that started this. + * @param eventType the name of the custom event to send (eg 'click' or '$md.drag') + * @param eventPointer the pointer object that matches this event. + */ + function jQueryDispatchEvent(srcEvent, eventType, eventPointer) { + eventPointer = eventPointer || pointer; + var eventObj = new angular.element.Event(eventType); + + eventObj.$material = true; + eventObj.pointer = eventPointer; + eventObj.srcEvent = srcEvent; + + angular.extend(eventObj, { + clientX: eventPointer.x, + clientY: eventPointer.y, + screenX: eventPointer.x, + screenY: eventPointer.y, + pageX: eventPointer.x, + pageY: eventPointer.y, + ctrlKey: srcEvent.ctrlKey, + altKey: srcEvent.altKey, + shiftKey: srcEvent.shiftKey, + metaKey: srcEvent.metaKey + }); + angular.element(eventPointer.target).trigger(eventObj); + } + + /** + * NOTE: nativeDispatchEvent is very performance sensitive. + * @param srcEvent the original DOM touch event that started this. + * @param eventType the name of the custom event to send (eg 'click' or '$md.drag') + * @param eventPointer the pointer object that matches this event. + */ + function nativeDispatchEvent(srcEvent, eventType, eventPointer) { + eventPointer = eventPointer || pointer; + var eventObj; + + if (eventType === 'click' || eventType === 'mouseup' || eventType === 'mousedown') { + if (typeof window.MouseEvent === "function") { + eventObj = new MouseEvent(eventType, { + bubbles: true, + cancelable: true, + screenX: Number(srcEvent.screenX), + screenY: Number(srcEvent.screenY), + clientX: Number(eventPointer.x), + clientY: Number(eventPointer.y), + ctrlKey: srcEvent.ctrlKey, + altKey: srcEvent.altKey, + shiftKey: srcEvent.shiftKey, + metaKey: srcEvent.metaKey, + button: srcEvent.button, + buttons: srcEvent.buttons, + relatedTarget: srcEvent.relatedTarget || null + }); + } else { + eventObj = document.createEvent('MouseEvents'); + // This has been deprecated + // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent + eventObj.initMouseEvent( + eventType, true, true, window, srcEvent.detail, + eventPointer.x, eventPointer.y, eventPointer.x, eventPointer.y, + srcEvent.ctrlKey, srcEvent.altKey, srcEvent.shiftKey, srcEvent.metaKey, + srcEvent.button, srcEvent.relatedTarget || null + ); + } + } else { + if (typeof window.CustomEvent === "function") { + eventObj = new CustomEvent(eventType, { + bubbles: true, + cancelable: true, + detail: {} + }); + } else { + // This has been deprecated + // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/initCustomEvent + eventObj = document.createEvent('CustomEvent'); + eventObj.initCustomEvent(eventType, true, true, {}); + } + } + eventObj.$material = true; + eventObj.pointer = eventPointer; + eventObj.srcEvent = srcEvent; + eventPointer.target.dispatchEvent(eventObj); + } +} + +/** + * Attach Gestures: hook document and check shouldHijack clicks + * @ngInject + */ +function attachToDocument($mdGesture, $$MdGestureHandler) { + if (disableAllGestures) { + return; + } + + // Polyfill document.contains for IE11. + // TODO: move to util + document.contains || (document.contains = function (node) { + return document.body.contains(node); + }); + + if (!isInitialized && $mdGesture.isHijackingClicks) { + /* + * If hijack clicks is true, we preventDefault any click that wasn't + * sent by AngularJS Material. This is because on older Android & iOS, a false, or 'ghost', + * click event will be sent ~400ms after a touchend event happens. + * The only way to know if this click is real is to prevent any normal + * click events, and add a flag to events sent by material so we know not to prevent those. + * + * Two exceptions to click events that should be prevented are: + * - click events sent by the keyboard (eg form submit) + * - events that originate from an Ionic app + */ + document.addEventListener('click' , clickHijacker , true); + document.addEventListener('mouseup' , mouseInputHijacker, true); + document.addEventListener('mousedown', mouseInputHijacker, true); + document.addEventListener('focus' , mouseInputHijacker, true); + + isInitialized = true; + } + + function mouseInputHijacker(ev) { + var isKeyClick = !ev.clientX && !ev.clientY; + + if ( + !isKeyClick && + !ev.$material && + !ev.isIonicTap && + !isInputEventFromLabelClick(ev) && + (ev.type !== 'mousedown' || (!canFocus(ev.target) && !canFocus(document.activeElement))) + ) { + ev.preventDefault(); + ev.stopPropagation(); + } + } + + /** + * Ignore click events that don't come from AngularJS Material, Ionic, Input Label clicks, + * or key presses that generate click events. This helps to ignore the ghost tap events on + * older mobile browsers that get sent after a 300-400ms delay. + * @param ev MouseEvent or modified MouseEvent with $material, pointer, and other fields + */ + function clickHijacker(ev) { + var isKeyClick; + if (isIos) { + isKeyClick = angular.isDefined(ev.webkitForce) && ev.webkitForce === 0; + } else { + isKeyClick = ev.clientX === 0 && ev.clientY === 0; + } + if (!isKeyClick && !ev.$material && !ev.isIonicTap && !isInputEventFromLabelClick(ev)) { + ev.preventDefault(); + ev.stopPropagation(); + lastLabelClickPos = null; + } else { + lastLabelClickPos = null; + if (ev.target.tagName.toLowerCase() === 'label') { + lastLabelClickPos = {x: ev.x, y: ev.y}; + } + } + } + + + // Listen to all events to cover all platforms. + var START_EVENTS = 'mousedown touchstart pointerdown'; + var MOVE_EVENTS = 'mousemove touchmove pointermove'; + var END_EVENTS = 'mouseup mouseleave touchend touchcancel pointerup pointercancel'; + + angular.element(document) + .on(START_EVENTS, gestureStart) + .on(MOVE_EVENTS, gestureMove) + .on(END_EVENTS, gestureEnd) + // For testing + .on('$$mdGestureReset', function gestureClearCache () { + lastPointer = pointer = null; + }); + + /** + * When a DOM event happens, run all registered gesture handlers' lifecycle + * methods which match the DOM event. + * Eg. when a 'touchstart' event happens, runHandlers('start') will call and + * run `handler.cancel()` and `handler.start()` on all registered handlers. + */ + function runHandlers(handlerEvent, event) { + var handler; + for (var name in HANDLERS) { + handler = HANDLERS[name]; + if (handler instanceof $$MdGestureHandler) { + + if (handlerEvent === 'start') { + // Run cancel to reset any handlers' state + handler.cancel(); + } + handler[handlerEvent](event, pointer); + } + } + } + + /* + * gestureStart vets if a start event is legitimate (and not part of a 'ghost click' from iOS/Android) + * If it is legitimate, we initiate the pointer state and mark the current pointer's type + * For example, for a touchstart event, mark the current pointer as a 'touch' pointer, so mouse events + * won't effect it. + */ + function gestureStart(ev) { + // If we're already touched down, abort + if (pointer) return; + + var now = +Date.now(); + + // iOS & old android bug: after a touch event, a click event is sent 350 ms later. + // If <400ms have passed, don't allow an event of a different type than the previous event + if (lastPointer && !typesMatch(ev, lastPointer) && (now - lastPointer.endTime < 1500)) { + return; + } + + pointer = makeStartPointer(ev); + + runHandlers('start', ev); + } + + /** + * If a move event happens of the right type, update the pointer and run all the move handlers. + * "of the right type": if a mousemove happens but our pointer started with a touch event, do + * nothing. + */ + function gestureMove(ev) { + if (!pointer || !typesMatch(ev, pointer)) return; + + updatePointerState(ev, pointer); + runHandlers('move', ev); + } + + /** + * If an end event happens of the right type, update the pointer, run endHandlers, and save the + * pointer as 'lastPointer'. + */ + function gestureEnd(ev) { + if (!pointer || !typesMatch(ev, pointer)) return; + + updatePointerState(ev, pointer); + pointer.endTime = +Date.now(); + + if (ev.type !== 'pointercancel') { + runHandlers('end', ev); + } + + lastPointer = pointer; + pointer = null; + } + +} + +// ******************** +// Module Functions +// ******************** + +/* + * Initiate the pointer. x, y, and the pointer's type. + */ +function makeStartPointer(ev) { + var point = getEventPoint(ev); + var startPointer = { + startTime: +Date.now(), + target: ev.target, + // 'p' for pointer events, 'm' for mouse, 't' for touch + type: ev.type.charAt(0) + }; + startPointer.startX = startPointer.x = point.pageX; + startPointer.startY = startPointer.y = point.pageY; + return startPointer; +} + +/* + * return whether the pointer's type matches the event's type. + * Eg if a touch event happens but the pointer has a mouse type, return false. + */ +function typesMatch(ev, pointer) { + return ev && pointer && ev.type.charAt(0) === pointer.type; +} + +/** + * Gets whether the given event is an input event that was caused by clicking on an + * associated label element. + * + * This is necessary because the browser will, upon clicking on a label element, fire an + * *extra* click event on its associated input (if any). mdGesture is able to flag the label + * click as with `$material` correctly, but not the second input click. + * + * In order to determine whether an input event is from a label click, we compare the (x, y) for + * the event to the (x, y) for the most recent label click (which is cleared whenever a non-label + * click occurs). Unfortunately, there are no event properties that tie the input and the label + * together (such as relatedTarget). + * + * @param {MouseEvent} event + * @returns {boolean} + */ +function isInputEventFromLabelClick(event) { + return lastLabelClickPos + && lastLabelClickPos.x === event.x + && lastLabelClickPos.y === event.y; +} + +/* + * Update the given pointer based upon the given DOMEvent. + * Distance, velocity, direction, duration, etc + */ +function updatePointerState(ev, pointer) { + var point = getEventPoint(ev); + var x = pointer.x = point.pageX; + var y = pointer.y = point.pageY; + + pointer.distanceX = x - pointer.startX; + pointer.distanceY = y - pointer.startY; + pointer.distance = Math.sqrt( + pointer.distanceX * pointer.distanceX + pointer.distanceY * pointer.distanceY + ); + + pointer.directionX = pointer.distanceX > 0 ? 'right' : pointer.distanceX < 0 ? 'left' : ''; + pointer.directionY = pointer.distanceY > 0 ? 'down' : pointer.distanceY < 0 ? 'up' : ''; + + pointer.duration = +Date.now() - pointer.startTime; + pointer.velocityX = pointer.distanceX / pointer.duration; + pointer.velocityY = pointer.distanceY / pointer.duration; +} + +/** + * Normalize the point where the DOM event happened whether it's touch or mouse. + * @returns point event obj with pageX and pageY on it. + */ +function getEventPoint(ev) { + ev = ev.originalEvent || ev; // support jQuery events + return (ev.touches && ev.touches[0]) || + (ev.changedTouches && ev.changedTouches[0]) || + ev; +} + +/** Checks whether an element can be focused. */ +function canFocus(element) { + return ( + !!element && + element.getAttribute('tabindex') !== '-1' && + !element.hasAttribute('disabled') && + ( + element.hasAttribute('tabindex') || + element.hasAttribute('href') || + element.isContentEditable || + ['INPUT', 'SELECT', 'BUTTON', 'TEXTAREA', 'VIDEO', 'AUDIO'].indexOf(element.nodeName) !== -1 + ) + ); +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.core.interaction + * @description + * User interaction detection to provide proper accessibility. + */ +MdInteractionService.$inject = ["$timeout", "$mdUtil", "$rootScope"]; +angular + .module('material.core.interaction', []) + .service('$mdInteraction', MdInteractionService); + + +/** + * @ngdoc service + * @name $mdInteraction + * @module material.core.interaction + * + * @description + * + * Service which keeps track of the last interaction type and validates them for several browsers. + * The service hooks into the document's body and listens for touch, mouse and keyboard events. + * + * The most recent interaction type can be retrieved by calling the `getLastInteractionType` method. + * + * Here is an example markup for using the interaction service. + * + * + * var lastType = $mdInteraction.getLastInteractionType(); + * + * if (lastType === 'keyboard') { + * // We only restore the focus for keyboard users. + * restoreFocus(); + * } + * + * + */ +function MdInteractionService($timeout, $mdUtil, $rootScope) { + this.$timeout = $timeout; + this.$mdUtil = $mdUtil; + this.$rootScope = $rootScope; + + // IE browsers can also trigger pointer events, which also leads to an interaction. + this.pointerEvent = 'MSPointerEvent' in window ? 'MSPointerDown' : 'PointerEvent' in window ? 'pointerdown' : null; + this.bodyElement = angular.element(document.body); + this.isBuffering = false; + this.bufferTimeout = null; + this.lastInteractionType = null; + this.lastInteractionTime = null; + this.inputHandler = this.onInputEvent.bind(this); + this.bufferedInputHandler = this.onBufferInputEvent.bind(this); + + // Type Mappings for the different events + // There will be three three interaction types + // `keyboard`, `mouse` and `touch` + // type `pointer` will be evaluated in `pointerMap` for IE Browser events + this.inputEventMap = { + 'keydown': 'keyboard', + 'mousedown': 'mouse', + 'mouseenter': 'mouse', + 'touchstart': 'touch', + 'pointerdown': 'pointer', + 'MSPointerDown': 'pointer' + }; + + // IE PointerDown events will be validated in `touch` or `mouse` + // Index numbers referenced here: https://msdn.microsoft.com/library/windows/apps/hh466130.aspx + this.iePointerMap = { + 2: 'touch', + 3: 'touch', + 4: 'mouse' + }; + + this.initializeEvents(); + this.$rootScope.$on('$destroy', this.deregister.bind(this)); +} + +/** + * Removes all event listeners created by $mdInteration on the + * body element. + */ +MdInteractionService.prototype.deregister = function() { + + this.bodyElement.off('keydown mousedown', this.inputHandler); + + if ('ontouchstart' in document.documentElement) { + this.bodyElement.off('touchstart', this.bufferedInputHandler); + } + + if (this.pointerEvent) { + this.bodyElement.off(this.pointerEvent, this.inputHandler); + } + +}; + +/** + * Initializes the interaction service, by registering all interaction events to the + * body element. + */ +MdInteractionService.prototype.initializeEvents = function() { + + this.bodyElement.on('keydown mousedown', this.inputHandler); + + if ('ontouchstart' in document.documentElement) { + this.bodyElement.on('touchstart', this.bufferedInputHandler); + } + + if (this.pointerEvent) { + this.bodyElement.on(this.pointerEvent, this.inputHandler); + } + +}; + +/** + * Event listener for normal interaction events, which should be tracked. + * @param event {MouseEvent|KeyboardEvent|PointerEvent|TouchEvent} + */ +MdInteractionService.prototype.onInputEvent = function(event) { + if (this.isBuffering) { + return; + } + + var type = this.inputEventMap[event.type]; + + if (type === 'pointer') { + type = this.iePointerMap[event.pointerType] || event.pointerType; + } + + this.lastInteractionType = type; + this.lastInteractionTime = this.$mdUtil.now(); +}; + +/** + * Event listener for interaction events which should be buffered (touch events). + * @param event {TouchEvent} + */ +MdInteractionService.prototype.onBufferInputEvent = function(event) { + this.$timeout.cancel(this.bufferTimeout); + + this.onInputEvent(event); + this.isBuffering = true; + + // The timeout of 650ms is needed to delay the touchstart, because otherwise the touch will call + // the `onInput` function multiple times. + this.bufferTimeout = this.$timeout(function() { + this.isBuffering = false; + }.bind(this), 650, false); + +}; + +/** + * @ngdoc method + * @name $mdInteraction#getLastInteractionType + * @description Retrieves the last interaction type triggered in body. + * @returns {string|null} Last interaction type. + */ +MdInteractionService.prototype.getLastInteractionType = function() { + return this.lastInteractionType; +}; + +/** + * @ngdoc method + * @name $mdInteraction#isUserInvoked + * @description Method to detect whether any interaction happened recently or not. + * @param {number=} checkDelay Time to check for any interaction to have been triggered. + * @returns {boolean} Whether there was any interaction or not. + */ +MdInteractionService.prototype.isUserInvoked = function(checkDelay) { + var delay = angular.isNumber(checkDelay) ? checkDelay : 15; + + // Check for any interaction to be within the specified check time. + return this.lastInteractionTime >= this.$mdUtil.now() - delay; +}; + +})(); +(function(){ +"use strict"; + +angular.module('material.core') + .provider('$$interimElement', InterimElementProvider); + +/* + * @ngdoc service + * @name $$interimElement + * @module material.core + * + * @description + * + * Factory that constructs `$$interimElement.$service` services. + * Used internally in material design for elements that appear on screen temporarily. + * The service provides a promise-like API for interacting with the temporary + * elements. + * + * ```js + * app.service('$mdToast', function($$interimElement) { + * var $mdToast = $$interimElement(toastDefaultOptions); + * return $mdToast; + * }); + * ``` + * @param {object=} defaultOptions Options used by default for the `show` method on the service. + * + * @returns {$$interimElement.$service} + * + */ + +function InterimElementProvider() { + InterimElementFactory.$inject = ["$document", "$q", "$rootScope", "$timeout", "$rootElement", "$animate", "$mdUtil", "$mdCompiler", "$mdTheming", "$injector", "$exceptionHandler"]; + createInterimElementProvider.$get = InterimElementFactory; + return createInterimElementProvider; + + /** + * Returns a new provider which allows configuration of a new interimElement + * service. Allows configuration of default options & methods for options, + * as well as configuration of 'preset' methods (eg dialog.basic(): basic is a preset method) + */ + function createInterimElementProvider(interimFactoryName) { + factory.$inject = ["$$interimElement", "$injector"]; + var EXPOSED_METHODS = ['onHide', 'onShow', 'onRemove']; + + var customMethods = {}; + var providerConfig = { + presets: {} + }; + + var provider = { + setDefaults: setDefaults, + addPreset: addPreset, + addMethod: addMethod, + $get: factory + }; + + /** + * all interim elements will come with the 'build' preset + */ + provider.addPreset('build', { + methods: ['controller', 'controllerAs', 'resolve', 'multiple', + 'template', 'templateUrl', 'themable', 'transformTemplate', 'parent', 'contentElement'] + }); + + return provider; + + /** + * Save the configured defaults to be used when the factory is instantiated + */ + function setDefaults(definition) { + providerConfig.optionsFactory = definition.options; + providerConfig.methods = (definition.methods || []).concat(EXPOSED_METHODS); + return provider; + } + + /** + * Add a method to the factory that isn't specific to any interim element operations + */ + + function addMethod(name, fn) { + customMethods[name] = fn; + return provider; + } + + /** + * Save the configured preset to be used when the factory is instantiated + */ + function addPreset(name, definition) { + definition = definition || {}; + definition.methods = definition.methods || []; + definition.options = definition.options || function() { return {}; }; + + if (/^cancel|hide|show$/.test(name)) { + throw new Error("Preset '" + name + "' in " + interimFactoryName + " is reserved!"); + } + if (definition.methods.indexOf('_options') > -1) { + throw new Error("Method '_options' in " + interimFactoryName + " is reserved!"); + } + providerConfig.presets[name] = { + methods: definition.methods.concat(EXPOSED_METHODS), + optionsFactory: definition.options, + argOption: definition.argOption + }; + return provider; + } + + function addPresetMethod(presetName, methodName, method) { + providerConfig.presets[presetName][methodName] = method; + } + + /** + * Create a factory that has the given methods & defaults implementing interimElement + */ + /* @ngInject */ + function factory($$interimElement, $injector) { + var defaultMethods; + var defaultOptions; + var interimElementService = $$interimElement(); + + /* + * publicService is what the developer will be using. + * It has methods hide(), cancel(), show(), build(), and any other + * presets which were set during the config phase. + */ + var publicService = { + hide: interimElementService.hide, + cancel: interimElementService.cancel, + show: showInterimElement, + + // Special internal method to destroy an interim element without animations + // used when navigation changes causes a $scope.$destroy() action + destroy : destroyInterimElement + }; + + + defaultMethods = providerConfig.methods || []; + // This must be invoked after the publicService is initialized + defaultOptions = invokeFactory(providerConfig.optionsFactory, {}); + + // Copy over the simple custom methods + angular.forEach(customMethods, function(fn, name) { + publicService[name] = fn; + }); + + angular.forEach(providerConfig.presets, function(definition, name) { + var presetDefaults = invokeFactory(definition.optionsFactory, {}); + var presetMethods = (definition.methods || []).concat(defaultMethods); + + // Every interimElement built with a preset has a field called `$type`, + // which matches the name of the preset. + // Eg in preset 'confirm', options.$type === 'confirm' + angular.extend(presetDefaults, { $type: name }); + + // This creates a preset class which has setter methods for every + // method given in the `.addPreset()` function, as well as every + // method given in the `.setDefaults()` function. + // + // @example + // .setDefaults({ + // methods: ['hasBackdrop', 'clickOutsideToClose', 'escapeToClose', 'targetEvent'], + // options: dialogDefaultOptions + // }) + // .addPreset('alert', { + // methods: ['title', 'ok'], + // options: alertDialogOptions + // }) + // + // Set values will be passed to the options when interimElement.show() is called. + function Preset(opts) { + this._options = angular.extend({}, presetDefaults, opts); + } + angular.forEach(presetMethods, function(name) { + Preset.prototype[name] = function(value) { + this._options[name] = value; + return this; + }; + }); + + // Create shortcut method for one-linear methods + if (definition.argOption) { + var methodName = 'show' + name.charAt(0).toUpperCase() + name.slice(1); + publicService[methodName] = function(arg) { + var config = publicService[name](arg); + return publicService.show(config); + }; + } + + // eg $mdDialog.alert() will return a new alert preset + publicService[name] = function(arg) { + // If argOption is supplied, eg `argOption: 'content'`, then we assume + // if the argument is not an options object then it is the `argOption` option. + // + // @example `$mdToast.simple('hello')` // sets options.content to hello + // // because argOption === 'content' + if (arguments.length && definition.argOption && + !angular.isObject(arg) && !angular.isArray(arg)) { + + return (new Preset())[definition.argOption](arg); + + } else { + return new Preset(arg); + } + + }; + }); + + return publicService; + + /** + * + */ + function showInterimElement(opts) { + // opts is either a preset which stores its options on an _options field, + // or just an object made up of options + opts = opts || { }; + if (opts._options) opts = opts._options; + + return interimElementService.show( + angular.extend({}, defaultOptions, opts) + ); + } + + /** + * Special method to hide and destroy an interimElement WITHOUT + * any 'leave` or hide animations ( an immediate force hide/remove ) + * + * NOTE: This calls the onRemove() subclass method for each component... + * which must have code to respond to `options.$destroy == true` + */ + function destroyInterimElement(opts) { + return interimElementService.destroy(opts); + } + + /** + * Helper to call $injector.invoke with a local of the factory name for + * this provider. + * If an $mdDialog is providing options for a dialog and tries to inject + * $mdDialog, a circular dependency error will happen. + * We get around that by manually injecting $mdDialog as a local. + */ + function invokeFactory(factory, defaultVal) { + var locals = {}; + locals[interimFactoryName] = publicService; + return $injector.invoke(factory || function() { return defaultVal; }, {}, locals); + } + + } + + } + + /* @ngInject */ + function InterimElementFactory($document, $q, $rootScope, $timeout, $rootElement, $animate, + $mdUtil, $mdCompiler, $mdTheming, $injector, $exceptionHandler) { + return function createInterimElementService() { + var SHOW_CANCELLED = false; + + /* + * @ngdoc service + * @name $$interimElement.$service + * + * @description + * A service used to control inserting and removing an element into the DOM. + * + */ + + var service; + + var showPromises = []; // Promises for the interim's which are currently opening. + var hidePromises = []; // Promises for the interim's which are currently hiding. + var showingInterims = []; // Interim elements which are currently showing up. + + // Publish instance $$interimElement service; + // ... used as $mdDialog, $mdToast, $mdMenu, and $mdSelect + + return service = { + show: show, + hide: waitForInterim(hide), + cancel: waitForInterim(cancel), + destroy : destroy, + $injector_: $injector + }; + + /* + * @ngdoc method + * @name $$interimElement.$service#show + * @kind function + * + * @description + * Adds the `$interimElement` to the DOM and returns a special promise that will be resolved or rejected + * with hide or cancel, respectively. To external cancel/hide, developers should use the + * + * @param {*} options is hashMap of settings + * @returns a Promise + * + */ + function show(options) { + options = options || {}; + var interimElement = new InterimElement(options || {}); + + // When an interim element is currently showing, we have to cancel it. + // Just hiding it, will resolve the InterimElement's promise, the promise should be + // rejected instead. + var hideAction = options.multiple ? $q.resolve() : $q.all(showPromises); + + if (!options.multiple) { + // Wait for all opening interim's to finish their transition. + hideAction = hideAction.then(function() { + // Wait for all closing and showing interim's to be completely closed. + var promiseArray = hidePromises.concat(showingInterims.map(service.cancel)); + return $q.all(promiseArray); + }); + } + + var showAction = hideAction.then(function() { + + return interimElement + .show() + .then(function () { + showingInterims.push(interimElement); + }) + .catch(function (reason) { + return reason; + }) + .finally(function() { + showPromises.splice(showPromises.indexOf(showAction), 1); + }); + + }); + + showPromises.push(showAction); + + // In AngularJS 1.6+, exceptions inside promises will cause a rejection. We need to handle + // the rejection and only log it if it's an error. + interimElement.deferred.promise.catch(function(fault) { + if (fault instanceof Error) { + $exceptionHandler(fault); + } + + return fault; + }); + + // Return a promise that will be resolved when the interim + // element is hidden or cancelled... + return interimElement.deferred.promise; + } + + /* + * @ngdoc method + * @name $$interimElement.$service#hide + * @kind function + * + * @description + * Removes the `$interimElement` from the DOM and resolves the promise returned from `show` + * + * @param {*} resolveParam Data to resolve the promise with + * @returns a Promise that will be resolved after the element has been removed. + * + */ + function hide(reason, options) { + options = options || {}; + + if (options.closeAll) { + // We have to make a shallow copy of the array, because otherwise the map will break. + return $q.all(showingInterims.slice().reverse().map(closeElement)); + } else if (options.closeTo !== undefined) { + return $q.all(showingInterims.slice(options.closeTo).map(closeElement)); + } + + // Hide the latest showing interim element. + return closeElement(showingInterims[showingInterims.length - 1]); + + function closeElement(interim) { + + if (!interim) { + return $q.when(reason); + } + + var hideAction = interim + .remove(reason, false, options || { }) + .catch(function(reason) { return reason; }) + .finally(function() { + hidePromises.splice(hidePromises.indexOf(hideAction), 1); + }); + + showingInterims.splice(showingInterims.indexOf(interim), 1); + hidePromises.push(hideAction); + + return interim.deferred.promise; + } + } + + /* + * @ngdoc method + * @name $$interimElement.$service#cancel + * @kind function + * + * @description + * Removes the `$interimElement` from the DOM and rejects the promise returned from `show` + * + * @param {*} reason Data to reject the promise with + * @returns Promise that will be resolved after the element has been removed. + * + */ + function cancel(reason, options) { + var interim = showingInterims.pop(); + if (!interim) { + return $q.when(reason); + } + + var cancelAction = interim + .remove(reason, true, options || {}) + .catch(function(reason) { return reason; }) + .finally(function() { + hidePromises.splice(hidePromises.indexOf(cancelAction), 1); + }); + + hidePromises.push(cancelAction); + + // Since AngularJS 1.6.7, promises will be logged to $exceptionHandler when the promise + // is not handling the rejection. We create a pseudo catch handler, which will prevent the + // promise from being logged to the $exceptionHandler. + return interim.deferred.promise.catch(angular.noop); + } + + /** + * Creates a function to wait for at least one interim element to be available. + * @param callbackFn Function to be used as callback + * @returns {Function} + */ + function waitForInterim(callbackFn) { + return function() { + var fnArguments = arguments; + + if (!showingInterims.length) { + // When there are still interim's opening, then wait for the first interim element to + // finish its open animation. + if (showPromises.length) { + return showPromises[0].finally(function () { + return callbackFn.apply(service, fnArguments); + }); + } + + return $q.when("No interim elements currently showing up."); + } + + return callbackFn.apply(service, fnArguments); + }; + } + + /* + * Special method to quick-remove the interim element without animations + * Note: interim elements are in "interim containers" + */ + function destroy(targetEl) { + var interim = !targetEl ? showingInterims.shift() : null; + + var parentEl = angular.element(targetEl).length && angular.element(targetEl)[0].parentNode; + + if (parentEl) { + // Try to find the interim in the stack which corresponds to the supplied DOM element. + var filtered = showingInterims.filter(function(entry) { + return entry.options.element[0] === parentEl; + }); + + // Note: This function might be called when the element already has been removed, + // in which case we won't find any matches. + if (filtered.length) { + interim = filtered[0]; + showingInterims.splice(showingInterims.indexOf(interim), 1); + } + } + + return interim ? interim.remove(SHOW_CANCELLED, false, { '$destroy': true }) : + $q.when(SHOW_CANCELLED); + } + + /* + * Internal Interim Element Object + * Used internally to manage the DOM element and related data + */ + function InterimElement(options) { + var self, element, showAction = $q.when(true); + + options = configureScopeAndTransitions(options); + + return self = { + options : options, + deferred: $q.defer(), + show : createAndTransitionIn, + remove : transitionOutAndRemove + }; + + /** + * Compile, link, and show this interim element + * Use optional autoHided and transition-in effects + */ + function createAndTransitionIn() { + return $q(function(resolve, reject) { + + // Trigger onCompiling callback before the compilation starts. + // This is useful, when modifying options, which can be influenced by developers. + options.onCompiling && options.onCompiling(options); + + compileElement(options) + .then(function(compiledData) { + element = linkElement(compiledData, options); + + // Expose the cleanup function from the compiler. + options.cleanupElement = compiledData.cleanup; + + showAction = showElement(element, options, compiledData.controller) + .then(resolve, rejectAll); + }).catch(rejectAll); + + function rejectAll(fault) { + // Force the '$md.show()' promise to reject + self.deferred.reject(fault); + + // Continue rejection propagation + reject(fault); + } + }); + } + + /** + * After the show process has finished/rejected: + * - announce 'removing', + * - perform the transition-out, and + * - perform optional clean up scope. + */ + function transitionOutAndRemove(response, isCancelled, opts) { + + // abort if the show() and compile failed + if (!element) return $q.when(false); + + options = angular.extend(options || {}, opts || {}); + options.cancelAutoHide && options.cancelAutoHide(); + options.element.triggerHandler('$mdInterimElementRemove'); + + if (options.$destroy === true) { + + return hideElement(options.element, options).then(function(){ + (isCancelled && rejectAll(response)) || resolveAll(response); + }); + + } else { + $q.when(showAction).finally(function() { + hideElement(options.element, options).then(function() { + isCancelled ? rejectAll(response) : resolveAll(response); + }, rejectAll); + }); + + return self.deferred.promise; + } + + + /** + * The `show()` returns a promise that will be resolved when the interim + * element is hidden or cancelled... + */ + function resolveAll(response) { + self.deferred.resolve(response); + } + + /** + * Force the '$md.show()' promise to reject + */ + function rejectAll(fault) { + self.deferred.reject(fault); + } + } + + /** + * Prepare optional isolated scope and prepare $animate with default enter and leave + * transitions for the new element instance. + */ + function configureScopeAndTransitions(options) { + options = options || { }; + if (options.template) { + options.template = $mdUtil.processTemplate(options.template); + } + + return angular.extend({ + preserveScope: false, + cancelAutoHide : angular.noop, + scope: options.scope || $rootScope.$new(options.isolateScope), + + /** + * Default usage to enable $animate to transition-in; can be easily overridden via 'options' + */ + onShow: function transitionIn(scope, element, options) { + return $animate.enter(element, options.parent); + }, + + /** + * Default usage to enable $animate to transition-out; can be easily overridden via 'options' + */ + onRemove: function transitionOut(scope, element) { + // Element could be undefined if a new element is shown before + // the old one finishes compiling. + return element && $animate.leave(element) || $q.when(); + } + }, options); + + } + + /** + * Compile an element with a templateUrl, controller, and locals + */ + function compileElement(options) { + + var compiled = !options.skipCompile ? $mdCompiler.compile(options) : null; + + return compiled || $q(function (resolve) { + resolve({ + locals: {}, + link: function () { + return options.element; + } + }); + }); + } + + /** + * Link an element with compiled configuration + */ + function linkElement(compileData, options){ + angular.extend(compileData.locals, options); + + var element = compileData.link(options.scope); + + // Search for parent at insertion time, if not specified + options.element = element; + options.parent = findParent(element, options); + if (options.themable) $mdTheming(element); + + return element; + } + + /** + * Search for parent at insertion time, if not specified + */ + function findParent(element, options) { + var parent = options.parent; + + // Search for parent at insertion time, if not specified + if (angular.isFunction(parent)) { + parent = parent(options.scope, element, options); + } else if (angular.isString(parent)) { + parent = angular.element($document[0].querySelector(parent)); + } else { + parent = angular.element(parent); + } + + // If parent querySelector/getter function fails, or it's just null, + // find a default. + if (!(parent || {}).length) { + var el; + if ($rootElement[0] && $rootElement[0].querySelector) { + el = $rootElement[0].querySelector(':not(svg) > body'); + } + if (!el) el = $rootElement[0]; + if (el.nodeName == '#comment') { + el = $document[0].body; + } + return angular.element(el); + } + + return parent; + } + + /** + * If auto-hide is enabled, start timer and prepare cancel function + */ + function startAutoHide() { + var autoHideTimer, cancelAutoHide = angular.noop; + + if (options.hideDelay) { + autoHideTimer = $timeout(service.hide, options.hideDelay) ; + cancelAutoHide = function() { + $timeout.cancel(autoHideTimer); + }; + } + + // Cache for subsequent use + options.cancelAutoHide = function() { + cancelAutoHide(); + options.cancelAutoHide = undefined; + }; + } + + /** + * Show the element ( with transitions), notify complete and start + * optional auto-Hide + */ + function showElement(element, options, controller) { + // Trigger onShowing callback before the `show()` starts + var notifyShowing = options.onShowing || angular.noop; + // Trigger onComplete callback when the `show()` finishes + var notifyComplete = options.onComplete || angular.noop; + + // Necessary for consistency between AngularJS 1.5 and 1.6. + try { + notifyShowing(options.scope, element, options, controller); + } catch (e) { + return $q.reject(e); + } + + return $q(function (resolve, reject) { + try { + // Start transitionIn + $q.when(options.onShow(options.scope, element, options, controller)) + .then(function () { + notifyComplete(options.scope, element, options); + startAutoHide(); + + resolve(element); + }, reject); + + } catch (e) { + reject(e.message); + } + }); + } + + function hideElement(element, options) { + var announceRemoving = options.onRemoving || angular.noop; + + return $q(function (resolve, reject) { + try { + // Start transitionIn + var action = $q.when(options.onRemove(options.scope, element, options) || true); + + // Trigger callback *before* the remove operation starts + announceRemoving(element, action); + + if (options.$destroy) { + // For $destroy, onRemove should be synchronous + resolve(element); + + if (!options.preserveScope && options.scope) { + // scope destroy should still be be done after the current digest is done + action.then(function() { options.scope.$destroy(); }); + } + } else { + // Wait until transition-out is done + action.then(function () { + if (!options.preserveScope && options.scope) { + options.scope.$destroy(); + } + + resolve(element); + }, reject); + } + } catch (e) { + reject(e.message); + } + }); + } + + } + }; + + } + +} + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + var $mdUtil, $interpolate, $log; + + var SUFFIXES = /(-gt)?-(sm|md|lg|print)/g; + var WHITESPACE = /\s+/g; + + var FLEX_OPTIONS = ['grow', 'initial', 'auto', 'none', 'noshrink', 'nogrow']; + var LAYOUT_OPTIONS = ['row', 'column']; + var ALIGNMENT_MAIN_AXIS= ["", "start", "center", "end", "stretch", "space-around", "space-between"]; + var ALIGNMENT_CROSS_AXIS= ["", "start", "center", "end", "stretch"]; + + var config = { + /** + * Enable directive attribute-to-class conversions + * Developers can use `` to quickly + * disable the Layout directives and prohibit the injection of Layout classNames + */ + enabled: true, + + /** + * List of mediaQuery breakpoints and associated suffixes + * + * [ + * { suffix: "sm", mediaQuery: "screen and (max-width: 599px)" }, + * { suffix: "md", mediaQuery: "screen and (min-width: 600px) and (max-width: 959px)" } + * ] + */ + breakpoints: [] + }; + + registerLayoutAPI(angular.module('material.core.layout', ['ng'])); + + /** + * registerLayoutAPI() + * + * The original AngularJS Material Layout solution used attribute selectors and CSS. + * + * ```html + *
    My Content
    + * ``` + * + * ```css + * [layout] { + * box-sizing: border-box; + * display:flex; + * } + * [layout=column] { + * flex-direction : column + * } + * ``` + * + * Use of attribute selectors creates significant performance impacts in some + * browsers... mainly IE. + * + * This module registers directives that allow the same layout attributes to be + * interpreted and converted to class selectors. The directive will add equivalent classes to each element that + * contains a Layout directive. + * + * ```html + *
    My Content
    + *``` + * + * ```css + * .layout { + * box-sizing: border-box; + * display:flex; + * } + * .layout-column { + * flex-direction : column + * } + * ``` + */ + function registerLayoutAPI(module){ + var PREFIX_REGEXP = /^((?:x|data)[:\-_])/i; + var SPECIAL_CHARS_REGEXP = /([:\-_]+(.))/g; + + // NOTE: these are also defined in constants::MEDIA_PRIORITY and constants::MEDIA + var BREAKPOINTS = ["", "xs", "gt-xs", "sm", "gt-sm", "md", "gt-md", "lg", "gt-lg", "xl", "print"]; + var API_WITH_VALUES = ["layout", "flex", "flex-order", "flex-offset", "layout-align"]; + var API_NO_VALUES = ["show", "hide", "layout-padding", "layout-margin"]; + + + // Build directive registration functions for the standard Layout API... for all breakpoints. + angular.forEach(BREAKPOINTS, function(mqb) { + + // Attribute directives with expected, observable value(s) + angular.forEach(API_WITH_VALUES, function(name){ + var fullName = mqb ? name + "-" + mqb : name; + module.directive(directiveNormalize(fullName), attributeWithObserve(fullName)); + }); + + // Attribute directives with no expected value(s) + angular.forEach(API_NO_VALUES, function(name){ + var fullName = mqb ? name + "-" + mqb : name; + module.directive(directiveNormalize(fullName), attributeWithoutValue(fullName)); + }); + + }); + + // Register other, special directive functions for the Layout features: + module + + .provider('$$mdLayout' , function() { + // Publish internal service for Layouts + return { + $get : angular.noop, + validateAttributeValue : validateAttributeValue, + validateAttributeUsage : validateAttributeUsage, + /** + * Easy way to disable/enable the Layout API. + * When disabled, this stops all attribute-to-classname generations + */ + disableLayouts : function(isDisabled) { + config.enabled = (isDisabled !== true); + } + }; + }) + + .directive('mdLayoutCss' , disableLayoutDirective) + .directive('ngCloak' , buildCloakInterceptor('ng-cloak')) + + .directive('layoutWrap' , attributeWithoutValue('layout-wrap')) + .directive('layoutNowrap' , attributeWithoutValue('layout-nowrap')) + .directive('layoutNoWrap' , attributeWithoutValue('layout-no-wrap')) + .directive('layoutFill' , attributeWithoutValue('layout-fill')) + + // !! Deprecated attributes: use the `-lt` (aka less-than) notations + + .directive('layoutLtMd' , warnAttrNotSupported('layout-lt-md', true)) + .directive('layoutLtLg' , warnAttrNotSupported('layout-lt-lg', true)) + .directive('flexLtMd' , warnAttrNotSupported('flex-lt-md', true)) + .directive('flexLtLg' , warnAttrNotSupported('flex-lt-lg', true)) + + .directive('layoutAlignLtMd', warnAttrNotSupported('layout-align-lt-md')) + .directive('layoutAlignLtLg', warnAttrNotSupported('layout-align-lt-lg')) + .directive('flexOrderLtMd' , warnAttrNotSupported('flex-order-lt-md')) + .directive('flexOrderLtLg' , warnAttrNotSupported('flex-order-lt-lg')) + .directive('offsetLtMd' , warnAttrNotSupported('flex-offset-lt-md')) + .directive('offsetLtLg' , warnAttrNotSupported('flex-offset-lt-lg')) + + .directive('hideLtMd' , warnAttrNotSupported('hide-lt-md')) + .directive('hideLtLg' , warnAttrNotSupported('hide-lt-lg')) + .directive('showLtMd' , warnAttrNotSupported('show-lt-md')) + .directive('showLtLg' , warnAttrNotSupported('show-lt-lg')) + + // Determine if + .config(detectDisabledLayouts); + + /** + * Converts snake_case to camelCase. + * Also there is special case for Moz prefix starting with upper case letter. + * @param name Name to normalize + */ + function directiveNormalize(name) { + return name + .replace(PREFIX_REGEXP, '') + .replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { + return offset ? letter.toUpperCase() : letter; + }); + } + + } + + + /** + * Detect if any of the HTML tags has a [md-layouts-disabled] attribute; + * If yes, then immediately disable all layout API features + * + * Note: this attribute should be specified on either the HTML or BODY tags + */ + /** + * @ngInject + */ + function detectDisabledLayouts() { + var isDisabled = !!document.querySelector('[md-layouts-disabled]'); + config.enabled = !isDisabled; + } + + /** + * Special directive that will disable ALL Layout conversions of layout + * attribute(s) to classname(s). + * + * + * + * + * + * ... + * + * + * Note: Using md-layout-css directive requires the developer to load the Material + * Layout Attribute stylesheet (which only uses attribute selectors): + * + * `angular-material.layout.css` + * + * Another option is to use the LayoutProvider to configure and disable the attribute + * conversions; this would obviate the use of the `md-layout-css` directive + * + */ + function disableLayoutDirective() { + // Return a 1x-only, first-match attribute directive + config.enabled = false; + + return { + restrict : 'A', + priority : '900' + }; + } + + /** + * Tail-hook ngCloak to delay the uncloaking while Layout transformers + * finish processing. Eliminates flicker with Material.Layouts + */ + function buildCloakInterceptor(className) { + return ['$timeout', function($timeout){ + return { + restrict : 'A', + priority : -10, // run after normal ng-cloak + compile : function(element) { + if (!config.enabled) return angular.noop; + + // Re-add the cloak + element.addClass(className); + + return function(scope, element) { + // Wait while layout injectors configure, then uncloak + // NOTE: $rAF does not delay enough... and this is a 1x-only event, + // $timeout is acceptable. + $timeout(function(){ + element.removeClass(className); + }, 10, false); + }; + } + }; + }]; + } + + + // ********************************************************************************* + // + // These functions create registration functions for AngularJS Material Layout attribute directives + // This provides easy translation to switch AngularJS Material attribute selectors to + // CLASS selectors and directives; which has huge performance implications + // for IE Browsers + // + // ********************************************************************************* + + /** + * Creates a directive registration function where a possible dynamic attribute + * value will be observed/watched. + * @param {string} className attribute name; eg `layout-gt-md` with value ="row" + */ + function attributeWithObserve(className) { + + return ['$mdUtil', '$interpolate', "$log", function(_$mdUtil_, _$interpolate_, _$log_) { + $mdUtil = _$mdUtil_; + $interpolate = _$interpolate_; + $log = _$log_; + + return { + restrict: 'A', + compile: function(element, attr) { + var linkFn; + if (config.enabled) { + // immediately replace static (non-interpolated) invalid values... + + validateAttributeUsage(className, attr, element, $log); + + validateAttributeValue(className, + getNormalizedAttrValue(className, attr, ""), + buildUpdateFn(element, className, attr) + ); + + linkFn = translateWithValueToCssClass; + } + + // Use for postLink to account for transforms after ng-transclude. + return linkFn || angular.noop; + } + }; + }]; + + /** + * Add as transformed class selector(s), then + * remove the deprecated attribute selector + */ + function translateWithValueToCssClass(scope, element, attrs) { + var updateFn = updateClassWithValue(element, className, attrs); + var unwatch = attrs.$observe(attrs.$normalize(className), updateFn); + + updateFn(getNormalizedAttrValue(className, attrs, "")); + scope.$on("$destroy", function() { unwatch(); }); + } + } + + /** + * Creates a registration function for AngularJS Material Layout attribute directive. + * This is a `simple` transpose of attribute usage to class usage; where we ignore + * any attribute value + */ + function attributeWithoutValue(className) { + return ['$mdUtil', '$interpolate', "$log", function(_$mdUtil_, _$interpolate_, _$log_) { + $mdUtil = _$mdUtil_; + $interpolate = _$interpolate_; + $log = _$log_; + + return { + restrict: 'A', + compile: function(element, attr) { + var linkFn; + if (config.enabled) { + // immediately replace static (non-interpolated) invalid values... + + validateAttributeValue(className, + getNormalizedAttrValue(className, attr, ""), + buildUpdateFn(element, className, attr) + ); + + translateToCssClass(null, element); + + // Use for postLink to account for transforms after ng-transclude. + linkFn = translateToCssClass; + } + + return linkFn || angular.noop; + } + }; + }]; + + /** + * Add as transformed class selector, then + * remove the deprecated attribute selector + */ + function translateToCssClass(scope, element) { + element.addClass(className); + } + } + + + + /** + * After link-phase, do NOT remove deprecated layout attribute selector. + * Instead watch the attribute so interpolated data-bindings to layout + * selectors will continue to be supported. + * + * $observe() the className and update with new class (after removing the last one) + * + * e.g. `layout="{{layoutDemo.direction}}"` will update... + * + * NOTE: The value must match one of the specified styles in the CSS. + * For example `flex-gt-md="{{size}}` where `scope.size == 47` will NOT work since + * only breakpoints for 0, 5, 10, 15... 100, 33, 34, 66, 67 are defined. + * + */ + function updateClassWithValue(element, className) { + var lastClass; + + return function updateClassFn(newValue) { + var value = validateAttributeValue(className, newValue || ""); + if (angular.isDefined(value)) { + if (lastClass) element.removeClass(lastClass); + lastClass = !value ? className : className + "-" + value.trim().replace(WHITESPACE, "-"); + element.addClass(lastClass); + } + }; + } + + /** + * Provide console warning that this layout attribute has been deprecated + * + */ + function warnAttrNotSupported(className) { + var parts = className.split("-"); + return ["$log", function($log) { + $log.warn(className + "has been deprecated. Please use a `" + parts[0] + "-gt-` variant."); + return angular.noop; + }]; + } + + /** + * Centralize warnings for known flexbox issues (especially IE-related issues) + */ + function validateAttributeUsage(className, attr, element, $log){ + var message, usage, url; + var nodeName = element[0].nodeName.toLowerCase(); + + switch (className.replace(SUFFIXES,"")) { + case "flex": + if ((nodeName == "md-button") || (nodeName == "fieldset")){ + // @see https://github.com/philipwalton/flexbugs#9-some-html-elements-cant-be-flex-containers + // Use
    wrapper inside (preferred) or outside + + usage = "<" + nodeName + " " + className + ">"; + url = "https://github.com/philipwalton/flexbugs#9-some-html-elements-cant-be-flex-containers"; + message = "Markup '{0}' may not work as expected in IE Browsers. Consult '{1}' for details."; + + $log.warn($mdUtil.supplant(message, [usage, url])); + } + } + + } + + + /** + * For the Layout attribute value, validate or replace with default + * fallback value + */ + function validateAttributeValue(className, value, updateFn) { + var origValue; + + if (!needsInterpolation(value)) { + switch (className.replace(SUFFIXES,"")) { + case 'layout' : + if (!findIn(value, LAYOUT_OPTIONS)) { + value = LAYOUT_OPTIONS[0]; // 'row'; + } + break; + + case 'flex' : + if (!findIn(value, FLEX_OPTIONS)) { + if (isNaN(value)) { + value = ''; + } + } + break; + + case 'flex-offset' : + case 'flex-order' : + if (!value || isNaN(+value)) { + value = '0'; + } + break; + + case 'layout-align' : + var axis = extractAlignAxis(value); + value = $mdUtil.supplant("{main}-{cross}",axis); + break; + + case 'layout-padding' : + case 'layout-margin' : + case 'layout-fill' : + case 'layout-wrap' : + case 'layout-nowrap' : + value = ''; + break; + } + + if (value != origValue) { + (updateFn || angular.noop)(value); + } + } + + return value ? value.trim() : ""; + } + + /** + * Replace current attribute value with fallback value + */ + function buildUpdateFn(element, className, attrs) { + return function updateAttrValue(fallback) { + if (!needsInterpolation(fallback)) { + // Do not modify the element's attribute value; so + // uses '' will not + // be affected. Just update the attrs value. + attrs[attrs.$normalize(className)] = fallback; + } + }; + } + + /** + * See if the original value has interpolation symbols: + * e.g. flex-gt-md="{{triggerPoint}}" + */ + function needsInterpolation(value) { + return (value || "").indexOf($interpolate.startSymbol()) > -1; + } + + function getNormalizedAttrValue(className, attrs, defaultVal) { + var normalizedAttr = attrs.$normalize(className); + return attrs[normalizedAttr] ? attrs[normalizedAttr].trim().replace(WHITESPACE, "-") : defaultVal || null; + } + + function findIn(item, list, replaceWith) { + item = replaceWith && item ? item.replace(WHITESPACE, replaceWith) : item; + + var found = false; + if (item) { + list.forEach(function(it) { + it = replaceWith ? it.replace(WHITESPACE, replaceWith) : it; + found = found || (it === item); + }); + } + return found; + } + + function extractAlignAxis(attrValue) { + var axis = { + main : "start", + cross: "stretch" + }, values; + + attrValue = (attrValue || ""); + + if (attrValue.indexOf("-") === 0 || attrValue.indexOf(" ") === 0) { + // For missing main-axis values + attrValue = "none" + attrValue; + } + + values = attrValue.toLowerCase().trim().replace(WHITESPACE, "-").split("-"); + if (values.length && (values[0] === "space")) { + // for main-axis values of "space-around" or "space-between" + values = [values[0]+"-"+values[1],values[2]]; + } + + if (values.length > 0) axis.main = values[0] || axis.main; + if (values.length > 1) axis.cross = values[1] || axis.cross; + + if (ALIGNMENT_MAIN_AXIS.indexOf(axis.main) < 0) axis.main = "start"; + if (ALIGNMENT_CROSS_AXIS.indexOf(axis.cross) < 0) axis.cross = "stretch"; + + return axis; + } + + +})(); + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.core.liveannouncer + * @description + * AngularJS Material Live Announcer to provide accessibility for Voice Readers. + */ +MdLiveAnnouncer.$inject = ["$timeout"]; +angular + .module('material.core') + .service('$mdLiveAnnouncer', MdLiveAnnouncer); + +/** + * @ngdoc service + * @name $mdLiveAnnouncer + * @module material.core.liveannouncer + * + * @description + * + * Service to announce messages to supported screenreaders. + * + * > The `$mdLiveAnnouncer` service is internally used for components to provide proper accessibility. + * + * + * module.controller('AppCtrl', function($mdLiveAnnouncer) { + * // Basic announcement (Polite Mode) + * $mdLiveAnnouncer.announce('Hey Google'); + * + * // Custom announcement (Assertive Mode) + * $mdLiveAnnouncer.announce('Hey Google', 'assertive'); + * }); + * + * + */ +function MdLiveAnnouncer($timeout) { + /** @private @const @type {!angular.$timeout} */ + this._$timeout = $timeout; + + /** @private @const @type {!HTMLElement} */ + this._liveElement = this._createLiveElement(); + + /** @private @const @type {!number} */ + this._announceTimeout = 100; +} + +/** + * @ngdoc method + * @name $mdLiveAnnouncer#announce + * @description Announces messages to supported screenreaders. + * @param {string} message Message to be announced to the screenreader + * @param {'off'|'polite'|'assertive'} politeness The politeness of the announcer element. + */ +MdLiveAnnouncer.prototype.announce = function(message, politeness) { + if (!politeness) { + politeness = 'polite'; + } + + var self = this; + + self._liveElement.textContent = ''; + self._liveElement.setAttribute('aria-live', politeness); + + // This 100ms timeout is necessary for some browser + screen-reader combinations: + // - Both JAWS and NVDA over IE11 will not announce anything without a non-zero timeout. + // - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a + // second time without clearing and then using a non-zero delay. + // (using JAWS 17 at time of this writing). + self._$timeout(function() { + self._liveElement.textContent = message; + }, self._announceTimeout, false); +}; + +/** + * Creates a live announcer element, which listens for DOM changes and announces them + * to the screenreaders. + * @returns {!HTMLElement} + * @private + */ +MdLiveAnnouncer.prototype._createLiveElement = function() { + var liveEl = document.createElement('div'); + + liveEl.classList.add('md-visually-hidden'); + liveEl.setAttribute('role', 'status'); + liveEl.setAttribute('aria-atomic', 'true'); + liveEl.setAttribute('aria-live', 'polite'); + + document.body.appendChild(liveEl); + + return liveEl; +}; + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc service + * @name $$mdMeta + * @module material.core.meta + * + * @description + * + * A provider and a service that simplifies meta tags access + * + * Note: This is intended only for use with dynamic meta tags such as browser color and title. + * Tags that are only processed when the page is rendered (such as `charset`, and `http-equiv`) + * will not work since `$$mdMeta` adds the tags after the page has already been loaded. + * + * ```js + * app.config(function($$mdMetaProvider) { + * var removeMeta = $$mdMetaProvider.setMeta('meta-name', 'content'); + * var metaValue = $$mdMetaProvider.getMeta('meta-name'); // -> 'content' + * + * removeMeta(); + * }); + * + * app.controller('myController', function($$mdMeta) { + * var removeMeta = $$mdMeta.setMeta('meta-name', 'content'); + * var metaValue = $$mdMeta.getMeta('meta-name'); // -> 'content' + * + * removeMeta(); + * }); + * ``` + * + * @returns {$$mdMeta.$service} + * + */ +angular.module('material.core.meta', []) + .provider('$$mdMeta', function () { + var head = angular.element(document.head); + var metaElements = {}; + + /** + * Checks if the requested element was written manually and maps it + * + * @param {string} name meta tag 'name' attribute value + * @returns {boolean} returns true if there is an element with the requested name + */ + function mapExistingElement(name) { + if (metaElements[name]) { + return true; + } + + var element = document.getElementsByName(name)[0]; + + if (!element) { + return false; + } + + metaElements[name] = angular.element(element); + + return true; + } + + /** + * @ngdoc method + * @name $$mdMeta#setMeta + * + * @description + * Creates meta element with the 'name' and 'content' attributes, + * if the meta tag is already created than we replace the 'content' value + * + * @param {string} name meta tag 'name' attribute value + * @param {string} content meta tag 'content' attribute value + * @returns {function} remove function + * + */ + function setMeta(name, content) { + mapExistingElement(name); + + if (!metaElements[name]) { + var newMeta = angular.element(''); + head.append(newMeta); + metaElements[name] = newMeta; + } + else { + metaElements[name].attr('content', content); + } + + return function () { + metaElements[name].attr('content', ''); + metaElements[name].remove(); + delete metaElements[name]; + }; + } + + /** + * @ngdoc method + * @name $$mdMeta#getMeta + * + * @description + * Gets the 'content' attribute value of the wanted meta element + * + * @param {string} name meta tag 'name' attribute value + * @returns {string} content attribute value + */ + function getMeta(name) { + if (!mapExistingElement(name)) { + throw Error('$$mdMeta: could not find a meta tag with the name \'' + name + '\''); + } + + return metaElements[name].attr('content'); + } + + var module = { + setMeta: setMeta, + getMeta: getMeta + }; + + return angular.extend({}, module, { + $get: function () { + return module; + } + }); + }); +})(); +(function(){ +"use strict"; + + /** + * @ngdoc module + * @name material.core.componentRegistry + * + * @description + * A component instance registration service. + * Note: currently this as a private service in the SideNav component. + */ + ComponentRegistry.$inject = ["$log", "$q"]; + angular.module('material.core') + .factory('$mdComponentRegistry', ComponentRegistry); + + /* + * @private + * @ngdoc factory + * @name ComponentRegistry + * @module material.core.componentRegistry + * + */ + function ComponentRegistry($log, $q) { + + var self; + var instances = []; + var pendings = { }; + + return self = { + /** + * Used to print an error when an instance for a handle isn't found. + */ + notFoundError: function(handle, msgContext) { + $log.error((msgContext || "") + 'No instance found for handle', handle); + }, + /** + * Return all registered instances as an array. + */ + getInstances: function() { + return instances; + }, + + /** + * Get a registered instance. + * @param handle the String handle to look up for a registered instance. + */ + get: function(handle) { + if (!isValidID(handle)) return null; + + var i, j, instance; + for (i = 0, j = instances.length; i < j; i++) { + instance = instances[i]; + if (instance.$$mdHandle === handle) { + return instance; + } + } + return null; + }, + + /** + * Register an instance. + * @param instance the instance to register + * @param handle the handle to identify the instance under. + */ + register: function(instance, handle) { + if (!handle) return angular.noop; + + instance.$$mdHandle = handle; + instances.push(instance); + resolveWhen(); + + return deregister; + + /** + * Remove registration for an instance + */ + function deregister() { + var index = instances.indexOf(instance); + if (index !== -1) { + instances.splice(index, 1); + } + } + + /** + * Resolve any pending promises for this instance + */ + function resolveWhen() { + var dfd = pendings[handle]; + if (dfd) { + dfd.forEach(function (promise) { + promise.resolve(instance); + }); + delete pendings[handle]; + } + } + }, + + /** + * Async accessor to registered component instance + * If not available then a promise is created to notify + * all listeners when the instance is registered. + */ + when : function(handle) { + if (isValidID(handle)) { + var deferred = $q.defer(); + var instance = self.get(handle); + + if (instance) { + deferred.resolve(instance); + } else { + if (pendings[handle] === undefined) { + pendings[handle] = []; + } + pendings[handle].push(deferred); + } + + return deferred.promise; + } + return $q.reject("Invalid `md-component-id` value."); + } + + }; + + function isValidID(handle){ + return handle && (handle !== ""); + } + + } + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + /** + * @ngdoc service + * @name $mdButtonInkRipple + * @module material.core + * + * @description + * Provides ripple effects for md-button. See $mdInkRipple service for all possible configuration options. + * + * @param {object=} scope Scope within the current context + * @param {object=} element The element the ripple effect should be applied to + * @param {object=} options (Optional) Configuration options to override the default ripple configuration + */ + + MdButtonInkRipple.$inject = ["$mdInkRipple"]; + angular.module('material.core') + .factory('$mdButtonInkRipple', MdButtonInkRipple); + + function MdButtonInkRipple($mdInkRipple) { + return { + attach: function attachRipple(scope, element, options) { + options = angular.extend(optionsForElement(element), options); + + return $mdInkRipple.attach(scope, element, options); + } + }; + + function optionsForElement(element) { + if (element.hasClass('md-icon-button')) { + return { + isMenuItem: element.hasClass('md-menu-item'), + fitRipple: true, + center: true + }; + } else { + return { + isMenuItem: element.hasClass('md-menu-item'), + dimBackground: true + }; + } + } + } +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + /** + * @ngdoc service + * @name $mdCheckboxInkRipple + * @module material.core + * + * @description + * Provides ripple effects for md-checkbox. See $mdInkRipple service for all possible configuration options. + * + * @param {object=} scope Scope within the current context + * @param {object=} element The element the ripple effect should be applied to + * @param {object=} options (Optional) Configuration options to override the defaultripple configuration + */ + + MdCheckboxInkRipple.$inject = ["$mdInkRipple"]; + angular.module('material.core') + .factory('$mdCheckboxInkRipple', MdCheckboxInkRipple); + + function MdCheckboxInkRipple($mdInkRipple) { + return { + attach: attach + }; + + function attach(scope, element, options) { + return $mdInkRipple.attach(scope, element, angular.extend({ + center: true, + dimBackground: false, + fitRipple: true + }, options)); + } + } +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + /** + * @ngdoc service + * @name $mdListInkRipple + * @module material.core + * + * @description + * Provides ripple effects for md-list. See $mdInkRipple service for all possible configuration options. + * + * @param {object=} scope Scope within the current context + * @param {object=} element The element the ripple effect should be applied to + * @param {object=} options (Optional) Configuration options to override the defaultripple configuration + */ + + MdListInkRipple.$inject = ["$mdInkRipple"]; + angular.module('material.core') + .factory('$mdListInkRipple', MdListInkRipple); + + function MdListInkRipple($mdInkRipple) { + return { + attach: attach + }; + + function attach(scope, element, options) { + return $mdInkRipple.attach(scope, element, angular.extend({ + center: false, + dimBackground: true, + outline: false, + rippleSize: 'full' + }, options)); + } + } +})(); + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.core.ripple + * @description + * Ripple + */ +InkRippleCtrl.$inject = ["$scope", "$element", "rippleOptions", "$window", "$timeout", "$mdUtil", "$mdColorUtil"]; +InkRippleDirective.$inject = ["$mdButtonInkRipple", "$mdCheckboxInkRipple"]; +angular.module('material.core') + .provider('$mdInkRipple', InkRippleProvider) + .directive('mdInkRipple', InkRippleDirective) + .directive('mdNoInk', attrNoDirective) + .directive('mdNoBar', attrNoDirective) + .directive('mdNoStretch', attrNoDirective); + +var DURATION = 450; + +/** + * @ngdoc directive + * @name mdInkRipple + * @module material.core.ripple + * + * @description + * The `md-ink-ripple` directive allows you to specify the ripple color or if a ripple is allowed. + * + * @param {string|boolean} md-ink-ripple A color string `#FF0000` or boolean (`false` or `0`) for + * preventing ripple + * + * @usage + * ### String values + * + * + * Ripples in red + * + * + * + * Not rippling + * + * + * + * ### Interpolated values + * + * + * Ripples with the return value of 'randomColor' function + * + * + * + * Ripples if 'canRipple' function return value is not 'false' or '0' + * + * + */ +function InkRippleDirective ($mdButtonInkRipple, $mdCheckboxInkRipple) { + return { + controller: angular.noop, + link: function (scope, element, attr) { + attr.hasOwnProperty('mdInkRippleCheckbox') + ? $mdCheckboxInkRipple.attach(scope, element) + : $mdButtonInkRipple.attach(scope, element); + } + }; +} + +/** + * @ngdoc service + * @name $mdInkRipple + * @module material.core.ripple + * + * @description + * `$mdInkRipple` is a service for adding ripples to any element. + * + * @usage + * + * app.factory('$myElementInkRipple', function($mdInkRipple) { + * return { + * attach: function (scope, element, options) { + * return $mdInkRipple.attach(scope, element, angular.extend({ + * center: false, + * dimBackground: true + * }, options)); + * } + * }; + * }); + * + * app.controller('myController', function ($scope, $element, $myElementInkRipple) { + * $scope.onClick = function (ev) { + * $myElementInkRipple.attach($scope, angular.element(ev.target), { center: true }); + * } + * }); + * + */ + +/** + * @ngdoc service + * @name $mdInkRippleProvider + * @module material.core.ripple + * + * @description + * If you want to disable ink ripples globally, for all components, you can call the + * `disableInkRipple` method in your app's config. + * + * + * @usage + * + * app.config(function ($mdInkRippleProvider) { + * $mdInkRippleProvider.disableInkRipple(); + * }); + * + */ + +function InkRippleProvider () { + var isDisabledGlobally = false; + + return { + disableInkRipple: disableInkRipple, + $get: ["$injector", function($injector) { + return { attach: attach }; + + /** + * @ngdoc method + * @name $mdInkRipple#attach + * + * @description + * Attaching given scope, element and options to inkRipple controller + * + * @param {object=} scope Scope within the current context + * @param {object=} element The element the ripple effect should be applied to + * @param {object=} options (Optional) Configuration options to override the defaultRipple configuration + * * `center` - Whether the ripple should start from the center of the container element + * * `dimBackground` - Whether the background should be dimmed with the ripple color + * * `colorElement` - The element the ripple should take its color from, defined by css property `color` + * * `fitRipple` - Whether the ripple should fill the element + */ + function attach (scope, element, options) { + if (isDisabledGlobally || element.controller('mdNoInk')) return angular.noop; + return $injector.instantiate(InkRippleCtrl, { + $scope: scope, + $element: element, + rippleOptions: options + }); + } + }] + }; + + /** + * @ngdoc method + * @name $mdInkRippleProvider#disableInkRipple + * + * @description + * A config-time method that, when called, disables ripples globally. + */ + function disableInkRipple () { + isDisabledGlobally = true; + } +} + +/** + * Controller used by the ripple service in order to apply ripples + * @ngInject + */ +function InkRippleCtrl ($scope, $element, rippleOptions, $window, $timeout, $mdUtil, $mdColorUtil) { + this.$window = $window; + this.$timeout = $timeout; + this.$mdUtil = $mdUtil; + this.$mdColorUtil = $mdColorUtil; + this.$scope = $scope; + this.$element = $element; + this.options = rippleOptions; + this.mousedown = false; + this.ripples = []; + this.timeout = null; // Stores a reference to the most-recent ripple timeout + this.lastRipple = null; + + $mdUtil.valueOnUse(this, 'container', this.createContainer); + + this.$element.addClass('md-ink-ripple'); + + // attach method for unit tests + ($element.controller('mdInkRipple') || {}).createRipple = angular.bind(this, this.createRipple); + ($element.controller('mdInkRipple') || {}).setColor = angular.bind(this, this.color); + + this.bindEvents(); +} + + +/** + * Either remove or unlock any remaining ripples when the user mouses off of the element (either by + * mouseup or mouseleave event) + */ +function autoCleanup (self, cleanupFn) { + if (self.mousedown || self.lastRipple) { + self.mousedown = false; + self.$mdUtil.nextTick(angular.bind(self, cleanupFn), false); + } +} + + +/** + * Returns the color that the ripple should be (either based on CSS or hard-coded) + * @returns {string} + */ +InkRippleCtrl.prototype.color = function (value) { + var self = this; + + // If assigning a color value, apply it to background and the ripple color + if (angular.isDefined(value)) { + self._color = self._parseColor(value); + } + + // If color lookup, use assigned, defined, or inherited + return self._color || self._parseColor(self.inkRipple()) || self._parseColor(getElementColor()); + + /** + * Finds the color element and returns its text color for use as default ripple color + * @returns {string} + */ + function getElementColor () { + var items = self.options && self.options.colorElement ? self.options.colorElement : []; + var elem = items.length ? items[ 0 ] : self.$element[ 0 ]; + + return elem ? self.$window.getComputedStyle(elem).color : 'rgb(0,0,0)'; + } +}; + +/** + * Updating the ripple colors based on the current inkRipple value + * or the element's computed style color + */ +InkRippleCtrl.prototype.calculateColor = function () { + return this.color(); +}; + + +/** + * Takes a string color and converts it to RGBA format + * @param {string} color + * @param {number} multiplier + * @returns {string} + */ +InkRippleCtrl.prototype._parseColor = function parseColor (color, multiplier) { + multiplier = multiplier || 1; + var colorUtil = this.$mdColorUtil; + + if (!color) return; + if (color.indexOf('rgba') === 0) return color.replace(/\d?\.?\d*\s*\)\s*$/, (0.1 * multiplier).toString() + ')'); + if (color.indexOf('rgb') === 0) return colorUtil.rgbToRgba(color); + if (color.indexOf('#') === 0) return colorUtil.hexToRgba(color); + +}; + +/** + * Binds events to the root element for + */ +InkRippleCtrl.prototype.bindEvents = function () { + this.$element.on('mousedown', angular.bind(this, this.handleMousedown)); + this.$element.on('mouseup touchend', angular.bind(this, this.handleMouseup)); + this.$element.on('mouseleave', angular.bind(this, this.handleMouseup)); + this.$element.on('touchmove', angular.bind(this, this.handleTouchmove)); +}; + +/** + * Create a new ripple on every mousedown event from the root element + * @param event {MouseEvent} + */ +InkRippleCtrl.prototype.handleMousedown = function (event) { + if (this.mousedown) return; + + // When jQuery is loaded, we have to get the original event + if (event.hasOwnProperty('originalEvent')) event = event.originalEvent; + this.mousedown = true; + if (this.options.center) { + this.createRipple(this.container.prop('clientWidth') / 2, this.container.prop('clientWidth') / 2); + } else { + + // We need to calculate the relative coordinates if the target is a sublayer of the ripple element + if (event.srcElement !== this.$element[0]) { + var layerRect = this.$element[0].getBoundingClientRect(); + var layerX = event.clientX - layerRect.left; + var layerY = event.clientY - layerRect.top; + + this.createRipple(layerX, layerY); + } else { + this.createRipple(event.offsetX, event.offsetY); + } + } +}; + +/** + * Either remove or unlock any remaining ripples when the user mouses off of the element (either by + * mouseup, touchend or mouseleave event) + */ +InkRippleCtrl.prototype.handleMouseup = function () { + this.$timeout(function () { + autoCleanup(this, this.clearRipples); + }.bind(this)); +}; + +/** + * Either remove or unlock any remaining ripples when the user mouses off of the element (by + * touchmove) + */ +InkRippleCtrl.prototype.handleTouchmove = function () { + autoCleanup(this, this.deleteRipples); +}; + +/** + * Cycles through all ripples and attempts to remove them. + */ +InkRippleCtrl.prototype.deleteRipples = function () { + for (var i = 0; i < this.ripples.length; i++) { + this.ripples[ i ].remove(); + } +}; + +/** + * Cycles through all ripples and attempts to remove them with fade. + * Depending on logic within `fadeInComplete`, some removals will be postponed. + */ +InkRippleCtrl.prototype.clearRipples = function () { + for (var i = 0; i < this.ripples.length; i++) { + this.fadeInComplete(this.ripples[ i ]); + } +}; + +/** + * Creates the ripple container element + * @returns {*} + */ +InkRippleCtrl.prototype.createContainer = function () { + var container = angular.element('
    '); + this.$element.append(container); + return container; +}; + +InkRippleCtrl.prototype.clearTimeout = function () { + if (this.timeout) { + this.$timeout.cancel(this.timeout); + this.timeout = null; + } +}; + +InkRippleCtrl.prototype.isRippleAllowed = function () { + var element = this.$element[0]; + do { + if (!element.tagName || element.tagName === 'BODY') break; + + if (element && angular.isFunction(element.hasAttribute)) { + if (element.hasAttribute('disabled')) return false; + if (this.inkRipple() === 'false' || this.inkRipple() === '0') return false; + } + + } while (element = element.parentNode); + return true; +}; + +/** + * The attribute `md-ink-ripple` may be a static or interpolated + * color value OR a boolean indicator (used to disable ripples) + */ +InkRippleCtrl.prototype.inkRipple = function () { + return this.$element.attr('md-ink-ripple'); +}; + +/** + * Creates a new ripple and adds it to the container. Also tracks ripple in `this.ripples`. + * @param left + * @param top + */ +InkRippleCtrl.prototype.createRipple = function (left, top) { + if (!this.isRippleAllowed()) return; + + var ctrl = this; + var colorUtil = ctrl.$mdColorUtil; + var ripple = angular.element('
    '); + var width = this.$element.prop('clientWidth'); + var height = this.$element.prop('clientHeight'); + var x = Math.max(Math.abs(width - left), left) * 2; + var y = Math.max(Math.abs(height - top), top) * 2; + var size = getSize(this.options.fitRipple, x, y); + var color = this.calculateColor(); + + ripple.css({ + left: left + 'px', + top: top + 'px', + background: 'black', + width: size + 'px', + height: size + 'px', + backgroundColor: colorUtil.rgbaToRgb(color), + borderColor: colorUtil.rgbaToRgb(color) + }); + this.lastRipple = ripple; + + // we only want one timeout to be running at a time + this.clearTimeout(); + this.timeout = this.$timeout(function () { + ctrl.clearTimeout(); + if (!ctrl.mousedown) ctrl.fadeInComplete(ripple); + }, DURATION * 0.35, false); + + if (this.options.dimBackground) this.container.css({ backgroundColor: color }); + this.container.append(ripple); + this.ripples.push(ripple); + ripple.addClass('md-ripple-placed'); + + this.$mdUtil.nextTick(function () { + + ripple.addClass('md-ripple-scaled md-ripple-active'); + ctrl.$timeout(function () { + ctrl.clearRipples(); + }, DURATION, false); + + }, false); + + function getSize (fit, x, y) { + return fit + ? Math.max(x, y) + : Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + } +}; + + + +/** + * After fadeIn finishes, either kicks off the fade-out animation or queues the element for removal on mouseup + * @param ripple + */ +InkRippleCtrl.prototype.fadeInComplete = function (ripple) { + if (this.lastRipple === ripple) { + if (!this.timeout && !this.mousedown) { + this.removeRipple(ripple); + } + } else { + this.removeRipple(ripple); + } +}; + +/** + * Kicks off the animation for removing a ripple + * @param ripple {Element} + */ +InkRippleCtrl.prototype.removeRipple = function (ripple) { + var ctrl = this; + var index = this.ripples.indexOf(ripple); + if (index < 0) return; + this.ripples.splice(this.ripples.indexOf(ripple), 1); + ripple.removeClass('md-ripple-active'); + ripple.addClass('md-ripple-remove'); + if (this.ripples.length === 0) this.container.css({ backgroundColor: '' }); + // use a 2-second timeout in order to allow for the animation to finish + // we don't actually care how long the animation takes + this.$timeout(function () { + ctrl.fadeOutComplete(ripple); + }, DURATION, false); +}; + +/** + * Removes the provided ripple from the DOM + * @param ripple + */ +InkRippleCtrl.prototype.fadeOutComplete = function (ripple) { + ripple.remove(); + this.lastRipple = null; +}; + +/** + * Used to create an empty directive. This is used to track flag-directives whose children may have + * functionality based on them. + * + * Example: `md-no-ink` will potentially be used by all child directives. + */ +function attrNoDirective () { + return { controller: angular.noop }; +} + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + /** + * @ngdoc service + * @name $mdTabInkRipple + * @module material.core + * + * @description + * Provides ripple effects for md-tabs. See $mdInkRipple service for all possible configuration options. + * + * @param {object=} scope Scope within the current context + * @param {object=} element The element the ripple effect should be applied to + * @param {object=} options (Optional) Configuration options to override the defaultripple configuration + */ + + MdTabInkRipple.$inject = ["$mdInkRipple"]; + angular.module('material.core') + .factory('$mdTabInkRipple', MdTabInkRipple); + + function MdTabInkRipple($mdInkRipple) { + return { + attach: attach + }; + + function attach(scope, element, options) { + return $mdInkRipple.attach(scope, element, angular.extend({ + center: false, + dimBackground: true, + outline: false, + rippleSize: 'full' + }, options)); + } + } +})(); + +})(); +(function(){ +"use strict"; + +angular.module('material.core.theming.palette', []) +.constant('$mdColorPalette', { + 'red': { + '50': '#ffebee', + '100': '#ffcdd2', + '200': '#ef9a9a', + '300': '#e57373', + '400': '#ef5350', + '500': '#f44336', + '600': '#e53935', + '700': '#d32f2f', + '800': '#c62828', + '900': '#b71c1c', + 'A100': '#ff8a80', + 'A200': '#ff5252', + 'A400': '#ff1744', + 'A700': '#d50000', + 'contrastDefaultColor': 'light', + 'contrastDarkColors': '50 100 200 300 A100', + 'contrastStrongLightColors': '400 500 600 700 A200 A400 A700' + }, + 'pink': { + '50': '#fce4ec', + '100': '#f8bbd0', + '200': '#f48fb1', + '300': '#f06292', + '400': '#ec407a', + '500': '#e91e63', + '600': '#d81b60', + '700': '#c2185b', + '800': '#ad1457', + '900': '#880e4f', + 'A100': '#ff80ab', + 'A200': '#ff4081', + 'A400': '#f50057', + 'A700': '#c51162', + 'contrastDefaultColor': 'light', + 'contrastDarkColors': '50 100 200 A100', + 'contrastStrongLightColors': '500 600 A200 A400 A700' + }, + 'purple': { + '50': '#f3e5f5', + '100': '#e1bee7', + '200': '#ce93d8', + '300': '#ba68c8', + '400': '#ab47bc', + '500': '#9c27b0', + '600': '#8e24aa', + '700': '#7b1fa2', + '800': '#6a1b9a', + '900': '#4a148c', + 'A100': '#ea80fc', + 'A200': '#e040fb', + 'A400': '#d500f9', + 'A700': '#aa00ff', + 'contrastDefaultColor': 'light', + 'contrastDarkColors': '50 100 200 A100', + 'contrastStrongLightColors': '300 400 A200 A400 A700' + }, + 'deep-purple': { + '50': '#ede7f6', + '100': '#d1c4e9', + '200': '#b39ddb', + '300': '#9575cd', + '400': '#7e57c2', + '500': '#673ab7', + '600': '#5e35b1', + '700': '#512da8', + '800': '#4527a0', + '900': '#311b92', + 'A100': '#b388ff', + 'A200': '#7c4dff', + 'A400': '#651fff', + 'A700': '#6200ea', + 'contrastDefaultColor': 'light', + 'contrastDarkColors': '50 100 200 A100', + 'contrastStrongLightColors': '300 400 A200' + }, + 'indigo': { + '50': '#e8eaf6', + '100': '#c5cae9', + '200': '#9fa8da', + '300': '#7986cb', + '400': '#5c6bc0', + '500': '#3f51b5', + '600': '#3949ab', + '700': '#303f9f', + '800': '#283593', + '900': '#1a237e', + 'A100': '#8c9eff', + 'A200': '#536dfe', + 'A400': '#3d5afe', + 'A700': '#304ffe', + 'contrastDefaultColor': 'light', + 'contrastDarkColors': '50 100 200 A100', + 'contrastStrongLightColors': '300 400 A200 A400' + }, + 'blue': { + '50': '#e3f2fd', + '100': '#bbdefb', + '200': '#90caf9', + '300': '#64b5f6', + '400': '#42a5f5', + '500': '#2196f3', + '600': '#1e88e5', + '700': '#1976d2', + '800': '#1565c0', + '900': '#0d47a1', + 'A100': '#82b1ff', + 'A200': '#448aff', + 'A400': '#2979ff', + 'A700': '#2962ff', + 'contrastDefaultColor': 'light', + 'contrastDarkColors': '50 100 200 300 400 A100', + 'contrastStrongLightColors': '500 600 700 A200 A400 A700' + }, + 'light-blue': { + '50': '#e1f5fe', + '100': '#b3e5fc', + '200': '#81d4fa', + '300': '#4fc3f7', + '400': '#29b6f6', + '500': '#03a9f4', + '600': '#039be5', + '700': '#0288d1', + '800': '#0277bd', + '900': '#01579b', + 'A100': '#80d8ff', + 'A200': '#40c4ff', + 'A400': '#00b0ff', + 'A700': '#0091ea', + 'contrastDefaultColor': 'dark', + 'contrastLightColors': '600 700 800 900 A700', + 'contrastStrongLightColors': '600 700 800 A700' + }, + 'cyan': { + '50': '#e0f7fa', + '100': '#b2ebf2', + '200': '#80deea', + '300': '#4dd0e1', + '400': '#26c6da', + '500': '#00bcd4', + '600': '#00acc1', + '700': '#0097a7', + '800': '#00838f', + '900': '#006064', + 'A100': '#84ffff', + 'A200': '#18ffff', + 'A400': '#00e5ff', + 'A700': '#00b8d4', + 'contrastDefaultColor': 'dark', + 'contrastLightColors': '700 800 900', + 'contrastStrongLightColors': '700 800 900' + }, + 'teal': { + '50': '#e0f2f1', + '100': '#b2dfdb', + '200': '#80cbc4', + '300': '#4db6ac', + '400': '#26a69a', + '500': '#009688', + '600': '#00897b', + '700': '#00796b', + '800': '#00695c', + '900': '#004d40', + 'A100': '#a7ffeb', + 'A200': '#64ffda', + 'A400': '#1de9b6', + 'A700': '#00bfa5', + 'contrastDefaultColor': 'dark', + 'contrastLightColors': '500 600 700 800 900', + 'contrastStrongLightColors': '500 600 700' + }, + 'green': { + '50': '#e8f5e9', + '100': '#c8e6c9', + '200': '#a5d6a7', + '300': '#81c784', + '400': '#66bb6a', + '500': '#4caf50', + '600': '#43a047', + '700': '#388e3c', + '800': '#2e7d32', + '900': '#1b5e20', + 'A100': '#b9f6ca', + 'A200': '#69f0ae', + 'A400': '#00e676', + 'A700': '#00c853', + 'contrastDefaultColor': 'dark', + 'contrastLightColors': '500 600 700 800 900', + 'contrastStrongLightColors': '500 600 700' + }, + 'light-green': { + '50': '#f1f8e9', + '100': '#dcedc8', + '200': '#c5e1a5', + '300': '#aed581', + '400': '#9ccc65', + '500': '#8bc34a', + '600': '#7cb342', + '700': '#689f38', + '800': '#558b2f', + '900': '#33691e', + 'A100': '#ccff90', + 'A200': '#b2ff59', + 'A400': '#76ff03', + 'A700': '#64dd17', + 'contrastDefaultColor': 'dark', + 'contrastLightColors': '700 800 900', + 'contrastStrongLightColors': '700 800 900' + }, + 'lime': { + '50': '#f9fbe7', + '100': '#f0f4c3', + '200': '#e6ee9c', + '300': '#dce775', + '400': '#d4e157', + '500': '#cddc39', + '600': '#c0ca33', + '700': '#afb42b', + '800': '#9e9d24', + '900': '#827717', + 'A100': '#f4ff81', + 'A200': '#eeff41', + 'A400': '#c6ff00', + 'A700': '#aeea00', + 'contrastDefaultColor': 'dark', + 'contrastLightColors': '900', + 'contrastStrongLightColors': '900' + }, + 'yellow': { + '50': '#fffde7', + '100': '#fff9c4', + '200': '#fff59d', + '300': '#fff176', + '400': '#ffee58', + '500': '#ffeb3b', + '600': '#fdd835', + '700': '#fbc02d', + '800': '#f9a825', + '900': '#f57f17', + 'A100': '#ffff8d', + 'A200': '#ffff00', + 'A400': '#ffea00', + 'A700': '#ffd600', + 'contrastDefaultColor': 'dark' + }, + 'amber': { + '50': '#fff8e1', + '100': '#ffecb3', + '200': '#ffe082', + '300': '#ffd54f', + '400': '#ffca28', + '500': '#ffc107', + '600': '#ffb300', + '700': '#ffa000', + '800': '#ff8f00', + '900': '#ff6f00', + 'A100': '#ffe57f', + 'A200': '#ffd740', + 'A400': '#ffc400', + 'A700': '#ffab00', + 'contrastDefaultColor': 'dark' + }, + 'orange': { + '50': '#fff3e0', + '100': '#ffe0b2', + '200': '#ffcc80', + '300': '#ffb74d', + '400': '#ffa726', + '500': '#ff9800', + '600': '#fb8c00', + '700': '#f57c00', + '800': '#ef6c00', + '900': '#e65100', + 'A100': '#ffd180', + 'A200': '#ffab40', + 'A400': '#ff9100', + 'A700': '#ff6d00', + 'contrastDefaultColor': 'dark', + 'contrastLightColors': '800 900', + 'contrastStrongLightColors': '800 900' + }, + 'deep-orange': { + '50': '#fbe9e7', + '100': '#ffccbc', + '200': '#ffab91', + '300': '#ff8a65', + '400': '#ff7043', + '500': '#ff5722', + '600': '#f4511e', + '700': '#e64a19', + '800': '#d84315', + '900': '#bf360c', + 'A100': '#ff9e80', + 'A200': '#ff6e40', + 'A400': '#ff3d00', + 'A700': '#dd2c00', + 'contrastDefaultColor': 'light', + 'contrastDarkColors': '50 100 200 300 400 A100 A200', + 'contrastStrongLightColors': '500 600 700 800 900 A400 A700' + }, + 'brown': { + '50': '#efebe9', + '100': '#d7ccc8', + '200': '#bcaaa4', + '300': '#a1887f', + '400': '#8d6e63', + '500': '#795548', + '600': '#6d4c41', + '700': '#5d4037', + '800': '#4e342e', + '900': '#3e2723', + 'A100': '#d7ccc8', + 'A200': '#bcaaa4', + 'A400': '#8d6e63', + 'A700': '#5d4037', + 'contrastDefaultColor': 'light', + 'contrastDarkColors': '50 100 200 A100 A200', + 'contrastStrongLightColors': '300 400' + }, + 'grey': { + '50': '#fafafa', + '100': '#f5f5f5', + '200': '#eeeeee', + '300': '#e0e0e0', + '400': '#bdbdbd', + '500': '#9e9e9e', + '600': '#757575', + '700': '#616161', + '800': '#424242', + '900': '#212121', + 'A100': '#ffffff', + 'A200': '#000000', + 'A400': '#303030', + 'A700': '#616161', + 'contrastDefaultColor': 'dark', + 'contrastLightColors': '600 700 800 900 A200 A400 A700' + }, + 'blue-grey': { + '50': '#eceff1', + '100': '#cfd8dc', + '200': '#b0bec5', + '300': '#90a4ae', + '400': '#78909c', + '500': '#607d8b', + '600': '#546e7a', + '700': '#455a64', + '800': '#37474f', + '900': '#263238', + 'A100': '#cfd8dc', + 'A200': '#b0bec5', + 'A400': '#78909c', + 'A700': '#455a64', + 'contrastDefaultColor': 'light', + 'contrastDarkColors': '50 100 200 300 A100 A200', + 'contrastStrongLightColors': '400 500 700' + } +}); + +})(); +(function(){ +"use strict"; + +(function(angular) { + 'use strict'; +/** + * @ngdoc module + * @name material.core.theming + * @description + * Theming + */ +detectDisabledThemes.$inject = ["$mdThemingProvider"]; +ThemingDirective.$inject = ["$mdTheming", "$interpolate", "$parse", "$mdUtil", "$q", "$log"]; +ThemableDirective.$inject = ["$mdTheming"]; +ThemingProvider.$inject = ["$mdColorPalette", "$$mdMetaProvider"]; +generateAllThemes.$inject = ["$injector", "$mdTheming"]; +angular.module('material.core.theming', ['material.core.theming.palette', 'material.core.meta']) + .directive('mdTheme', ThemingDirective) + .directive('mdThemable', ThemableDirective) + .directive('mdThemesDisabled', disableThemesDirective) + .provider('$mdTheming', ThemingProvider) + .config(detectDisabledThemes) + .run(generateAllThemes); + +/** + * Detect if the HTML or the BODY tags has a [md-themes-disabled] attribute + * If yes, then immediately disable all theme stylesheet generation and DOM injection + */ +/** + * @ngInject + */ +function detectDisabledThemes($mdThemingProvider) { + var isDisabled = !!document.querySelector('[md-themes-disabled]'); + $mdThemingProvider.disableTheming(isDisabled); +} + +/** + * @ngdoc service + * @name $mdThemingProvider + * @module material.core.theming + * + * @description Provider to configure the `$mdTheming` service. + * + * ### Default Theme + * The `$mdThemingProvider` uses by default the following theme configuration: + * + * - Primary Palette: `Blue` + * - Accent Palette: `Pink` + * - Warn Palette: `Deep-Orange` + * - Background Palette: `Grey` + * + * If you don't want to use the `md-theme` directive on the elements itself, you may want to overwrite + * the default theme.
    + * This can be done by using the following markup. + * + * + * myAppModule.config(function($mdThemingProvider) { + * $mdThemingProvider + * .theme('default') + * .primaryPalette('blue') + * .accentPalette('teal') + * .warnPalette('red') + * .backgroundPalette('grey'); + * }); + * + * + + * ### Dynamic Themes + * + * By default, if you change a theme at runtime, the `$mdTheming` service will not detect those changes.
    + * If you have an application, which changes its theme on runtime, you have to enable theme watching. + * + * + * myAppModule.config(function($mdThemingProvider) { + * // Enable theme watching. + * $mdThemingProvider.alwaysWatchTheme(true); + * }); + * + * + * ### Custom Theme Styles + * + * Sometimes you may want to use your own theme styles for some custom components.
    + * You are able to register your own styles by using the following markup. + * + * + * myAppModule.config(function($mdThemingProvider) { + * // Register our custom stylesheet into the theming provider. + * $mdThemingProvider.registerStyles(STYLESHEET); + * }); + * + * + * The `registerStyles` method only accepts strings as value, so you're actually not able to load an external + * stylesheet file into the `$mdThemingProvider`. + * + * If it's necessary to load an external stylesheet, we suggest using a bundler, which supports including raw content, + * like [raw-loader](https://github.com/webpack/raw-loader) for `webpack`. + * + * + * myAppModule.config(function($mdThemingProvider) { + * // Register your custom stylesheet into the theming provider. + * $mdThemingProvider.registerStyles(require('../styles/my-component.theme.css')); + * }); + * + * + * ### Browser color + * + * Enables browser header coloring + * for more info please visit: + * https://developers.google.com/web/fundamentals/design-and-ui/browser-customization/theme-color + * + * Options parameter:
    + * `theme` - A defined theme via `$mdThemeProvider` to use the palettes from. Default is `default` theme.
    + * `palette` - Can be any one of the basic material design palettes, extended defined palettes and 'primary', + * 'accent', 'background' and 'warn'. Default is `primary`.
    + * `hue` - The hue from the selected palette. Default is `800`
    + * + * + * myAppModule.config(function($mdThemingProvider) { + * // Enable browser color + * $mdThemingProvider.enableBrowserColor({ + * theme: 'myTheme', // Default is 'default' + * palette: 'accent', // Default is 'primary', any basic material palette and extended palettes are available + * hue: '200' // Default is '800' + * }); + * }); + * + */ + +/** + * Some Example Valid Theming Expressions + * ======================================= + * + * Intention group expansion: (valid for primary, accent, warn, background) + * + * {{primary-100}} - grab shade 100 from the primary palette + * {{primary-100-0.7}} - grab shade 100, apply opacity of 0.7 + * {{primary-100-contrast}} - grab shade 100's contrast color + * {{primary-hue-1}} - grab the shade assigned to hue-1 from the primary palette + * {{primary-hue-1-0.7}} - apply 0.7 opacity to primary-hue-1 + * {{primary-color}} - Generates .md-hue-1, .md-hue-2, .md-hue-3 with configured shades set for each hue + * {{primary-color-0.7}} - Apply 0.7 opacity to each of the above rules + * {{primary-contrast}} - Generates .md-hue-1, .md-hue-2, .md-hue-3 with configured contrast (ie. text) color shades set for each hue + * {{primary-contrast-0.7}} - Apply 0.7 opacity to each of the above rules + * + * Foreground expansion: Applies rgba to black/white foreground text + * + * {{foreground-1}} - used for primary text + * {{foreground-2}} - used for secondary text/divider + * {{foreground-3}} - used for disabled text + * {{foreground-4}} - used for dividers + */ + +// In memory generated CSS rules; registered by theme.name +var GENERATED = { }; + +// In memory storage of defined themes and color palettes (both loaded by CSS, and user specified) +var PALETTES; + +// Text Colors on light and dark backgrounds +// @see https://material.io/archive/guidelines/style/color.html#color-usability +var DARK_FOREGROUND = { + name: 'dark', + '1': 'rgba(0,0,0,0.87)', + '2': 'rgba(0,0,0,0.54)', + '3': 'rgba(0,0,0,0.38)', + '4': 'rgba(0,0,0,0.12)' +}; +var LIGHT_FOREGROUND = { + name: 'light', + '1': 'rgba(255,255,255,1.0)', + '2': 'rgba(255,255,255,0.7)', + '3': 'rgba(255,255,255,0.5)', + '4': 'rgba(255,255,255,0.12)' +}; + +var DARK_SHADOW = '1px 1px 0px rgba(0,0,0,0.4), -1px -1px 0px rgba(0,0,0,0.4)'; +var LIGHT_SHADOW = ''; + +var DARK_CONTRAST_COLOR = colorToRgbaArray('rgba(0,0,0,0.87)'); +var LIGHT_CONTRAST_COLOR = colorToRgbaArray('rgba(255,255,255,0.87)'); +var STRONG_LIGHT_CONTRAST_COLOR = colorToRgbaArray('rgb(255,255,255)'); + +var THEME_COLOR_TYPES = ['primary', 'accent', 'warn', 'background']; +var DEFAULT_COLOR_TYPE = 'primary'; + +// A color in a theme will use these hues by default, if not specified by user. +var LIGHT_DEFAULT_HUES = { + 'accent': { + 'default': 'A200', + 'hue-1': 'A100', + 'hue-2': 'A400', + 'hue-3': 'A700' + }, + 'background': { + 'default': '50', + 'hue-1': 'A100', + 'hue-2': '100', + 'hue-3': '300' + } +}; + +var DARK_DEFAULT_HUES = { + 'background': { + 'default': 'A400', + 'hue-1': '800', + 'hue-2': '900', + 'hue-3': 'A200' + } +}; +THEME_COLOR_TYPES.forEach(function(colorType) { + // Color types with unspecified default hues will use these default hue values + var defaultDefaultHues = { + 'default': '500', + 'hue-1': '300', + 'hue-2': '800', + 'hue-3': 'A100' + }; + if (!LIGHT_DEFAULT_HUES[colorType]) LIGHT_DEFAULT_HUES[colorType] = defaultDefaultHues; + if (!DARK_DEFAULT_HUES[colorType]) DARK_DEFAULT_HUES[colorType] = defaultDefaultHues; +}); + +var VALID_HUE_VALUES = [ + '50', '100', '200', '300', '400', '500', '600', + '700', '800', '900', 'A100', 'A200', 'A400', 'A700' +]; + +var themeConfig = { + disableTheming : false, // Generate our themes at run time; also disable stylesheet DOM injection + generateOnDemand : false, // Whether or not themes are to be generated on-demand (vs. eagerly). + registeredStyles : [], // Custom styles registered to be used in the theming of custom components. + nonce : null // Nonce to be added as an attribute to the generated themes style tags. +}; + +/** + * + */ +function ThemingProvider($mdColorPalette, $$mdMetaProvider) { + ThemingService.$inject = ["$rootScope", "$mdUtil", "$q", "$log"]; + PALETTES = { }; + var THEMES = { }; + + var themingProvider; + + var alwaysWatchTheme = false; + var defaultTheme = 'default'; + + // Load JS Defined Palettes + angular.extend(PALETTES, $mdColorPalette); + + // Default theme defined in core.js + + /** + * Adds `theme-color` and `msapplication-navbutton-color` meta tags with the color parameter + * @param {string} color Hex value of the wanted browser color + * @returns {function} Remove function of the meta tags + */ + var setBrowserColor = function (color) { + // Chrome, Firefox OS and Opera + var removeChrome = $$mdMetaProvider.setMeta('theme-color', color); + // Windows Phone + var removeWindows = $$mdMetaProvider.setMeta('msapplication-navbutton-color', color); + + return function () { + removeChrome(); + removeWindows(); + }; + }; + + /** + * @ngdoc method + * @name $mdThemingProvider#enableBrowserColor + * @description + * Enables browser header coloring. For more info please visit + * + * Web Fundamentals. + * @param {object=} options Options for the browser color, which include:
    + * - `theme` - `{string}`: A defined theme via `$mdThemeProvider` to use the palettes from. Default is `default` theme.
    + * - `palette` - `{string}`: Can be any one of the basic material design palettes, extended defined palettes, or `primary`, + * `accent`, `background`, and `warn`. Default is `primary`.
    + * - `hue` - `{string}`: The hue from the selected palette. Default is `800`.
    + * @returns {function} Function that removes the browser coloring when called. + */ + var enableBrowserColor = function (options) { + options = angular.isObject(options) ? options : {}; + + var theme = options.theme || 'default'; + var hue = options.hue || '800'; + + var palette = PALETTES[options.palette] || + PALETTES[THEMES[theme].colors[options.palette || 'primary'].name]; + + var color = angular.isObject(palette[hue]) ? palette[hue].hex : palette[hue]; + if (color.substr(0, 1) !== '#') color = '#' + color; + + return setBrowserColor(color); + }; + + return themingProvider = { + definePalette: definePalette, + extendPalette: extendPalette, + theme: registerTheme, + + /** + * return a read-only clone of the current theme configuration + */ + configuration : function() { + return angular.extend({ }, themeConfig, { + defaultTheme : defaultTheme, + alwaysWatchTheme : alwaysWatchTheme, + registeredStyles : [].concat(themeConfig.registeredStyles) + }); + }, + + /** + * @ngdoc method + * @name $mdThemingProvider#disableTheming + * @description + * An easier way to disable theming without having to use `.constant("$MD_THEME_CSS","");`. + * This disables all dynamic theme style sheet generations and injections. + * @param {boolean=} isDisabled Disable all dynamic theme style sheet generations and injections + * if `true` or `undefined`. + */ + disableTheming: function(isDisabled) { + themeConfig.disableTheming = angular.isUndefined(isDisabled) || !!isDisabled; + }, + + /** + * @ngdoc method + * @name $mdThemingProvider#registerStyles + * @param {string} styles The styles to be appended to AngularJS Material's built in theme CSS. + */ + registerStyles: function(styles) { + themeConfig.registeredStyles.push(styles); + }, + + /** + * @ngdoc method + * @name $mdThemingProvider#setNonce + * @param {string} nonceValue The nonce to be added as an attribute to the theme style tags. + * Setting a value allows the use of CSP policy without using the unsafe-inline directive. + */ + setNonce: function(nonceValue) { + themeConfig.nonce = nonceValue; + }, + + generateThemesOnDemand: function(onDemand) { + themeConfig.generateOnDemand = onDemand; + }, + + /** + * @ngdoc method + * @name $mdThemingProvider#setDefaultTheme + * @param {string} theme Default theme name to be applied to elements. Default value is `default`. + */ + setDefaultTheme: function(theme) { + defaultTheme = theme; + }, + + /** + * @ngdoc method + * @name $mdThemingProvider#alwaysWatchTheme + * @param {boolean} alwaysWatch Whether or not to always watch themes for changes and re-apply + * classes when they change. Default is `false`. Enabling can reduce performance. + */ + alwaysWatchTheme: function(alwaysWatch) { + alwaysWatchTheme = alwaysWatch; + }, + + enableBrowserColor: enableBrowserColor, + + $get: ThemingService, + _LIGHT_DEFAULT_HUES: LIGHT_DEFAULT_HUES, + _DARK_DEFAULT_HUES: DARK_DEFAULT_HUES, + _PALETTES: PALETTES, + _THEMES: THEMES, + _parseRules: parseRules, + _rgba: rgba + }; + + /** + * @ngdoc method + * @name $mdThemingProvider#definePalette + * @description + * In the event that you need to define a custom color palette, you can use this function to + * make it available to your theme for use in its intention groups.
    + * Note that you must specify all hues in the definition map. + * @param {string} name Name of palette being defined + * @param {object} map Palette definition that includes hue definitions and contrast colors: + * - `'50'` - `{string}`: HEX color + * - `'100'` - `{string}`: HEX color + * - `'200'` - `{string}`: HEX color + * - `'300'` - `{string}`: HEX color + * - `'400'` - `{string}`: HEX color + * - `'500'` - `{string}`: HEX color + * - `'600'` - `{string}`: HEX color + * - `'700'` - `{string}`: HEX color + * - `'800'` - `{string}`: HEX color + * - `'900'` - `{string}`: HEX color + * - `'A100'` - `{string}`: HEX color + * - `'A200'` - `{string}`: HEX color + * - `'A400'` - `{string}`: HEX color + * - `'A700'` - `{string}`: HEX color + * - `'contrastDefaultColor'` - `{string}`: `light` or `dark` + * - `'contrastDarkColors'` - `{string[]}`: Hues which should use dark contrast colors (i.e. raised button text). + * For example: `['50', '100', '200', '300', '400', 'A100']`. + * - `'contrastLightColors'` - `{string[]}`: Hues which should use light contrast colors (i.e. raised button text). + * For example: `['500', '600', '700', '800', '900', 'A200', 'A400', 'A700']`. + */ + function definePalette(name, map) { + map = map || {}; + PALETTES[name] = checkPaletteValid(name, map); + return themingProvider; + } + + /** + * @ngdoc method + * @name $mdThemingProvider#extendPalette + * @description + * Sometimes it is easier to extend an existing color palette and then change a few properties, + * rather than defining a whole new palette. + * @param {string} name Name of palette being extended + * @param {object} map Palette definition that includes optional hue definitions and contrast colors: + * - `'50'` - `{string}`: HEX color + * - `'100'` - `{string}`: HEX color + * - `'200'` - `{string}`: HEX color + * - `'300'` - `{string}`: HEX color + * - `'400'` - `{string}`: HEX color + * - `'500'` - `{string}`: HEX color + * - `'600'` - `{string}`: HEX color + * - `'700'` - `{string}`: HEX color + * - `'800'` - `{string}`: HEX color + * - `'900'` - `{string}`: HEX color + * - `'A100'` - `{string}`: HEX color + * - `'A200'` - `{string}`: HEX color + * - `'A400'` - `{string}`: HEX color + * - `'A700'` - `{string}`: HEX color + * - `'contrastDefaultColor'` - `{string}`: `light` or `dark` + * - `'contrastDarkColors'` - `{string[]}`: Hues which should use dark contrast colors (i.e. raised button text). + * For example: `['50', '100', '200', '300', '400', 'A100']`. + * - `'contrastLightColors'` - `{string[]}`: Hues which should use light contrast colors (i.e. raised button text). + * For example: `['500', '600', '700', '800', '900', 'A200', 'A400', 'A700']`. + * @returns {object} A new object which is a copy of the given palette, `name`, + * with variables from `map` overwritten. + */ + function extendPalette(name, map) { + return checkPaletteValid(name, angular.extend({}, PALETTES[name] || {}, map)); + } + + // Make sure that palette has all required hues + function checkPaletteValid(name, map) { + var missingColors = VALID_HUE_VALUES.filter(function(field) { + return !map[field]; + }); + if (missingColors.length) { + throw new Error("Missing colors %1 in palette %2!" + .replace('%1', missingColors.join(', ')) + .replace('%2', name)); + } + + return map; + } + + /** + * @ngdoc method + * @name $mdThemingProvider#theme + * @description + * Register a theme (which is a collection of color palettes); i.e. `warn`, `accent`, + * `background`, and `primary`.
    + * Optionally inherit from an existing theme. + * @param {string} name Name of theme being registered + * @param {string=} inheritFrom Existing theme name to inherit from + */ + function registerTheme(name, inheritFrom) { + if (THEMES[name]) return THEMES[name]; + + inheritFrom = inheritFrom || 'default'; + + var parentTheme = typeof inheritFrom === 'string' ? THEMES[inheritFrom] : inheritFrom; + var theme = new Theme(name); + + if (parentTheme) { + angular.forEach(parentTheme.colors, function(color, colorType) { + theme.colors[colorType] = { + name: color.name, + // Make sure a COPY of the hues is given to the child color, + // not the same reference. + hues: angular.extend({}, color.hues) + }; + }); + } + THEMES[name] = theme; + + return theme; + } + + function Theme(name) { + var self = this; + self.name = name; + self.colors = {}; + + self.dark = setDark; + setDark(false); + + function setDark(isDark) { + isDark = arguments.length === 0 ? true : !!isDark; + + // If no change, abort + if (isDark === self.isDark) return; + + self.isDark = isDark; + + self.foregroundPalette = self.isDark ? LIGHT_FOREGROUND : DARK_FOREGROUND; + self.foregroundShadow = self.isDark ? DARK_SHADOW : LIGHT_SHADOW; + + // Light and dark themes have different default hues. + // Go through each existing color type for this theme, and for every + // hue value that is still the default hue value from the previous light/dark setting, + // set it to the default hue value from the new light/dark setting. + var newDefaultHues = self.isDark ? DARK_DEFAULT_HUES : LIGHT_DEFAULT_HUES; + var oldDefaultHues = self.isDark ? LIGHT_DEFAULT_HUES : DARK_DEFAULT_HUES; + angular.forEach(newDefaultHues, function(newDefaults, colorType) { + var color = self.colors[colorType]; + var oldDefaults = oldDefaultHues[colorType]; + if (color) { + for (var hueName in color.hues) { + if (color.hues[hueName] === oldDefaults[hueName]) { + color.hues[hueName] = newDefaults[hueName]; + } + } + } + }); + + return self; + } + + THEME_COLOR_TYPES.forEach(function(colorType) { + var defaultHues = (self.isDark ? DARK_DEFAULT_HUES : LIGHT_DEFAULT_HUES)[colorType]; + self[colorType + 'Palette'] = function setPaletteType(paletteName, hues) { + var color = self.colors[colorType] = { + name: paletteName, + hues: angular.extend({}, defaultHues, hues) + }; + + Object.keys(color.hues).forEach(function(name) { + if (!defaultHues[name]) { + throw new Error("Invalid hue name '%1' in theme %2's %3 color %4. Available hue names: %4" + .replace('%1', name) + .replace('%2', self.name) + .replace('%3', paletteName) + .replace('%4', Object.keys(defaultHues).join(', ')) + ); + } + }); + Object.keys(color.hues).map(function(key) { + return color.hues[key]; + }).forEach(function(hueValue) { + if (VALID_HUE_VALUES.indexOf(hueValue) == -1) { + throw new Error("Invalid hue value '%1' in theme %2's %3 color %4. Available hue values: %5" + .replace('%1', hueValue) + .replace('%2', self.name) + .replace('%3', colorType) + .replace('%4', paletteName) + .replace('%5', VALID_HUE_VALUES.join(', ')) + ); + } + }); + return self; + }; + + self[colorType + 'Color'] = function() { + var args = Array.prototype.slice.call(arguments); + // eslint-disable-next-line no-console + console.warn('$mdThemingProviderTheme.' + colorType + 'Color() has been deprecated. ' + + 'Use $mdThemingProviderTheme.' + colorType + 'Palette() instead.'); + return self[colorType + 'Palette'].apply(self, args); + }; + }); + } + + /** + * @ngdoc service + * @name $mdTheming + * @module material.core.theming + * @description + * Service that makes an element apply theming related classes to itself. + * + * For more information on the hue objects, their default values, as well as valid hue values, please visit the custom hues section of Configuring a Theme. + * + * + * // Example component directive that we want to apply theming classes to. + * app.directive('myFancyDirective', function($mdTheming) { + * return { + * restrict: 'AE', + * link: function(scope, element, attrs) { + * // Initialize the service using our directive's element + * $mdTheming(element); + * + * $mdTheming.defineTheme('myTheme', { + * primary: 'blue', + * primaryHues: { + * default: '500', + * hue-1: '300', + * hue-2: '900', + * hue-3: 'A100' + * }, + * accent: 'pink', + * accentHues: { + * default: '600', + * hue-1: '300', + * hue-2: '200', + * hue-3: 'A500' + * }, + * warn: 'red', + * // It's not necessary to specify all hues in the object. + * warnHues: { + * default: '200', + * hue-3: 'A100' + * }, + * // It's not necessary to specify custom hues at all. + * background: 'grey', + * dark: true + * }); + * // Your directive's custom code here. + * } + * }; + * }); + * + * @param {element=} element Element that will have theming classes applied to it. + */ + + /** + * @ngdoc property + * @name $mdTheming#THEMES + * @description + * Property to get all the themes defined + * @returns {object} All the themes defined with their properties. + */ + + /** + * @ngdoc property + * @name $mdTheming#PALETTES + * @description + * Property to get all the palettes defined + * @returns {object} All the palettes defined with their colors. + */ + + /** + * @ngdoc method + * @name $mdTheming#registered + * @description + * Determine is specified theme name is a valid, registered theme + * @param {string} themeName the theme to check if registered + * @returns {boolean} whether the theme is registered or not + */ + + /** + * @ngdoc method + * @name $mdTheming#defaultTheme + * @description + * Returns the default theme + * @returns {string} The default theme + */ + + /** + * @ngdoc method + * @name $mdTheming#generateTheme + * @description + * Lazy generate themes - by default, every theme is generated when defined. + * You can disable this in the configuration section using the + * `$mdThemingProvider.generateThemesOnDemand(true);` + * + * The theme name that is passed in must match the name of the theme that was defined as part of + * the configuration block. + * + * @param {string} name theme name to generate + */ + + /** + * @ngdoc method + * @name $mdTheming#setBrowserColor + * @description + * Enables browser header coloring. For more info please visit + * + * Web Fundamentals. + * @param {object=} options Options for the browser color, which include:
    + * - `theme` - `{string}`: A defined theme via `$mdThemeProvider` to use the palettes from. + * Default is `default` theme.
    + * - `palette` - `{string}`: Can be any one of the basic material design palettes, extended + * defined palettes, or `primary`, `accent`, `background`, and `warn`. Default is `primary`. + *
    + * - `hue` - `{string}`: The hue from the selected palette. Default is `800`.
    + * @returns {function} Function that removes the browser coloring when called. + */ + + /** + * @ngdoc method + * @name $mdTheming#defineTheme + * @description + * Dynamically define a theme by using an options object that contains palette names. + * + * @param {string} name Theme name to define + * @param {object} options Theme definition options + * + * Options are:
    + * - `primary` - `{string}`: The name of the primary palette to use in the theme.
    + * - `primaryHues` - `{object=}`: Override hues for primary palette.
    + * - `accent` - `{string}`: The name of the accent palette to use in the theme.
    + * - `accentHues` - `{object=}`: Override hues for accent palette.
    + * - `warn` - `{string}`: The name of the warn palette to use in the theme.
    + * - `warnHues` - `{object=}`: Override hues for warn palette.
    + * - `background` - `{string}`: The name of the background palette to use in the theme.
    + * - `backgroundHues` - `{object=}`: Override hues for background palette.
    + * - `dark` - `{boolean}`: Indicates if it's a dark theme.
    + * @returns {Promise} A resolved promise with the new theme name. + */ + + /* @ngInject */ + function ThemingService($rootScope, $mdUtil, $q, $log) { + // Allow us to be invoked via a linking function signature. + var applyTheme = function (scope, el) { + if (el === undefined) { el = scope; scope = undefined; } + if (scope === undefined) { scope = $rootScope; } + applyTheme.inherit(el, el); + }; + + Object.defineProperty(applyTheme, 'THEMES', { + get: function () { + return angular.extend({}, THEMES); + } + }); + Object.defineProperty(applyTheme, 'PALETTES', { + get: function () { + return angular.extend({}, PALETTES); + } + }); + Object.defineProperty(applyTheme, 'ALWAYS_WATCH', { + get: function () { + return alwaysWatchTheme; + } + }); + applyTheme.inherit = inheritTheme; + applyTheme.registered = registered; + applyTheme.defaultTheme = function() { return defaultTheme; }; + applyTheme.generateTheme = function(name) { generateTheme(THEMES[name], name, themeConfig.nonce); }; + applyTheme.defineTheme = function(name, options) { + options = options || {}; + + var theme = registerTheme(name); + + if (options.primary) { + theme.primaryPalette(options.primary, options.primaryHues); + } + if (options.accent) { + theme.accentPalette(options.accent, options.accentHues); + } + if (options.warn) { + theme.warnPalette(options.warn, options.warnHues); + } + if (options.background) { + theme.backgroundPalette(options.background, options.backgroundHues); + } + if (options.dark){ + theme.dark(); + } + + this.generateTheme(name); + + return $q.resolve(name); + }; + applyTheme.setBrowserColor = enableBrowserColor; + + return applyTheme; + + /** + * Determine is specified theme name is a valid, registered theme + */ + function registered(themeName) { + if (themeName === undefined || themeName === '') return true; + return applyTheme.THEMES[themeName] !== undefined; + } + + /** + * Get theme name for the element, then update with Theme CSS class + */ + function inheritTheme (el, parent) { + var ctrl = parent.controller('mdTheme') || el.data('$mdThemeController'); + var scope = el.scope(); + + updateThemeClass(lookupThemeName()); + + if (ctrl) { + var watchTheme = alwaysWatchTheme || + ctrl.$shouldWatch || + $mdUtil.parseAttributeBoolean(el.attr('md-theme-watch')); + + if (watchTheme || ctrl.isAsyncTheme) { + var clearNameWatcher = function () { + if (unwatch) { + unwatch(); + unwatch = undefined; + } + }; + + var unwatch = ctrl.registerChanges(function(name) { + updateThemeClass(name); + + if (!watchTheme) { + clearNameWatcher(); + } + }); + + if (scope) { + scope.$on('$destroy', clearNameWatcher); + } else { + el.on('$destroy', clearNameWatcher); + } + } + } + + /** + * Find the theme name from the parent controller or element data + */ + function lookupThemeName() { + // As a few components (dialog) add their controllers later, we should also watch for a controller init. + return ctrl && ctrl.$mdTheme || (defaultTheme === 'default' ? '' : defaultTheme); + } + + /** + * Remove old theme class and apply a new one + * NOTE: if not a valid theme name, then the current name is not changed + */ + function updateThemeClass(theme) { + if (!theme) return; + if (!registered(theme)) { + $log.warn('Attempted to use unregistered theme \'' + theme + '\'. ' + + 'Register it with $mdThemingProvider.theme().'); + } + + var oldTheme = el.data('$mdThemeName'); + if (oldTheme) el.removeClass('md-' + oldTheme +'-theme'); + el.addClass('md-' + theme + '-theme'); + el.data('$mdThemeName', theme); + if (ctrl) { + el.data('$mdThemeController', ctrl); + } + } + } + + } +} + +function ThemingDirective($mdTheming, $interpolate, $parse, $mdUtil, $q, $log) { + return { + priority: 101, // has to be more than 100 to be before interpolation (issue on IE) + link: { + pre: function(scope, el, attrs) { + var registeredCallbacks = []; + + var startSymbol = $interpolate.startSymbol(); + var endSymbol = $interpolate.endSymbol(); + + var theme = attrs.mdTheme.trim(); + + var hasInterpolation = + theme.substr(0, startSymbol.length) === startSymbol && + theme.lastIndexOf(endSymbol) === theme.length - endSymbol.length; + + var oneTimeOperator = '::'; + var oneTimeBind = attrs.mdTheme + .split(startSymbol).join('') + .split(endSymbol).join('') + .trim() + .substr(0, oneTimeOperator.length) === oneTimeOperator; + + var getTheme = function () { + var interpolation = $interpolate(attrs.mdTheme)(scope); + return $parse(interpolation)(scope) || interpolation; + }; + + var ctrl = { + isAsyncTheme: angular.isFunction(getTheme()) || angular.isFunction(getTheme().then), + registerChanges: function (cb, context) { + if (context) { + cb = angular.bind(context, cb); + } + + registeredCallbacks.push(cb); + + return function () { + var index = registeredCallbacks.indexOf(cb); + + if (index > -1) { + registeredCallbacks.splice(index, 1); + } + }; + }, + $setTheme: function (theme) { + if (!$mdTheming.registered(theme)) { + $log.warn('attempted to use unregistered theme \'' + theme + '\''); + } + + ctrl.$mdTheme = theme; + + // Iterating backwards to support unregistering during iteration + // http://stackoverflow.com/a/9882349/890293 + // we don't use `reverse()` of array because it mutates the array and we don't want it + // to get re-indexed + for (var i = registeredCallbacks.length; i--;) { + registeredCallbacks[i](theme); + } + }, + $shouldWatch: $mdUtil.parseAttributeBoolean(el.attr('md-theme-watch')) || + $mdTheming.ALWAYS_WATCH || + (hasInterpolation && !oneTimeBind) + }; + + el.data('$mdThemeController', ctrl); + + var setParsedTheme = function (theme) { + if (typeof theme === 'string') { + return ctrl.$setTheme(theme); + } + + $q.when(angular.isFunction(theme) ? theme() : theme) + .then(function(name) { + ctrl.$setTheme(name); + }); + }; + + setParsedTheme(getTheme()); + + var unwatch = scope.$watch(getTheme, function(theme) { + if (theme) { + setParsedTheme(theme); + + if (!ctrl.$shouldWatch) { + unwatch(); + } + } + }); + } + } + }; +} + +/** + * Special directive that will disable ALL runtime Theme style generation and DOM injection + * + * + * + * + * + * ... + * + * + * Note: Using md-themes-css directive requires the developer to load external + * theme stylesheets; e.g. custom themes from Material-Tools: + * + * `angular-material.themes.css` + * + * Another option is to use the ThemingProvider to configure and disable the attribute + * conversions; this would obviate the use of the `md-themes-css` directive + * + */ +function disableThemesDirective() { + themeConfig.disableTheming = true; + + // Return a 1x-only, first-match attribute directive + return { + restrict : 'A', + priority : '900' + }; +} + +function ThemableDirective($mdTheming) { + return $mdTheming; +} + +function parseRules(theme, colorType, rules) { + checkValidPalette(theme, colorType); + + rules = rules.replace(/THEME_NAME/g, theme.name); + var themeNameRegex = new RegExp('\\.md-' + theme.name + '-theme', 'g'); + var simpleVariableRegex = /'?"?\{\{\s*([a-zA-Z]+)-(A?\d+|hue-[0-3]|shadow|default)-?(\d\.?\d*)?(contrast)?\s*\}\}'?"?/g; + + // find and replace simple variables where we use a specific hue, not an entire palette + // eg. "{{primary-100}}" + // \(' + THEME_COLOR_TYPES.join('\|') + '\)' + rules = rules.replace(simpleVariableRegex, function(match, colorType, hue, opacity, contrast) { + if (colorType === 'foreground') { + if (hue == 'shadow') { + return theme.foregroundShadow; + } else { + return theme.foregroundPalette[hue] || theme.foregroundPalette['1']; + } + } + + // `default` is also accepted as a hue-value, because the background palettes are + // using it as a name for the default hue. + if (hue.indexOf('hue') === 0 || hue === 'default') { + hue = theme.colors[colorType].hues[hue]; + } + + return rgba((PALETTES[ theme.colors[colorType].name ][hue] || '')[contrast ? 'contrast' : 'value'], opacity); + }); + + // Matches '{{ primary-color }}', etc + var hueRegex = new RegExp('(\'|")?{{\\s*([a-zA-Z]+)-(color|contrast)-?(\\d\\.?\\d*)?\\s*}}("|\')?','g'); + var generatedRules = []; + + // For each type, generate rules for each hue (ie. default, md-hue-1, md-hue-2, md-hue-3) + angular.forEach(['default', 'hue-1', 'hue-2', 'hue-3'], function(hueName) { + var newRule = rules + .replace(hueRegex, function(match, _, matchedColorType, hueType, opacity) { + var color = theme.colors[matchedColorType]; + var palette = PALETTES[color.name]; + var hueValue = color.hues[hueName]; + return rgba(palette[hueValue][hueType === 'color' ? 'value' : 'contrast'], opacity); + }); + if (hueName !== 'default') { + newRule = newRule.replace(themeNameRegex, '.md-' + theme.name + '-theme.md-' + hueName); + } + + // Don't apply a selector rule to the default theme, making it easier to override + // styles of the base-component + if (theme.name == 'default') { + var themeRuleRegex = /((?:\s|>|\.|\w|-|:|\(|\)|\[|\]|"|'|=)*)\.md-default-theme((?:\s|>|\.|\w|-|:|\(|\)|\[|\]|"|'|=)*)/g; + + newRule = newRule.replace(themeRuleRegex, function(match, start, end) { + return match + ', ' + start + end; + }); + } + generatedRules.push(newRule); + }); + + return generatedRules; +} + +var rulesByType = {}; + +// Generate our themes at run time given the state of THEMES and PALETTES +function generateAllThemes($injector, $mdTheming) { + var head = document.head; + var firstChild = head ? head.firstElementChild : null; + var themeCss = !themeConfig.disableTheming && $injector.has('$MD_THEME_CSS') ? $injector.get('$MD_THEME_CSS') : ''; + + // Append our custom registered styles to the theme stylesheet. + themeCss += themeConfig.registeredStyles.join(''); + + if (!firstChild) return; + if (themeCss.length === 0) return; // no rules, so no point in running this expensive task + + // Expose contrast colors for palettes to ensure that text is always readable + angular.forEach(PALETTES, sanitizePalette); + + // MD_THEME_CSS is a string generated by the build process that includes all the themable + // components as templates + + // Break the CSS into individual rules + var rules = themeCss + .split(/\}(?!(\}|'|"|;))/) + .filter(function(rule) { return rule && rule.trim().length; }) + .map(function(rule) { return rule.trim() + '}'; }); + + THEME_COLOR_TYPES.forEach(function(type) { + rulesByType[type] = ''; + }); + + // Sort the rules based on type, allowing us to do color substitution on a per-type basis + rules.forEach(function(rule) { + // First: test that if the rule has '.md-accent', it goes into the accent set of rules + for (var i = 0, type; type = THEME_COLOR_TYPES[i]; i++) { + if (rule.indexOf('.md-' + type) > -1) { + return rulesByType[type] += rule; + } + } + + // If no eg 'md-accent' class is found, try to just find 'accent' in the rule and guess from + // there + for (i = 0; type = THEME_COLOR_TYPES[i]; i++) { + if (rule.indexOf(type) > -1) { + return rulesByType[type] += rule; + } + } + + // Default to the primary array + return rulesByType[DEFAULT_COLOR_TYPE] += rule; + }); + + // If themes are being generated on-demand, quit here. The user will later manually + // call generateTheme to do this on a theme-by-theme basis. + if (themeConfig.generateOnDemand) return; + + angular.forEach($mdTheming.THEMES, function(theme) { + if (!GENERATED[theme.name] && !($mdTheming.defaultTheme() !== 'default' && theme.name === 'default')) { + generateTheme(theme, theme.name, themeConfig.nonce); + } + }); + + + // ************************* + // Internal functions + // ************************* + + // The user specifies a 'default' contrast color as either light or dark, + // then explicitly lists which hues are the opposite contrast (eg. A100 has dark, A200 has light) + function sanitizePalette(palette, name) { + var defaultContrast = palette.contrastDefaultColor; + var lightColors = palette.contrastLightColors || []; + var strongLightColors = palette.contrastStrongLightColors || []; + var darkColors = palette.contrastDarkColors || []; + + // These colors are provided as space-separated lists + if (typeof lightColors === 'string') lightColors = lightColors.split(' '); + if (typeof strongLightColors === 'string') strongLightColors = strongLightColors.split(' '); + if (typeof darkColors === 'string') darkColors = darkColors.split(' '); + + // Cleanup after ourselves + delete palette.contrastDefaultColor; + delete palette.contrastLightColors; + delete palette.contrastStrongLightColors; + delete palette.contrastDarkColors; + + // Change { 'A100': '#fffeee' } to { 'A100': { value: '#fffeee', contrast:DARK_CONTRAST_COLOR } + angular.forEach(palette, function(hueValue, hueName) { + if (angular.isObject(hueValue)) return; // Already converted + // Map everything to rgb colors + var rgbValue = colorToRgbaArray(hueValue); + if (!rgbValue) { + throw new Error("Color %1, in palette %2's hue %3, is invalid. Hex or rgb(a) color expected." + .replace('%1', hueValue) + .replace('%2', palette.name) + .replace('%3', hueName)); + } + + palette[hueName] = { + hex: palette[hueName], + value: rgbValue, + contrast: getContrastColor() + }; + function getContrastColor() { + if (defaultContrast === 'light') { + if (darkColors.indexOf(hueName) > -1) { + return DARK_CONTRAST_COLOR; + } else { + return strongLightColors.indexOf(hueName) > -1 ? STRONG_LIGHT_CONTRAST_COLOR + : LIGHT_CONTRAST_COLOR; + } + } else { + if (lightColors.indexOf(hueName) > -1) { + return strongLightColors.indexOf(hueName) > -1 ? STRONG_LIGHT_CONTRAST_COLOR + : LIGHT_CONTRAST_COLOR; + } else { + return DARK_CONTRAST_COLOR; + } + } + } + }); + } +} + +function generateTheme(theme, name, nonce) { + var head = document.head; + var firstChild = head ? head.firstElementChild : null; + + if (!GENERATED[name]) { + // For each theme, use the color palettes specified for + // `primary`, `warn` and `accent` to generate CSS rules. + THEME_COLOR_TYPES.forEach(function(colorType) { + var styleStrings = parseRules(theme, colorType, rulesByType[colorType]); + while (styleStrings.length) { + var styleContent = styleStrings.shift(); + if (styleContent) { + var style = document.createElement('style'); + style.setAttribute('md-theme-style', ''); + if (nonce) { + style.setAttribute('nonce', nonce); + } + style.appendChild(document.createTextNode(styleContent)); + head.insertBefore(style, firstChild); + } + } + }); + + GENERATED[theme.name] = true; + } + +} + + +function checkValidPalette(theme, colorType) { + // If theme attempts to use a palette that doesnt exist, throw error + if (!PALETTES[ (theme.colors[colorType] || {}).name ]) { + throw new Error( + "You supplied an invalid color palette for theme %1's %2 palette. Available palettes: %3" + .replace('%1', theme.name) + .replace('%2', colorType) + .replace('%3', Object.keys(PALETTES).join(', ')) + ); + } +} + +function colorToRgbaArray(clr) { + if (angular.isArray(clr) && clr.length == 3) return clr; + if (/^rgb/.test(clr)) { + return clr.replace(/(^\s*rgba?\(|\)\s*$)/g, '').split(',').map(function(value, i) { + return i == 3 ? parseFloat(value, 10) : parseInt(value, 10); + }); + } + if (clr.charAt(0) == '#') clr = clr.substring(1); + if (!/^([a-fA-F0-9]{3}){1,2}$/g.test(clr)) return; + + var dig = clr.length / 3; + var red = clr.substr(0, dig); + var grn = clr.substr(dig, dig); + var blu = clr.substr(dig * 2); + if (dig === 1) { + red += red; + grn += grn; + blu += blu; + } + return [parseInt(red, 16), parseInt(grn, 16), parseInt(blu, 16)]; +} + +function rgba(rgbArray, opacity) { + if (!rgbArray) return "rgb('0,0,0')"; + + if (rgbArray.length == 4) { + rgbArray = angular.copy(rgbArray); + opacity ? rgbArray.pop() : opacity = rgbArray.pop(); + } + return opacity && (typeof opacity == 'number' || (typeof opacity == 'string' && opacity.length)) ? + 'rgba(' + rgbArray.join(',') + ',' + opacity + ')' : + 'rgb(' + rgbArray.join(',') + ')'; +} + + +})(window.angular); + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.autocomplete + */ +/* + * @see js folder for autocomplete implementation + */ +angular.module('material.components.autocomplete', [ + 'material.core', + 'material.components.icon', + 'material.components.virtualRepeat' +]); + +})(); +(function(){ +"use strict"; + + +MdAutocompleteCtrl.$inject = ["$scope", "$element", "$mdUtil", "$mdConstant", "$mdTheming", "$window", "$animate", "$rootElement", "$attrs", "$q", "$log", "$mdLiveAnnouncer"];angular + .module('material.components.autocomplete') + .controller('MdAutocompleteCtrl', MdAutocompleteCtrl); + +var ITEM_HEIGHT = 48, + MAX_ITEMS = 5, + MENU_PADDING = 8, + INPUT_PADDING = 2, // Padding provided by `md-input-container` + MODE_STANDARD = 'standard', + MODE_VIRTUAL = 'virtual'; + +function MdAutocompleteCtrl ($scope, $element, $mdUtil, $mdConstant, $mdTheming, $window, + $animate, $rootElement, $attrs, $q, $log, $mdLiveAnnouncer) { + + // Internal Variables. + var ctrl = this, + itemParts = $scope.itemsExpr.split(/ in /i), + itemExpr = itemParts[ 1 ], + elements = null, + cache = {}, + noBlur = false, + selectedItemWatchers = [], + hasFocus = false, + fetchesInProgress = 0, + enableWrapScroll = null, + inputModelCtrl = null, + debouncedOnResize = $mdUtil.debounce(onWindowResize), + mode = MODE_VIRTUAL; // default + + // Public Exported Variables with handlers + defineProperty('hidden', handleHiddenChange, true); + + // Public Exported Variables + ctrl.scope = $scope; + ctrl.parent = $scope.$parent; + ctrl.itemName = itemParts[ 0 ]; + ctrl.matches = []; + ctrl.loading = false; + ctrl.hidden = true; + ctrl.index = null; + ctrl.id = $mdUtil.nextUid(); + ctrl.isDisabled = null; + ctrl.isRequired = null; + ctrl.isReadonly = null; + ctrl.hasNotFound = false; + ctrl.selectedMessage = $scope.selectedMessage || 'selected'; + + // Public Exported Methods + ctrl.keydown = keydown; + ctrl.blur = blur; + ctrl.focus = focus; + ctrl.clear = clearValue; + ctrl.select = select; + ctrl.listEnter = onListEnter; + ctrl.listLeave = onListLeave; + ctrl.mouseUp = onMouseup; + ctrl.getCurrentDisplayValue = getCurrentDisplayValue; + ctrl.registerSelectedItemWatcher = registerSelectedItemWatcher; + ctrl.unregisterSelectedItemWatcher = unregisterSelectedItemWatcher; + ctrl.notFoundVisible = notFoundVisible; + ctrl.loadingIsVisible = loadingIsVisible; + ctrl.positionDropdown = positionDropdown; + + /** + * Report types to be used for the $mdLiveAnnouncer + * @enum {number} Unique flag id. + */ + var ReportType = { + Count: 1, + Selected: 2 + }; + + return init(); + + // initialization methods + + /** + * Initialize the controller, setup watchers, gather elements + */ + function init () { + + $mdUtil.initOptionalProperties($scope, $attrs, { + searchText: '', + selectedItem: null, + clearButton: false, + disableVirtualRepeat: false, + }); + + $mdTheming($element); + configureWatchers(); + $mdUtil.nextTick(function () { + + gatherElements(); + moveDropdown(); + + // Forward all focus events to the input element when autofocus is enabled + if ($scope.autofocus) { + $element.on('focus', focusInputElement); + } + if ($scope.inputAriaDescribedBy) { + elements.input.setAttribute('aria-describedby', $scope.inputAriaDescribedBy); + } + if (!$scope.floatingLabel) { + if ($scope.inputAriaLabel) { + elements.input.setAttribute('aria-label', $scope.inputAriaLabel); + } else if ($scope.inputAriaLabelledBy) { + elements.input.setAttribute('aria-labelledby', $scope.inputAriaLabelledBy); + } else if ($scope.placeholder) { + // If no aria-label or aria-labelledby references are defined, then just label using the + // placeholder. + elements.input.setAttribute('aria-label', $scope.placeholder); + } + } + }); + } + + function updateModelValidators() { + if (!$scope.requireMatch || !inputModelCtrl) return; + + inputModelCtrl.$setValidity('md-require-match', !!$scope.selectedItem || !$scope.searchText); + } + + /** + * Calculates the dropdown's position and applies the new styles to the menu element + * @returns {*} + */ + function positionDropdown () { + if (!elements) { + return $mdUtil.nextTick(positionDropdown, false, $scope); + } + + var dropdownHeight = ($scope.dropdownItems || MAX_ITEMS) * ITEM_HEIGHT; + var hrect = elements.wrap.getBoundingClientRect(), + vrect = elements.snap.getBoundingClientRect(), + root = elements.root.getBoundingClientRect(), + top = vrect.bottom - root.top, + bot = root.bottom - vrect.top, + left = hrect.left - root.left, + width = hrect.width, + offset = getVerticalOffset(), + position = $scope.dropdownPosition, + styles, enoughBottomSpace, enoughTopSpace; + var bottomSpace = root.bottom - vrect.bottom - MENU_PADDING + $mdUtil.getViewportTop(); + var topSpace = vrect.top - MENU_PADDING; + + // Automatically determine dropdown placement based on available space in viewport. + if (!position) { + enoughTopSpace = topSpace > dropdownHeight; + enoughBottomSpace = bottomSpace > dropdownHeight; + if (enoughBottomSpace) { + position = 'bottom'; + } else if (enoughTopSpace) { + position = 'top'; + } else { + position = topSpace > bottomSpace ? 'top' : 'bottom'; + } + } + // Adjust the width to account for the padding provided by `md-input-container` + if ($attrs.mdFloatingLabel) { + left += INPUT_PADDING; + width -= INPUT_PADDING * 2; + } + styles = { + left: left + 'px', + minWidth: width + 'px', + maxWidth: Math.max(hrect.right - root.left, root.right - hrect.left) - MENU_PADDING + 'px' + }; + + if (position === 'top') { + styles.top = 'auto'; + styles.bottom = bot + 'px'; + styles.maxHeight = Math.min(dropdownHeight, topSpace) + 'px'; + } else { + bottomSpace = root.bottom - hrect.bottom - MENU_PADDING + $mdUtil.getViewportTop(); + + styles.top = (top - offset) + 'px'; + styles.bottom = 'auto'; + styles.maxHeight = Math.min(dropdownHeight, bottomSpace) + 'px'; + } + + elements.$.scrollContainer.css(styles); + $mdUtil.nextTick(correctHorizontalAlignment, false, $scope); + + /** + * Calculates the vertical offset for floating label examples to account for ngMessages + * @returns {number} + */ + function getVerticalOffset () { + var offset = 0; + var inputContainer = $element.find('md-input-container'); + if (inputContainer.length) { + var input = inputContainer.find('input'); + offset = inputContainer.prop('offsetHeight'); + offset -= input.prop('offsetTop'); + offset -= input.prop('offsetHeight'); + // add in the height left up top for the floating label text + offset += inputContainer.prop('offsetTop'); + } + return offset; + } + + /** + * Makes sure that the menu doesn't go off of the screen on either side. + */ + function correctHorizontalAlignment () { + var dropdown = elements.scrollContainer.getBoundingClientRect(), + styles = {}; + if (dropdown.right > root.right) { + styles.left = (hrect.right - dropdown.width) + 'px'; + } + elements.$.scrollContainer.css(styles); + } + } + + /** + * Moves the dropdown menu to the body tag in order to avoid z-index and overflow issues. + */ + function moveDropdown () { + if (!elements.$.root.length) return; + $mdTheming(elements.$.scrollContainer); + elements.$.scrollContainer.detach(); + elements.$.root.append(elements.$.scrollContainer); + if ($animate.pin) $animate.pin(elements.$.scrollContainer, $rootElement); + } + + /** + * Sends focus to the input element. + */ + function focusInputElement () { + elements.input.focus(); + } + + /** + * Sets up any watchers used by autocomplete + */ + function configureWatchers () { + var wait = parseInt($scope.delay, 10) || 0; + + $attrs.$observe('disabled', function (value) { ctrl.isDisabled = $mdUtil.parseAttributeBoolean(value, false); }); + $attrs.$observe('required', function (value) { ctrl.isRequired = $mdUtil.parseAttributeBoolean(value, false); }); + $attrs.$observe('readonly', function (value) { ctrl.isReadonly = $mdUtil.parseAttributeBoolean(value, false); }); + + $scope.$watch('searchText', wait ? $mdUtil.debounce(handleSearchText, wait) : handleSearchText); + $scope.$watch('selectedItem', selectedItemChange); + + angular.element($window).on('resize', debouncedOnResize); + + $scope.$on('$destroy', cleanup); + } + + /** + * Removes any events or leftover elements created by this controller + */ + function cleanup () { + if (!ctrl.hidden) { + $mdUtil.enableScrolling(); + } + + angular.element($window).off('resize', debouncedOnResize); + + if (elements){ + var items = ['ul', 'scroller', 'scrollContainer', 'input']; + angular.forEach(items, function(key){ + elements.$[key].remove(); + }); + } + } + + /** + * Event handler to be called whenever the window resizes. + */ + function onWindowResize() { + if (!ctrl.hidden) { + positionDropdown(); + } + } + + /** + * Gathers all of the elements needed for this controller + */ + function gatherElements () { + + var snapWrap = gatherSnapWrap(); + + elements = { + main: $element[0], + scrollContainer: $element[0].querySelector('.md-virtual-repeat-container, .md-standard-list-container'), + scroller: $element[0].querySelector('.md-virtual-repeat-scroller, .md-standard-list-scroller'), + ul: $element.find('ul')[0], + input: $element.find('input')[0], + wrap: snapWrap.wrap, + snap: snapWrap.snap, + root: document.body, + }; + + elements.li = elements.ul.getElementsByTagName('li'); + elements.$ = getAngularElements(elements); + mode = elements.scrollContainer.classList.contains('md-standard-list-container') ? MODE_STANDARD : MODE_VIRTUAL; + inputModelCtrl = elements.$.input.controller('ngModel'); + } + + /** + * Gathers the snap and wrap elements + * + */ + function gatherSnapWrap() { + var element; + var value; + for (element = $element; element.length; element = element.parent()) { + value = element.attr('md-autocomplete-snap'); + if (angular.isDefined(value)) break; + } + + if (element.length) { + return { + snap: element[0], + wrap: (value.toLowerCase() === 'width') ? element[0] : $element.find('md-autocomplete-wrap')[0] + }; + } + + var wrap = $element.find('md-autocomplete-wrap')[0]; + return { + snap: wrap, + wrap: wrap + }; + } + + /** + * Gathers angular-wrapped versions of each element + * @param elements + * @returns {{}} + */ + function getAngularElements (elements) { + var obj = {}; + for (var key in elements) { + if (elements.hasOwnProperty(key)) obj[ key ] = angular.element(elements[ key ]); + } + return obj; + } + + // event/change handlers + + /** + * Handles changes to the `hidden` property. + * @param hidden + * @param oldHidden + */ + function handleHiddenChange (hidden, oldHidden) { + if (!hidden && oldHidden) { + positionDropdown(); + + // Report in polite mode, because the screen reader should finish the default description of + // the input element. + reportMessages(true, ReportType.Count | ReportType.Selected); + + if (elements) { + $mdUtil.disableScrollAround(elements.ul); + enableWrapScroll = disableElementScrollEvents(angular.element(elements.wrap)); + } + } else if (hidden && !oldHidden) { + $mdUtil.enableScrolling(); + + if (enableWrapScroll) { + enableWrapScroll(); + enableWrapScroll = null; + } + } + } + + /** + * Disables scrolling for a specific element + */ + function disableElementScrollEvents(element) { + + function preventDefault(e) { + e.preventDefault(); + } + + element.on('wheel', preventDefault); + element.on('touchmove', preventDefault); + + return function() { + element.off('wheel', preventDefault); + element.off('touchmove', preventDefault); + }; + } + + /** + * When the user mouses over the dropdown menu, ignore blur events. + */ + function onListEnter () { + noBlur = true; + } + + /** + * When the user's mouse leaves the menu, blur events may hide the menu again. + */ + function onListLeave () { + if (!hasFocus && !ctrl.hidden) elements.input.focus(); + noBlur = false; + ctrl.hidden = shouldHide(); + } + + /** + * When the mouse button is released, send focus back to the input field. + */ + function onMouseup () { + elements.input.focus(); + } + + /** + * Handles changes to the selected item. + * @param selectedItem + * @param previousSelectedItem + */ + function selectedItemChange (selectedItem, previousSelectedItem) { + + updateModelValidators(); + + if (selectedItem) { + getDisplayValue(selectedItem).then(function (val) { + $scope.searchText = val; + handleSelectedItemChange(selectedItem, previousSelectedItem); + }); + } else if (previousSelectedItem && $scope.searchText) { + getDisplayValue(previousSelectedItem).then(function(displayValue) { + // Clear the searchText, when the selectedItem is set to null. + // Do not clear the searchText, when the searchText isn't matching with the previous + // selected item. + if (angular.isString($scope.searchText) + && displayValue.toString().toLowerCase() === $scope.searchText.toLowerCase()) { + $scope.searchText = ''; + } + }); + } + + if (selectedItem !== previousSelectedItem) { + announceItemChange(); + } + } + + /** + * Use the user-defined expression to announce changes each time a new item is selected + */ + function announceItemChange () { + angular.isFunction($scope.itemChange) && + $scope.itemChange(getItemAsNameVal($scope.selectedItem)); + } + + /** + * Use the user-defined expression to announce changes each time the search text is changed + */ + function announceTextChange () { + angular.isFunction($scope.textChange) && $scope.textChange(); + } + + /** + * Calls any external watchers listening for the selected item. Used in conjunction with + * `registerSelectedItemWatcher`. + * @param selectedItem + * @param previousSelectedItem + */ + function handleSelectedItemChange (selectedItem, previousSelectedItem) { + selectedItemWatchers.forEach(function (watcher) { + watcher(selectedItem, previousSelectedItem); + }); + } + + /** + * Register a function to be called when the selected item changes. + * @param cb + */ + function registerSelectedItemWatcher (cb) { + if (selectedItemWatchers.indexOf(cb) === -1) { + selectedItemWatchers.push(cb); + } + } + + /** + * Unregister a function previously registered for selected item changes. + * @param cb + */ + function unregisterSelectedItemWatcher (cb) { + var i = selectedItemWatchers.indexOf(cb); + if (i !== -1) { + selectedItemWatchers.splice(i, 1); + } + } + + /** + * Handles changes to the searchText property. + * @param searchText + * @param previousSearchText + */ + function handleSearchText (searchText, previousSearchText) { + ctrl.index = getDefaultIndex(); + + // do nothing on init + if (searchText === previousSearchText) return; + + updateModelValidators(); + + getDisplayValue($scope.selectedItem).then(function (val) { + // clear selected item if search text no longer matches it + if (searchText !== val) { + $scope.selectedItem = null; + + // trigger change event if available + if (searchText !== previousSearchText) { + announceTextChange(); + } + + // cancel results if search text is not long enough + if (!isMinLengthMet()) { + ctrl.matches = []; + + setLoading(false); + reportMessages(true, ReportType.Count); + + } else { + handleQuery(); + } + } + }); + + } + + /** + * Handles input blur event, determines if the dropdown should hide. + */ + function blur($event) { + hasFocus = false; + + if (!noBlur) { + ctrl.hidden = shouldHide(); + evalAttr('ngBlur', { $event: $event }); + } + } + + /** + * Force blur on input element + * @param forceBlur + */ + function doBlur(forceBlur) { + if (forceBlur) { + noBlur = false; + hasFocus = false; + } + elements.input.blur(); + } + + /** + * Handles input focus event, determines if the dropdown should show. + */ + function focus($event) { + hasFocus = true; + + if (isSearchable() && isMinLengthMet()) { + handleQuery(); + } + + ctrl.hidden = shouldHide(); + + evalAttr('ngFocus', { $event: $event }); + } + + /** + * Handles keyboard input. + * @param event + */ + function keydown (event) { + switch (event.keyCode) { + case $mdConstant.KEY_CODE.DOWN_ARROW: + if (ctrl.loading || hasSelection()) return; + event.stopPropagation(); + event.preventDefault(); + ctrl.index = Math.min(ctrl.index + 1, ctrl.matches.length - 1); + updateScroll(); + reportMessages(false, ReportType.Selected); + break; + case $mdConstant.KEY_CODE.UP_ARROW: + if (ctrl.loading || hasSelection()) return; + event.stopPropagation(); + event.preventDefault(); + ctrl.index = ctrl.index < 0 ? ctrl.matches.length - 1 : Math.max(0, ctrl.index - 1); + updateScroll(); + reportMessages(false, ReportType.Selected); + break; + case $mdConstant.KEY_CODE.TAB: + // If we hit tab, assume that we've left the list so it will close + onListLeave(); + + if (ctrl.hidden || ctrl.loading || ctrl.index < 0 || ctrl.matches.length < 1) return; + select(ctrl.index); + break; + case $mdConstant.KEY_CODE.ENTER: + if (ctrl.hidden || ctrl.loading || ctrl.index < 0 || ctrl.matches.length < 1) return; + if (hasSelection()) return; + event.stopImmediatePropagation(); + event.preventDefault(); + select(ctrl.index); + break; + case $mdConstant.KEY_CODE.ESCAPE: + event.preventDefault(); // Prevent browser from always clearing input + if (!shouldProcessEscape()) return; + event.stopPropagation(); + + clearSelectedItem(); + if ($scope.searchText && hasEscapeOption('clear')) { + clearSearchText(); + } + + // Manually hide (needed for mdNotFound support) + ctrl.hidden = true; + + if (hasEscapeOption('blur')) { + // Force the component to blur if they hit escape + doBlur(true); + } + + break; + default: + } + } + + // getters + + /** + * Returns the minimum length needed to display the dropdown. + * @returns {*} + */ + function getMinLength () { + return angular.isNumber($scope.minLength) ? $scope.minLength : 1; + } + + /** + * Returns the display value for an item. + * @param item + * @returns {*} + */ + function getDisplayValue (item) { + return $q.when(getItemText(item) || item).then(function(itemText) { + if (itemText && !angular.isString(itemText)) { + $log.warn('md-autocomplete: Could not resolve display value to a string. ' + + 'Please check the `md-item-text` attribute.'); + } + + return itemText; + }); + + /** + * Getter function to invoke user-defined expression (in the directive) + * to convert your object to a single string. + * @param item + * @returns {string|null} + */ + function getItemText (item) { + return (item && $scope.itemText) ? $scope.itemText(getItemAsNameVal(item)) : null; + } + } + + /** + * Returns the locals object for compiling item templates. + * @param item + * @returns {Object|undefined} + */ + function getItemAsNameVal (item) { + if (!item) { + return undefined; + } + + var locals = {}; + if (ctrl.itemName) { + locals[ ctrl.itemName ] = item; + } + + return locals; + } + + /** + * Returns the default index based on whether or not autoselect is enabled. + * @returns {number} 0 if autoselect is enabled, -1 if not. + */ + function getDefaultIndex () { + return $scope.autoselect ? 0 : -1; + } + + /** + * Sets the loading parameter and updates the hidden state. + * @param value {boolean} Whether or not the component is currently loading. + */ + function setLoading(value) { + if (ctrl.loading !== value) { + ctrl.loading = value; + } + + // Always refresh the hidden variable as something else might have changed + ctrl.hidden = shouldHide(); + } + + /** + * Determines if the menu should be hidden. + * @returns {boolean} true if the menu should be hidden + */ + function shouldHide () { + return !shouldShow(); + } + + /** + * Determines whether the autocomplete is able to query within the current state. + * @returns {boolean} true if the query can be run + */ + function isSearchable() { + if (ctrl.loading && !hasMatches()) { + // No query when query is in progress. + return false; + } else if (hasSelection()) { + // No query if there is already a selection + return false; + } + else if (!hasFocus) { + // No query if the input does not have focus + return false; + } + return true; + } + + /** + * @returns {boolean} if the escape keydown should be processed, return true. + * Otherwise return false. + */ + function shouldProcessEscape() { + return hasEscapeOption('blur') || !ctrl.hidden || ctrl.loading || hasEscapeOption('clear') && $scope.searchText; + } + + /** + * @param {string} option check if this option is set + * @returns {boolean} if the specified escape option is set, return true. Return false otherwise. + */ + function hasEscapeOption(option) { + return !$scope.escapeOptions || $scope.escapeOptions.toLowerCase().indexOf(option) !== -1; + } + + /** + * Determines if the menu should be shown. + * @returns {boolean} true if the menu should be shown + */ + function shouldShow() { + if (ctrl.isReadonly) { + // Don't show if read only is set + return false; + } else if (!isSearchable()) { + // Don't show if a query is in progress, there is already a selection, + // or the input is not focused. + return false; + } + return (isMinLengthMet() && hasMatches()) || notFoundVisible(); + } + + /** + * @returns {boolean} true if the search text has matches. + */ + function hasMatches() { + return ctrl.matches.length ? true : false; + } + + /** + * @returns {boolean} true if the autocomplete has a valid selection. + */ + function hasSelection() { + return ctrl.scope.selectedItem ? true : false; + } + + /** + * @returns {boolean} true if the loading indicator is, or should be, visible. + */ + function loadingIsVisible() { + return ctrl.loading && !hasSelection(); + } + + /** + * @returns {*} the display value of the current item. + */ + function getCurrentDisplayValue () { + return getDisplayValue(ctrl.matches[ ctrl.index ]); + } + + /** + * Determines if the minimum length is met by the search text. + * @returns {*} true if the minimum length is met by the search text + */ + function isMinLengthMet () { + return ($scope.searchText || '').length >= getMinLength(); + } + + // actions + + /** + * Defines a public property with a handler and a default value. + * @param {string} key + * @param {Function} handler function + * @param {*} value default value + */ + function defineProperty (key, handler, value) { + Object.defineProperty(ctrl, key, { + get: function () { return value; }, + set: function (newValue) { + var oldValue = value; + value = newValue; + handler(newValue, oldValue); + } + }); + } + + /** + * Selects the item at the given index. + * @param {number} index to select + */ + function select (index) { + // force form to update state for validation + $mdUtil.nextTick(function () { + getDisplayValue(ctrl.matches[ index ]).then(function (val) { + var ngModel = elements.$.input.controller('ngModel'); + $mdLiveAnnouncer.announce(val + ' ' + ctrl.selectedMessage, 'assertive'); + ngModel.$setViewValue(val); + ngModel.$render(); + }).finally(function () { + $scope.selectedItem = ctrl.matches[ index ]; + setLoading(false); + }); + }, false); + } + + /** + * Clears the searchText value and selected item. + */ + function clearValue () { + clearSelectedItem(); + clearSearchText(); + } + + /** + * Clears the selected item + */ + function clearSelectedItem () { + // Reset our variables + ctrl.index = 0; + ctrl.matches = []; + } + + /** + * Clears the searchText value + */ + function clearSearchText () { + // Set the loading to true so we don't see flashes of content. + // The flashing will only occur when an async request is running. + // So the loading process will stop when the results had been retrieved. + setLoading(true); + + $scope.searchText = ''; + + // Normally, triggering the change / input event is unnecessary, because the browser detects it properly. + // But some browsers are not detecting it properly, which means that we have to trigger the event. + // Using the `input` is not working properly, because for example IE11 is not supporting the `input` event. + // The `change` event is a good alternative and is supported by all supported browsers. + var eventObj = document.createEvent('CustomEvent'); + eventObj.initCustomEvent('change', true, true, { value: '' }); + elements.input.dispatchEvent(eventObj); + + // For some reason, firing the above event resets the value of $scope.searchText if + // $scope.searchText has a space character at the end, so we blank it one more time and then + // focus. + elements.input.blur(); + $scope.searchText = ''; + elements.input.focus(); + } + + /** + * Fetches the results for the provided search text. + * @param searchText + */ + function fetchResults (searchText) { + var items = $scope.$parent.$eval(itemExpr), + term = searchText.toLowerCase(), + isList = angular.isArray(items), + isPromise = !!items.then; // Every promise should contain a `then` property + + if (isList) onResultsRetrieved(items); + else if (isPromise) handleAsyncResults(items); + + function handleAsyncResults(items) { + if (!items) return; + + items = $q.when(items); + fetchesInProgress++; + setLoading(true); + + $mdUtil.nextTick(function () { + items + .then(onResultsRetrieved) + .finally(function(){ + if (--fetchesInProgress === 0) { + setLoading(false); + } + }); + },true, $scope); + } + + function onResultsRetrieved(matches) { + cache[term] = matches; + + // Just cache the results if the request is now outdated. + // The request becomes outdated, when the new searchText has changed during the result fetching. + if ((searchText || '') !== ($scope.searchText || '')) { + return; + } + + handleResults(matches); + } + } + + + /** + * Reports given message types to supported screen readers. + * @param {boolean} isPolite Whether the announcement should be polite. + * @param {!number} types Message flags to be reported to the screen reader. + */ + function reportMessages(isPolite, types) { + var politeness = isPolite ? 'polite' : 'assertive'; + var messages = []; + + if (types & ReportType.Selected && ctrl.index !== -1) { + messages.push(getCurrentDisplayValue()); + } + + if (types & ReportType.Count) { + messages.push($q.resolve(getCountMessage())); + } + + $q.all(messages).then(function(data) { + $mdLiveAnnouncer.announce(data.join(' '), politeness); + }); + } + + /** + * @returns {string} the ARIA message for how many results match the current query. + */ + function getCountMessage () { + switch (ctrl.matches.length) { + case 0: + return 'There are no matches available.'; + case 1: + return 'There is 1 match available.'; + default: + return 'There are ' + ctrl.matches.length + ' matches available.'; + } + } + + /** + * Makes sure that the focused element is within view. + */ + function updateScroll () { + if (!elements.li[0]) return; + if (mode === MODE_STANDARD) { + updateStandardScroll(); + } else { + updateVirtualScroll(); + } + } + + function updateVirtualScroll() { + // elements in virtual scroll have consistent heights + var optionHeight = elements.li[0].offsetHeight, + top = optionHeight * ctrl.index, + bottom = top + optionHeight, + containerHeight = elements.scroller.clientHeight, + scrollTop = elements.scroller.scrollTop; + + if (top < scrollTop) { + scrollTo(top); + } else if (bottom > scrollTop + containerHeight) { + scrollTo(bottom - containerHeight); + } + } + + function updateStandardScroll() { + // elements in standard scroll have variable heights + var selected = elements.li[ctrl.index] || elements.li[0]; + var containerHeight = elements.scrollContainer.offsetHeight, + top = selected && selected.offsetTop || 0, + bottom = top + selected.clientHeight, + scrollTop = elements.scrollContainer.scrollTop; + + if (top < scrollTop) { + scrollTo(top); + } else if (bottom > scrollTop + containerHeight) { + scrollTo(bottom - containerHeight); + } + } + + function isPromiseFetching() { + return fetchesInProgress !== 0; + } + + function scrollTo (offset) { + if (mode === MODE_STANDARD) { + elements.scrollContainer.scrollTop = offset; + } else { + elements.$.scrollContainer.controller('mdVirtualRepeatContainer').scrollTo(offset); + } + } + + function notFoundVisible () { + var textLength = (ctrl.scope.searchText || '').length; + + return ctrl.hasNotFound && !hasMatches() && (!ctrl.loading || isPromiseFetching()) && textLength >= getMinLength() && (hasFocus || noBlur) && !hasSelection(); + } + + /** + * Starts the query to gather the results for the current searchText. Attempts to return cached + * results first, then forwards the process to `fetchResults` if necessary. + */ + function handleQuery () { + var searchText = $scope.searchText || ''; + var term = searchText.toLowerCase(); + + // If caching is enabled and the current searchText is stored in the cache + if (!$scope.noCache && cache[term]) { + // The results should be handled as same as a normal un-cached request does. + handleResults(cache[term]); + } else { + fetchResults(searchText); + } + + ctrl.hidden = shouldHide(); + } + + /** + * Handles the retrieved results by showing them in the autocompletes dropdown. + * @param results Retrieved results + */ + function handleResults(results) { + ctrl.matches = results; + ctrl.hidden = shouldHide(); + + // If loading is in progress, then we'll end the progress. This is needed for example, + // when the `clear` button was clicked, because there we always show the loading process, to prevent flashing. + if (ctrl.loading) setLoading(false); + + if ($scope.selectOnMatch) selectItemOnMatch(); + + positionDropdown(); + reportMessages(true, ReportType.Count); + } + + /** + * If there is only one matching item and the search text matches its display value exactly, + * automatically select that item. Note: This function is only called if the user uses the + * `md-select-on-match` flag. + */ + function selectItemOnMatch () { + var searchText = $scope.searchText, + matches = ctrl.matches, + item = matches[ 0 ]; + if (matches.length === 1) getDisplayValue(item).then(function (displayValue) { + var isMatching = searchText === displayValue; + if ($scope.matchInsensitive && !isMatching) { + isMatching = searchText.toLowerCase() === displayValue.toLowerCase(); + } + + if (isMatching) { + select(0); + } + }); + } + + /** + * Evaluates an attribute expression against the parent scope. + * @param {String} attr Name of the attribute to be evaluated. + * @param {Object?} locals Properties to be injected into the evaluation context. + */ + function evalAttr(attr, locals) { + if ($attrs[attr]) { + $scope.$parent.$eval($attrs[attr], locals || {}); + } + } + +} + +})(); +(function(){ +"use strict"; + + +MdAutocomplete.$inject = ["$$mdSvgRegistry"];angular + .module('material.components.autocomplete') + .directive('mdAutocomplete', MdAutocomplete); + +/** + * @ngdoc directive + * @name mdAutocomplete + * @module material.components.autocomplete + * + * @description + * `` is a special input component with a drop-down of all possible matches to a + * custom query. This component allows you to provide real-time suggestions as the user types + * in the input area. + * + * To start, you will need to specify the required parameters and provide a template for your + * results. The content inside `md-autocomplete` will be treated as a template. + * + * In more complex cases, you may want to include other content such as a message to display when + * no matches were found. You can do this by wrapping your template in `md-item-template` and + * adding a tag for `md-not-found`. An example of this is shown below. + * + * To reset the displayed value you must clear both values for `md-search-text` and + * `md-selected-item`. + * + * ### Validation + * + * You can use `ng-messages` to include validation the same way that you would normally validate; + * however, if you want to replicate a standard input with a floating label, you will have to + * do the following: + * + * - Make sure that your template is wrapped in `md-item-template` + * - Add your `ng-messages` code inside of `md-autocomplete` + * - Add your validation properties to `md-autocomplete` (ie. `required`) + * - Add a `name` to `md-autocomplete` (to be used on the generated `input`) + * + * There is an example below of how this should look. + * + * ### Snapping Drop-Down + * + * You can cause the autocomplete drop-down to snap to an ancestor element by applying the + * `md-autocomplete-snap` attribute to that element. You can also snap to the width of + * the `md-autocomplete-snap` element by setting the attribute's value to `width` + * (ie. `md-autocomplete-snap="width"`). + * + * ### Notes + * + * **Autocomplete Dropdown Items Rendering** + * + * The `md-autocomplete` uses the the + * mdVirtualRepeat directive for displaying the results inside of the dropdown.
    + * + * > When encountering issues regarding the item template please take a look at the + * VirtualRepeatContainer documentation. + * + * **Autocomplete inside of a Virtual Repeat** + * + * When using the `md-autocomplete` directive inside of a + * VirtualRepeatContainer the dropdown items + * might not update properly, because caching of the results is enabled by default. + * + * The autocomplete will then show invalid dropdown items, because the Virtual Repeat only updates + * the scope bindings rather than re-creating the `md-autocomplete`. This means that the previous + * cached results will be used. + * + * > To avoid such problems, ensure that the autocomplete does not cache any results via + * `md-no-cache="true"`: + * + * + * + * {{ item.display }} + * + * + * + * + * @param {expression} md-items An expression in the format of `item in results` to iterate over + * matches for your search.

    + * The `results` expression can be also a function, which returns the results synchronously + * or asynchronously (per Promise). + * @param {expression=} md-selected-item-change An expression to be run each time a new item is + * selected. + * @param {expression=} md-search-text-change An expression to be run each time the search text + * updates. + * @param {expression=} md-search-text A model to bind the search query text to. + * @param {object=} md-selected-item A model to bind the selected item to. + * @param {expression=} md-item-text An expression that will convert your object to a single string. + * @param {string=} placeholder Placeholder text that will be forwarded to the input. + * @param {boolean=} md-no-cache Disables the internal caching that happens in autocomplete. + * @param {boolean=} ng-disabled Determines whether or not to disable the input field. + * @param {boolean=} md-require-match When set to true, the autocomplete will add a validator, + * which will evaluate to false, when no item is currently selected. + * @param {number=} md-min-length Specifies the minimum length of text before autocomplete will + * make suggestions. + * @param {number=} md-delay Specifies the amount of time (in milliseconds) to wait before looking + * for results. + * @param {boolean=} md-clear-button Whether the clear button for the autocomplete input should show + * up or not. + * @param {boolean=} md-autofocus If true, the autocomplete will be automatically focused when a + * `$mdDialog`, `$mdBottomsheet` or `$mdSidenav`, which contains the autocomplete, is opening. + *

    + * Also the autocomplete will immediately focus the input element. + * @param {boolean=} md-no-asterisk When present, asterisk will not be appended to the floating + * label. + * @param {boolean=} md-autoselect If set to true, the first item will be automatically selected + * in the dropdown upon open. + * @param {string=} md-input-name The name attribute given to the input element to be used with + * FormController. + * @param {string=} md-menu-class This class will be applied to the dropdown menu for styling. + * @param {string=} md-menu-container-class This class will be applied to the parent container + * of the dropdown panel. + * @param {string=} md-input-class This will be applied to the input for styling. This attribute + * is only valid when a `md-floating-label` is defined. + * @param {string=} md-floating-label This will add a floating label to autocomplete and wrap it in + * `md-input-container`. + * @param {string=} md-select-on-focus When present the input's text will be automatically selected + * on focus. + * @param {string=} md-input-id An ID to be added to the input element. + * @param {number=} md-input-minlength The minimum length for the input's value for validation. + * @param {number=} md-input-maxlength The maximum length for the input's value for validation. + * @param {boolean=} md-select-on-match When set, autocomplete will automatically select + * the item if the search text is an exact match.

    + * An exact match is when only one match is displayed. + * @param {boolean=} md-match-case-insensitive When set and using `md-select-on-match`, autocomplete + * will select on case-insensitive match. + * @param {string=} md-escape-options Override escape key logic. Default is `blur clear`.
    + * Options: `blur`, `clear`, `none`. + * @param {string=} md-dropdown-items Specifies the maximum amount of items to be shown in + * the dropdown.

    + * When the dropdown doesn't fit into the viewport, the dropdown will shrink + * as much as possible. + * @param {string=} md-dropdown-position Overrides the default dropdown position. Options: `top`, + * `bottom`. + * @param {string=} input-aria-describedby A space-separated list of element IDs. This should + * contain the IDs of any elements that describe this autocomplete. Screen readers will read the + * content of these elements at the end of announcing that the autocomplete has been selected + * and describing its current state. The descriptive elements do not need to be visible on the + * page. + * @param {string=} input-aria-labelledby A space-separated list of element IDs. The ideal use case + * is that this would contain the ID of a `
    ' : ''; + } + + function getRepeatType(repeatMode) { + return isVirtualRepeatDisabled(repeatMode) ? + 'ng-repeat' : 'md-virtual-repeat'; + } + + function isVirtualRepeatDisabled(repeatMode) { + // ensure we have a valid repeat mode + var correctedRepeatMode = getRepeatMode(repeatMode); + return correctedRepeatMode !== REPEAT_VIRTUAL; + } + + function getInputElement () { + if (attr.mdFloatingLabel) { + return '\ + \ + \ + \ +
    ' + leftover + '
    \ +
    '; + } else { + return '\ + '; + } + } + + function getClearButton() { + return '' + + ''; + } + } + }; +} + +})(); +(function(){ +"use strict"; + + +MdAutocompleteItemScopeDirective.$inject = ["$compile", "$mdUtil"];angular + .module('material.components.autocomplete') + .directive('mdAutocompleteParentScope', MdAutocompleteItemScopeDirective); + +function MdAutocompleteItemScopeDirective($compile, $mdUtil) { + return { + restrict: 'AE', + compile: compile, + terminal: true, + transclude: 'element' + }; + + function compile(tElement, tAttr, transclude) { + return function postLink(scope, element, attr) { + var ctrl = scope.$mdAutocompleteCtrl; + var newScope = ctrl.parent.$new(); + var itemName = ctrl.itemName; + + // Watch for changes to our scope's variables and copy them to the new scope + watchVariable('$index', '$index'); + watchVariable('item', itemName); + + // Ensure that $digest calls on our scope trigger $digest on newScope. + connectScopes(); + + // Link the element against newScope. + transclude(newScope, function(clone) { + element.after(clone); + }); + + /** + * Creates a watcher for variables that are copied from the parent scope + * @param variable + * @param alias + */ + function watchVariable(variable, alias) { + newScope[alias] = scope[variable]; + + scope.$watch(variable, function(value) { + $mdUtil.nextTick(function() { + newScope[alias] = value; + }); + }); + } + + /** + * Creates watchers on scope and newScope that ensure that for any + * $digest of scope, newScope is also $digested. + */ + function connectScopes() { + var scopeDigesting = false; + var newScopeDigesting = false; + + scope.$watch(function() { + if (newScopeDigesting || scopeDigesting) { + return; + } + + scopeDigesting = true; + scope.$$postDigest(function() { + if (!newScopeDigesting) { + newScope.$digest(); + } + + scopeDigesting = newScopeDigesting = false; + }); + }); + + newScope.$watch(function() { + newScopeDigesting = true; + }); + } + }; + } +} +})(); +(function(){ +"use strict"; + + +MdHighlightCtrl.$inject = ["$scope", "$element", "$attrs"];angular + .module('material.components.autocomplete') + .controller('MdHighlightCtrl', MdHighlightCtrl); + +function MdHighlightCtrl ($scope, $element, $attrs) { + this.$scope = $scope; + this.$element = $element; + this.$attrs = $attrs; + + // Cache the Regex to avoid rebuilding each time. + this.regex = null; +} + +MdHighlightCtrl.prototype.init = function(unsafeTermFn, unsafeContentFn) { + + this.flags = this.$attrs.mdHighlightFlags || ''; + + this.unregisterFn = this.$scope.$watch(function($scope) { + return { + term: unsafeTermFn($scope), + contentText: unsafeContentFn($scope) + }; + }.bind(this), this.onRender.bind(this), true); + + this.$element.on('$destroy', this.unregisterFn); +}; + +/** + * Triggered once a new change has been recognized and the highlighted + * text needs to be updated. + */ +MdHighlightCtrl.prototype.onRender = function(state, prevState) { + + var contentText = state.contentText; + + /* Update the regex if it's outdated, because we don't want to rebuilt it constantly. */ + if (this.regex === null || state.term !== prevState.term) { + this.regex = this.createRegex(state.term, this.flags); + } + + /* If a term is available apply the regex to the content */ + if (state.term) { + this.applyRegex(contentText); + } else { + this.$element.text(contentText); + } + +}; + +/** + * Decomposes the specified text into different tokens (whether match or not). + * Breaking down the string guarantees proper XSS protection due to the native browser + * escaping of unsafe text. + */ +MdHighlightCtrl.prototype.applyRegex = function(text) { + var tokens = this.resolveTokens(text); + + this.$element.empty(); + + tokens.forEach(function (token) { + + if (token.isMatch) { + var tokenEl = angular.element('').text(token.text); + + this.$element.append(tokenEl); + } else { + this.$element.append(document.createTextNode(token)); + } + + }.bind(this)); + +}; + + /** + * Decomposes the specified text into different tokens by running the regex against the text. + */ +MdHighlightCtrl.prototype.resolveTokens = function(string) { + var tokens = []; + var lastIndex = 0; + + // Use replace here, because it supports global and single regular expressions at same time. + string.replace(this.regex, function(match, index) { + appendToken(lastIndex, index); + + tokens.push({ + text: match, + isMatch: true + }); + + lastIndex = index + match.length; + }); + + // Append the missing text as a token. + appendToken(lastIndex); + + return tokens; + + function appendToken(from, to) { + var targetText = string.slice(from, to); + targetText && tokens.push(targetText); + } +}; + +/** Creates a regex for the specified text with the given flags. */ +MdHighlightCtrl.prototype.createRegex = function(term, flags) { + var startFlag = '', endFlag = ''; + var regexTerm = this.sanitizeRegex(term); + + if (flags.indexOf('^') >= 0) startFlag = '^'; + if (flags.indexOf('$') >= 0) endFlag = '$'; + + return new RegExp(startFlag + regexTerm + endFlag, flags.replace(/[$^]/g, '')); +}; + +/** Sanitizes a regex by removing all common RegExp identifiers */ +MdHighlightCtrl.prototype.sanitizeRegex = function(term) { + return term && term.toString().replace(/[\\^$*+?.()|{}[\]]/g, '\\$&'); +}; + +})(); +(function(){ +"use strict"; + + +MdHighlight.$inject = ["$interpolate", "$parse"];angular + .module('material.components.autocomplete') + .directive('mdHighlightText', MdHighlight); + +/** + * @ngdoc directive + * @name mdHighlightText + * @module material.components.autocomplete + * + * @description + * The `md-highlight-text` directive allows you to specify text that should be highlighted within + * an element. Highlighted text will be wrapped in `` which can + * be styled through CSS. Please note that child elements may not be used with this directive. + * + * @param {string} md-highlight-text A model to be searched for + * @param {string=} md-highlight-flags A list of flags (loosely based on JavaScript RexExp flags). + * #### **Supported flags**: + * - `g`: Find all matches within the provided text + * - `i`: Ignore case when searching for matches + * - `$`: Only match if the text ends with the search term + * - `^`: Only match if the text begins with the search term + * + * @usage + * + * + *
      + *
    • + * {{result.text}} + *
    • + *
    + *
    + */ + +function MdHighlight ($interpolate, $parse) { + return { + terminal: true, + controller: 'MdHighlightCtrl', + compile: function mdHighlightCompile(tElement, tAttr) { + var termExpr = $parse(tAttr.mdHighlightText); + var unsafeContentExpr = $interpolate(tElement.html()); + + return function mdHighlightLink(scope, element, attr, ctrl) { + ctrl.init(termExpr, unsafeContentExpr); + }; + } + }; +} + +})(); +(function(){ +"use strict"; + +/* + * @ngdoc module + * @name material.components.backdrop + * @description Backdrop + */ + +/** + * @ngdoc directive + * @name mdBackdrop + * @module material.components.backdrop + * + * @restrict E + * + * @description + * `` is a backdrop element used by other components, such as dialog and bottom sheet. + * Apply class `opaque` to make the backdrop use the theme backdrop color. + * + */ + +angular + .module('material.components.backdrop', ['material.core']) + .directive('mdBackdrop', ["$mdTheming", "$mdUtil", "$animate", "$rootElement", "$window", "$log", "$$rAF", "$document", function BackdropDirective($mdTheming, $mdUtil, $animate, $rootElement, $window, $log, $$rAF, $document) { + var ERROR_CSS_POSITION = ' may not work properly in a scrolled, static-positioned parent container.'; + + return { + restrict: 'E', + link: postLink + }; + + function postLink(scope, element, attrs) { + // backdrop may be outside the $rootElement, tell ngAnimate to animate regardless + if ($animate.pin) $animate.pin(element, $rootElement); + + var bodyStyles; + + $$rAF(function() { + // If body scrolling has been disabled using mdUtil.disableBodyScroll(), + // adjust the 'backdrop' height to account for the fixed 'body' top offset. + // Note that this can be pretty expensive and is better done inside the $$rAF. + bodyStyles = $window.getComputedStyle($document[0].body); + + if (bodyStyles.position === 'fixed') { + var resizeHandler = $mdUtil.debounce(function(){ + bodyStyles = $window.getComputedStyle($document[0].body); + resize(); + }, 60, null, false); + + resize(); + angular.element($window).on('resize', resizeHandler); + + scope.$on('$destroy', function() { + angular.element($window).off('resize', resizeHandler); + }); + } + + // Often $animate.enter() is used to append the backDrop element + // so let's wait until $animate is done... + var parent = element.parent(); + + if (parent.length) { + if (parent[0].nodeName === 'BODY') { + element.css('position', 'fixed'); + } + + var styles = $window.getComputedStyle(parent[0]); + + if (styles.position === 'static') { + // backdrop uses position:absolute and will not work properly with parent position:static (default) + $log.warn(ERROR_CSS_POSITION); + } + + // Only inherit the parent if the backdrop has a parent. + $mdTheming.inherit(element, parent); + } + }); + + function resize() { + var viewportHeight = parseInt(bodyStyles.height, 10) + Math.abs(parseInt(bodyStyles.top, 10)); + element.css('height', viewportHeight + 'px'); + } + } + + }]); + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.bottomSheet + * @description + * BottomSheet + */ +MdBottomSheetDirective.$inject = ["$mdBottomSheet"]; +MdBottomSheetProvider.$inject = ["$$interimElementProvider"]; +angular + .module('material.components.bottomSheet', [ + 'material.core', + 'material.components.backdrop' + ]) + .directive('mdBottomSheet', MdBottomSheetDirective) + .provider('$mdBottomSheet', MdBottomSheetProvider); + +/* @ngInject */ +function MdBottomSheetDirective($mdBottomSheet) { + return { + restrict: 'E', + link : function postLink(scope, element) { + element.addClass('_md'); // private md component indicator for styling + + // When navigation force destroys an interimElement, then + // listen and $destroy() that interim instance... + scope.$on('$destroy', function() { + $mdBottomSheet.destroy(); + }); + } + }; +} + + +/** + * @ngdoc service + * @name $mdBottomSheet + * @module material.components.bottomSheet + * + * @description + * `$mdBottomSheet` opens a bottom sheet over the app and provides a simple promise API. + * + * ## Restrictions + * + * - The bottom sheet's template must have an outer `` element. + * - Add the `md-grid` class to the bottom sheet for a grid layout. + * - Add the `md-list` class to the bottom sheet for a list layout. + * + * @usage + * + *
    + * + * Open a Bottom Sheet! + * + *
    + *
    + * + * var app = angular.module('app', ['ngMaterial']); + * app.controller('MyController', function($scope, $mdBottomSheet) { + * $scope.openBottomSheet = function() { + * $mdBottomSheet.show({ + * template: '' + + * 'Hello! Close' + + * '' + * }) + * + * // Fires when the hide() method is used + * .then(function() { + * console.log('You clicked the button to close the bottom sheet!'); + * }) + * + * // Fires when the cancel() method is used + * .catch(function() { + * console.log('You hit escape or clicked the backdrop to close.'); + * }); + * }; + * + * $scope.closeBottomSheet = function($scope, $mdBottomSheet) { + * $mdBottomSheet.hide(); + * } + * + * }); + * + * + * ### Custom Presets + * Developers are also able to create their own preset, which can be easily used without repeating + * their options each time. + * + * + * $mdBottomSheetProvider.addPreset('testPreset', { + * options: function() { + * return { + * template: + * '' + + * 'This is a custom preset' + + * '', + * controllerAs: 'bottomSheet', + * bindToController: true, + * clickOutsideToClose: true, + * escapeToClose: true + * }; + * } + * }); + * + * + * After you create your preset during the config phase, you can easily access it. + * + * + * $mdBottomSheet.show( + * $mdBottomSheet.testPreset() + * ); + * + */ + + /** + * @ngdoc method + * @name $mdBottomSheet#show + * + * @description + * Show a bottom sheet with the specified options. + * + * Note: You should always provide a `.catch()` method in case the user hits the + * `esc` key or clicks the background to close. In this case, the `cancel()` method will + * automatically be called on the bottom sheet which will `reject()` the promise. See the @usage + * section above for an example. + * + * Newer versions of Angular will throw a `Possibly unhandled rejection` exception if you forget + * this. + * + * @param {object} optionsOrPreset Either provide an `$mdBottomSheetPreset` defined during the config phase or + * an options object, with the following properties: + * + * - `templateUrl` - `{string=}`: The url of an html template file that will + * be used as the content of the bottom sheet. Restrictions: the template must + * have an outer `md-bottom-sheet` element. + * - `template` - `{string=}`: Same as templateUrl, except this is an actual + * template string. + * - `scope` - `{object=}`: the scope to link the template / controller to. If none is specified, it will create a new child scope. + * This scope will be destroyed when the bottom sheet is removed unless `preserveScope` is set to true. + * - `preserveScope` - `{boolean=}`: whether to preserve the scope when the element is removed. Default is false + * - `controller` - `{string=}`: The controller to associate with this bottom sheet. + * - `locals` - `{string=}`: An object containing key/value pairs. The keys will + * be used as names of values to inject into the controller. For example, + * `locals: {three: 3}` would inject `three` into the controller with the value + * of 3. + * - `clickOutsideToClose` - `{boolean=}`: Whether the user can click outside the bottom sheet to + * close it. Default true. + * - `bindToController` - `{boolean=}`: When set to true, the locals will be bound to the controller instance. + * - `disableBackdrop` - `{boolean=}`: When set to true, the bottomsheet will not show a backdrop. + * - `escapeToClose` - `{boolean=}`: Whether the user can press escape to close the bottom sheet. + * Default true. + * - `isLockedOpen` - `{boolean=}`: Disables all default ways of closing the bottom sheet. **Note:** this will override + * the `clickOutsideToClose` and `escapeToClose` options, leaving only the `hide` and `cancel` + * methods as ways of closing the bottom sheet. Defaults to false. + * - `resolve` - `{object=}`: Similar to locals, except it takes promises as values + * and the bottom sheet will not open until the promises resolve. + * - `controllerAs` - `{string=}`: An alias to assign the controller to on the scope. + * - `parent` - `{element=}`: The element to append the bottom sheet to. The `parent` may be a `function`, `string`, + * `object`, or null. Defaults to appending to the body of the root element (or the root element) of the application. + * e.g. angular.element(document.getElementById('content')) or "#content" + * - `disableParentScroll` - `{boolean=}`: Whether to disable scrolling while the bottom sheet is open. + * Default true. + * + * @returns {promise} A promise that can be resolved with `$mdBottomSheet.hide()` or + * rejected with `$mdBottomSheet.cancel()`. + */ + +/** + * @ngdoc method + * @name $mdBottomSheet#hide + * + * @description + * Hide the existing bottom sheet and resolve the promise returned from + * `$mdBottomSheet.show()`. This call will close the most recently opened/current bottomsheet (if + * any). + * + * Note: Use a `.then()` on your `.show()` to handle this callback. + * + * @param {*=} response An argument for the resolved promise. + * + */ + +/** + * @ngdoc method + * @name $mdBottomSheet#cancel + * + * @description + * Hide the existing bottom sheet and reject the promise returned from + * `$mdBottomSheet.show()`. + * + * Note: Use a `.catch()` on your `.show()` to handle this callback. + * + * @param {*=} response An argument for the rejected promise. + * + */ + +function MdBottomSheetProvider($$interimElementProvider) { + // how fast we need to flick down to close the sheet, pixels/ms + bottomSheetDefaults.$inject = ["$animate", "$mdConstant", "$mdUtil", "$mdTheming", "$mdBottomSheet", "$rootElement", "$mdGesture", "$log"]; + var CLOSING_VELOCITY = 0.5; + var PADDING = 80; // same as css + + return $$interimElementProvider('$mdBottomSheet') + .setDefaults({ + methods: ['disableParentScroll', 'escapeToClose', 'clickOutsideToClose'], + options: bottomSheetDefaults + }); + + /* @ngInject */ + function bottomSheetDefaults($animate, $mdConstant, $mdUtil, $mdTheming, $mdBottomSheet, $rootElement, + $mdGesture, $log) { + var backdrop; + + return { + themable: true, + onShow: onShow, + onRemove: onRemove, + disableBackdrop: false, + escapeToClose: true, + clickOutsideToClose: true, + disableParentScroll: true, + isLockedOpen: false + }; + + + function onShow(scope, element, options, controller) { + + element = $mdUtil.extractElementByName(element, 'md-bottom-sheet'); + + // prevent tab focus or click focus on the bottom-sheet container + element.attr('tabindex', '-1'); + + // Once the md-bottom-sheet has `ng-cloak` applied on his template the opening animation will not work properly. + // This is a very common problem, so we have to notify the developer about this. + if (element.hasClass('ng-cloak')) { + var message = '$mdBottomSheet: using `` will affect the bottom-sheet opening animations.'; + $log.warn(message, element[0]); + } + + if (options.isLockedOpen) { + options.clickOutsideToClose = false; + options.escapeToClose = false; + } else { + options.cleanupGestures = registerGestures(element, options.parent); + } + + if (!options.disableBackdrop) { + // Add a backdrop that will close on click + backdrop = $mdUtil.createBackdrop(scope, "md-bottom-sheet-backdrop md-opaque"); + + // Prevent mouse focus on backdrop; ONLY programatic focus allowed. + // This allows clicks on backdrop to propogate to the $rootElement and + // ESC key events to be detected properly. + backdrop[0].tabIndex = -1; + + if (options.clickOutsideToClose) { + backdrop.on('click', function() { + $mdUtil.nextTick($mdBottomSheet.cancel,true); + }); + } + + $mdTheming.inherit(backdrop, options.parent); + + $animate.enter(backdrop, options.parent, null); + } + + $mdTheming.inherit(element, options.parent); + + if (options.disableParentScroll) { + options.restoreScroll = $mdUtil.disableScrollAround(element, options.parent); + } + + return $animate.enter(element, options.parent, backdrop) + .then(function() { + var focusable = $mdUtil.findFocusTarget(element) || angular.element( + element[0].querySelector('button') || + element[0].querySelector('a') || + element[0].querySelector($mdUtil.prefixer('ng-click', true)) + ) || backdrop; + + if (options.escapeToClose) { + options.rootElementKeyupCallback = function(e) { + if (e.keyCode === $mdConstant.KEY_CODE.ESCAPE) { + $mdUtil.nextTick($mdBottomSheet.cancel,true); + } + }; + + $rootElement.on('keyup', options.rootElementKeyupCallback); + focusable && focusable.focus(); + } + }); + + } + + function onRemove(scope, element, options) { + if (!options.disableBackdrop) $animate.leave(backdrop); + + return $animate.leave(element).then(function() { + if (options.disableParentScroll) { + options.restoreScroll(); + delete options.restoreScroll; + } + + options.cleanupGestures && options.cleanupGestures(); + }); + } + + /** + * Adds the drag gestures to the bottom sheet. + */ + function registerGestures(element, parent) { + var deregister = $mdGesture.register(parent, 'drag', { horizontal: false }); + parent.on('$md.dragstart', onDragStart) + .on('$md.drag', onDrag) + .on('$md.dragend', onDragEnd); + + return function cleanupGestures() { + deregister(); + parent.off('$md.dragstart', onDragStart); + parent.off('$md.drag', onDrag); + parent.off('$md.dragend', onDragEnd); + }; + + function onDragStart() { + // Disable transitions on transform so that it feels fast + element.css($mdConstant.CSS.TRANSITION_DURATION, '0ms'); + } + + function onDrag(ev) { + var transform = ev.pointer.distanceY; + if (transform < 5) { + // Slow down drag when trying to drag up, and stop after PADDING + transform = Math.max(-PADDING, transform / 2); + } + element.css($mdConstant.CSS.TRANSFORM, 'translate3d(0,' + (PADDING + transform) + 'px,0)'); + } + + function onDragEnd(ev) { + if (ev.pointer.distanceY > 0 && + (ev.pointer.distanceY > 20 || Math.abs(ev.pointer.velocityY) > CLOSING_VELOCITY)) { + var distanceRemaining = element.prop('offsetHeight') - ev.pointer.distanceY; + var transitionDuration = Math.min(distanceRemaining / ev.pointer.velocityY * 0.75, 500); + element.css($mdConstant.CSS.TRANSITION_DURATION, transitionDuration + 'ms'); + $mdUtil.nextTick($mdBottomSheet.cancel,true); + } else { + element.css($mdConstant.CSS.TRANSITION_DURATION, ''); + element.css($mdConstant.CSS.TRANSFORM, ''); + } + } + } + + } + +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.button + * @description + * + * Button + */ +MdButtonDirective.$inject = ["$mdButtonInkRipple", "$mdTheming", "$mdAria", "$mdInteraction"]; +MdAnchorDirective.$inject = ["$mdTheming"]; +angular + .module('material.components.button', ['material.core']) + .directive('mdButton', MdButtonDirective) + .directive('a', MdAnchorDirective); + + +/** + * @private + * @restrict E + * + * @description + * `a` is an anchor directive used to inherit theme colors for md-primary, md-accent, etc. + * + * @usage + * + * + * + * + * + * + */ +function MdAnchorDirective($mdTheming) { + return { + restrict : 'E', + link : function postLink(scope, element) { + // Make sure to inherit theme so stand-alone anchors + // support theme colors for md-primary, md-accent, etc. + $mdTheming(element); + } + }; +} + + +/** + * @ngdoc directive + * @name mdButton + * @module material.components.button + * + * @restrict E + * + * @description + * `` is a button directive with optional ink ripples (default enabled). + * + * If you supply a `href` or `ng-href` attribute, it will become an `` element. Otherwise, it + * will become a `'; + } + } + + function postLink(scope, element, attr) { + $mdTheming(element); + $mdButtonInkRipple.attach(scope, element); + + // Use async expect to support possible bindings in the button label + $mdAria.expectWithoutText(element, 'aria-label'); + + // For anchor elements, we have to set tabindex manually when the element is disabled. + // We don't do this for md-nav-bar anchors as the component manages its own tabindex values. + if (isAnchor(attr) && angular.isDefined(attr.ngDisabled) && + !element.hasClass('_md-nav-button')) { + scope.$watch(attr.ngDisabled, function(isDisabled) { + element.attr('tabindex', isDisabled ? -1 : 0); + }); + } + + // disabling click event when disabled is true + element.on('click', function(e){ + if (attr.disabled === true) { + e.preventDefault(); + e.stopImmediatePropagation(); + } + }); + + if (!element.hasClass('md-no-focus')) { + + element.on('focus', function() { + + // Only show the focus effect when being focused through keyboard interaction or programmatically + if (!$mdInteraction.isUserInvoked() || $mdInteraction.getLastInteractionType() === 'keyboard') { + element.addClass('md-focused'); + } + + }); + + element.on('blur', function() { + element.removeClass('md-focused'); + }); + } + + } + +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.card + * + * @description + * Card components. + */ +mdCardDirective.$inject = ["$mdTheming"]; +angular.module('material.components.card', [ + 'material.core' + ]) + .directive('mdCard', mdCardDirective); + + +/** + * @ngdoc directive + * @name mdCard + * @module material.components.card + * + * @restrict E + * + * @description + * The `` directive is a container element used within `` containers. + * + * An image included as a direct descendant will fill the card's width. If you want to avoid this, + * you can add the `md-image-no-fill` class to the parent element. The `` + * container will wrap text content and provide padding. An `` element can be + * optionally included to put content flush against the bottom edge of the card. + * + * Action buttons can be included in an `` element, similar to ``. + * You can then position buttons using layout attributes. + * + * Card is built with: + * * `` - Header for the card, holds avatar, text and squared image + * - `` - Card avatar + * - `md-user-avatar` - Class for user image + * - `` + * - `` - Contains elements for the card description + * - `md-title` - Class for the card title + * - `md-subhead` - Class for the card sub header + * * `` - Image for the card + * * `` - Card content title + * - `` + * - `md-headline` - Class for the card content title + * - `md-subhead` - Class for the card content sub header + * - `` - Squared image within the title + * - `md-media-sm` - Class for small image + * - `md-media-md` - Class for medium image + * - `md-media-lg` - Class for large image + * - `md-media-xl` - Class for extra large image + * * `` - Card content + * * `` - Card actions + * - `` - Icon actions + * + * Cards have constant width and variable heights; where the maximum height is limited to what can + * fit within a single view on a platform, but it can temporarily expand as needed. + * + * @usage + * ### Card with optional footer + * + * + * image caption + * + *

    Card headline

    + *

    Card content

    + *
    + * + * Card footer + * + *
    + *
    + * + * ### Card with actions + * + * + * image caption + * + *

    Card headline

    + *

    Card content

    + *
    + * + * Action 1 + * Action 2 + * + *
    + *
    + * + * ### Card with header, image, title actions and content + * + * + * + * + * + * + * + * Title + * Sub header + * + * + * image caption + * + * + * Card headline + * Card subheader + * + * + * + * Action 1 + * Action 2 + * + * + * + * + * + * + * + *

    + * Card content + *

    + *
    + *
    + *
    + */ +function mdCardDirective($mdTheming) { + return { + restrict: 'E', + link: function ($scope, $element, attr) { + $element.addClass('_md'); // private md component indicator for styling + $mdTheming($element); + } + }; +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.checkbox + * @description Checkbox module! + */ +MdCheckboxDirective.$inject = ["inputDirective", "$mdAria", "$mdConstant", "$mdTheming", "$mdUtil", "$mdInteraction"]; +angular + .module('material.components.checkbox', ['material.core']) + .directive('mdCheckbox', MdCheckboxDirective); + +/** + * @ngdoc directive + * @name mdCheckbox + * @module material.components.checkbox + * @restrict E + * + * @description + * The checkbox directive is used like the normal + * [angular checkbox](https://docs.angularjs.org/api/ng/input/input%5Bcheckbox%5D). + * + * As per the [Material Design spec](https://material.io/archive/guidelines/style/color.html#color-color-palette) + * the checkbox is in the accent color by default. The primary color palette may be used with + * the `md-primary` class. + * + * @param {expression} ng-model Assignable angular expression to data-bind to. + * @param {string=} name Property name of the form under which the control is published. + * @param {expression=} ng-true-value The value to which the expression should be set when selected. + * @param {expression=} ng-false-value The value to which the expression should be set when not + * selected. + * @param {expression=} ng-change Expression to be executed when the model value changes. + * @param {boolean=} md-no-ink If present, disable ink ripple effects. + * @param {string=} aria-label Adds label to checkbox for accessibility. + * Defaults to checkbox's text. If no default text is found, a warning will be logged. + * @param {expression=} md-indeterminate This determines when the checkbox should be rendered as + * 'indeterminate'. If a truthy expression or no value is passed in the checkbox renders in the + * md-indeterminate state. If falsy expression is passed in it just looks like a normal unchecked + * checkbox. The indeterminate, checked, and unchecked states are mutually exclusive. A box + * cannot be in any two states at the same time. Adding the 'md-indeterminate' attribute + * overrides any checked/unchecked rendering logic. When using the 'md-indeterminate' attribute + * use 'ng-checked' to define rendering logic instead of using 'ng-model'. + * @param {expression=} ng-checked If this expression evaluates as truthy, the 'md-checked' css + * class is added to the checkbox and it will appear checked. + * + * @usage + * + * + * Finished ? + * + * + * + * No Ink Effects + * + * + * + * Disabled + * + * + * + * + */ +function MdCheckboxDirective(inputDirective, $mdAria, $mdConstant, $mdTheming, $mdUtil, $mdInteraction) { + inputDirective = inputDirective[0]; + + return { + restrict: 'E', + transclude: true, + require: ['^?mdInputContainer', '?ngModel', '?^form'], + priority: $mdConstant.BEFORE_NG_ARIA, + template: + '
    ' + + '
    ' + + '
    ' + + '
    ', + compile: compile + }; + + // ********************************************************** + // Private Methods + // ********************************************************** + + function compile (tElement, tAttrs) { + tAttrs.$set('tabindex', tAttrs.tabindex || '0'); + tAttrs.$set('type', 'checkbox'); + tAttrs.$set('role', tAttrs.type); + + return { + pre: function(scope, element) { + // Attach a click handler during preLink, in order to immediately stop propagation + // (especially for ng-click) when the checkbox is disabled. + element.on('click', function(e) { + if (this.hasAttribute('disabled')) { + e.stopImmediatePropagation(); + } + }); + }, + post: postLink + }; + + function postLink(scope, element, attr, ctrls) { + var isIndeterminate; + var containerCtrl = ctrls[0]; + var ngModelCtrl = ctrls[1] || $mdUtil.fakeNgModel(); + var formCtrl = ctrls[2]; + + if (containerCtrl) { + var isErrorGetter = containerCtrl.isErrorGetter || function() { + return ngModelCtrl.$invalid && (ngModelCtrl.$touched || (formCtrl && formCtrl.$submitted)); + }; + + containerCtrl.input = element; + + scope.$watch(isErrorGetter, containerCtrl.setInvalid); + } + + $mdTheming(element); + + // Redirect focus events to the root element, because IE11 is always focusing the container element instead + // of the md-checkbox element. This causes issues when using ngModelOptions: `updateOnBlur` + element.children().on('focus', function() { + element.focus(); + }); + + if ($mdUtil.parseAttributeBoolean(attr.mdIndeterminate)) { + setIndeterminateState(); + scope.$watch(attr.mdIndeterminate, setIndeterminateState); + } + + if (attr.ngChecked) { + scope.$watch(scope.$eval.bind(scope, attr.ngChecked), function(value) { + ngModelCtrl.$setViewValue(value); + ngModelCtrl.$render(); + }); + } + + $$watchExpr('ngDisabled', 'tabindex', { + true: '-1', + false: attr.tabindex + }); + + $mdAria.expectWithText(element, 'aria-label'); + + // Reuse the original input[type=checkbox] directive from AngularJS core. + // This is a bit hacky as we need our own event listener and own render + // function. + inputDirective.link.pre(scope, { + on: angular.noop, + 0: {} + }, attr, [ngModelCtrl]); + + element.on('click', listener) + .on('keypress', keypressHandler) + .on('focus', function() { + if ($mdInteraction.getLastInteractionType() === 'keyboard') { + element.addClass('md-focused'); + } + }) + .on('blur', function() { + element.removeClass('md-focused'); + }); + + ngModelCtrl.$render = render; + + function $$watchExpr(expr, htmlAttr, valueOpts) { + if (attr[expr]) { + scope.$watch(attr[expr], function(val) { + if (valueOpts[val]) { + element.attr(htmlAttr, valueOpts[val]); + } + }); + } + } + + /** + * @param {KeyboardEvent} ev 'keypress' event to handle + */ + function keypressHandler(ev) { + var keyCode = ev.which || ev.keyCode; + var submit, form; + + ev.preventDefault(); + switch (keyCode) { + case $mdConstant.KEY_CODE.SPACE: + element.addClass('md-focused'); + listener(ev); + break; + case $mdConstant.KEY_CODE.ENTER: + // Match the behavior of the native . + // When the enter key is pressed while focusing a native checkbox inside a form, + // the browser will trigger a `click` on the first non-disabled submit button/input + // in the form. Note that this is different from text inputs, which + // will directly submit the form without needing a submit button/input to be present. + form = $mdUtil.getClosest(ev.target, 'form'); + if (form) { + submit = form.querySelector('button[type="submit"]:enabled, input[type="submit"]:enabled'); + if (submit) { + submit.click(); + } + } + break; + } + } + + function listener(ev) { + // skipToggle boolean is used by the switch directive to prevent the click event + // when releasing the drag. There will be always a click if releasing the drag over the checkbox + if (element[0].hasAttribute('disabled') || scope.skipToggle) { + return; + } + + scope.$apply(function() { + // Toggle the checkbox value... + var viewValue = attr.ngChecked && attr.ngClick ? attr.checked : !ngModelCtrl.$viewValue; + + ngModelCtrl.$setViewValue(viewValue, ev && ev.type); + ngModelCtrl.$render(); + }); + } + + function render() { + // Cast the $viewValue to a boolean since it could be undefined + element.toggleClass('md-checked', !!ngModelCtrl.$viewValue && !isIndeterminate); + } + + function setIndeterminateState(newValue) { + isIndeterminate = newValue !== false; + if (isIndeterminate) { + element.attr('aria-checked', 'mixed'); + } + element.toggleClass('md-indeterminate', isIndeterminate); + } + } + } +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.chips + */ +/* + * @see js folder for chips implementation + */ +angular.module('material.components.chips', [ + 'material.core', + 'material.components.autocomplete' +]); + +})(); +(function(){ +"use strict"; + + +MdChipCtrl.$inject = ["$scope", "$element", "$mdConstant", "$timeout", "$mdUtil"];angular + .module('material.components.chips') + .controller('MdChipCtrl', MdChipCtrl); + +/** + * Controller for the MdChip component. Responsible for handling keyboard + * events and editing the chip if needed. + * + * @param $scope + * @param $element + * @param $mdConstant + * @param $timeout + * @param $mdUtil + * @constructor + */ +function MdChipCtrl ($scope, $element, $mdConstant, $timeout, $mdUtil) { + /** + * @type {$scope} + */ + this.$scope = $scope; + + /** + * @type {$element} + */ + this.$element = $element; + + /** + * @type {$mdConstant} + */ + this.$mdConstant = $mdConstant; + + /** + * @type {$timeout} + */ + this.$timeout = $timeout; + + /** + * @type {$mdUtil} + */ + this.$mdUtil = $mdUtil; + + /** + * @type {boolean} + */ + this.isEditing = false; + + /** + * @type {MdChipsCtrl} + */ + this.parentController = undefined; + + /** + * @type {boolean} + */ + this.enableChipEdit = false; +} + + +/** + * @param {MdChipsCtrl} controller + */ +MdChipCtrl.prototype.init = function(controller) { + this.parentController = controller; + this.enableChipEdit = this.parentController.enableChipEdit; + + if (this.enableChipEdit) { + this.$element.on('keydown', this.chipKeyDown.bind(this)); + this.$element.on('dblclick', this.chipMouseDoubleClick.bind(this)); + this.getChipContent().addClass('_md-chip-content-edit-is-enabled'); + } +}; + + +/** + * @return {Object} first element with the md-chip-content class + */ +MdChipCtrl.prototype.getChipContent = function() { + var chipContents = this.$element[0].getElementsByClassName('md-chip-content'); + return angular.element(chipContents[0]); +}; + + +/** + * When editing the chip, if the user modifies the existing contents, we'll get a span back and + * need to ignore text elements as they only contain blank space. + * `children()` ignores text elements. + * + * When editing the chip, if the user deletes the contents and then enters some new content + * we'll only get a text element back. + * @return {Object} jQuery object representing the content element of the chip + */ +MdChipCtrl.prototype.getContentElement = function() { + var contentElement = angular.element(this.getChipContent().children()[0]); + if (!contentElement || contentElement.length === 0) { + contentElement = angular.element(this.getChipContent().contents()[0]); + } + return contentElement; +}; + + +/** + * @return {number} index of this chip + */ +MdChipCtrl.prototype.getChipIndex = function() { + return parseInt(this.$element.attr('index')); +}; + + +/** + * Update the chip's contents, focus the chip if it's selected, and exit edit mode. + * If the contents were updated to be empty, remove the chip and re-focus the input element. + */ +MdChipCtrl.prototype.goOutOfEditMode = function() { + if (!this.isEditing) { + return; + } + + this.isEditing = false; + this.$element.removeClass('_md-chip-editing'); + this.getChipContent()[0].contentEditable = 'false'; + var chipIndex = this.getChipIndex(); + + var content = this.getContentElement().text(); + if (content) { + this.parentController.updateChipContents(chipIndex, content); + + this.$mdUtil.nextTick(function() { + if (this.parentController.selectedChip === chipIndex) { + this.parentController.focusChip(chipIndex); + } + }.bind(this)); + } else { + this.parentController.removeChipAndFocusInput(chipIndex); + } +}; + + +/** + * Given an HTML element. Selects contents of it. + * @param {Element} node + */ +MdChipCtrl.prototype.selectNodeContents = function(node) { + var range, selection; + if (document.body.createTextRange) { + range = document.body.createTextRange(); + range.moveToElementText(node); + range.select(); + } else if (window.getSelection) { + selection = window.getSelection(); + range = document.createRange(); + range.selectNodeContents(node); + selection.removeAllRanges(); + selection.addRange(range); + } +}; + + +/** + * Presents an input element to edit the contents of the chip. + */ +MdChipCtrl.prototype.goInEditMode = function() { + this.isEditing = true; + this.$element.addClass('_md-chip-editing'); + this.getChipContent()[0].contentEditable = 'true'; + this.getChipContent().on('blur', function() { + this.goOutOfEditMode(); + }.bind(this)); + + this.selectNodeContents(this.getChipContent()[0]); +}; + + +/** + * Handles the keydown event on the chip element. If enable-chip-edit attribute is + * set to true, space or enter keys can trigger going into edit mode. Enter can also + * trigger submitting if the chip is already being edited. + * @param {KeyboardEvent} event + */ +MdChipCtrl.prototype.chipKeyDown = function(event) { + if (!this.isEditing && + (event.keyCode === this.$mdConstant.KEY_CODE.ENTER || + event.keyCode === this.$mdConstant.KEY_CODE.SPACE)) { + event.preventDefault(); + this.goInEditMode(); + } else if (this.isEditing && event.keyCode === this.$mdConstant.KEY_CODE.ENTER) { + event.preventDefault(); + this.goOutOfEditMode(); + } +}; + + +/** + * Enter edit mode if we're not already editing and the enable-chip-edit attribute is enabled. + */ +MdChipCtrl.prototype.chipMouseDoubleClick = function() { + if (this.enableChipEdit && !this.isEditing) { + this.goInEditMode(); + } +}; + +})(); +(function(){ +"use strict"; + + +MdChip.$inject = ["$mdTheming", "$mdUtil", "$compile", "$timeout"];angular + .module('material.components.chips') + .directive('mdChip', MdChip); + +/** + * @ngdoc directive + * @name mdChip + * @module material.components.chips + * + * @description + * `` is a component used within ``. It is responsible for rendering an + * individual chip. + * + * + * @usage + * + * + * {{$chip}} + * + * + * + */ + +/** + * MDChip Directive Definition + * + * @param $mdTheming + * @param $mdUtil + * @param $compile + * @param $timeout + * @ngInject + */ +function MdChip($mdTheming, $mdUtil, $compile, $timeout) { + return { + restrict: 'E', + require: ['^?mdChips', 'mdChip'], + link: postLink, + controller: 'MdChipCtrl' + }; + + function postLink(scope, element, attr, ctrls) { + var chipsController = ctrls.shift(); + var chipController = ctrls.shift(); + var chipContentElement = angular.element(element[0].querySelector('.md-chip-content')); + + $mdTheming(element); + + if (chipsController) { + chipController.init(chipsController); + + // When a chip is blurred, make sure to unset (or reset) the selected chip so that tabbing + // through elements works properly + chipContentElement.on('blur', function() { + chipsController.resetSelectedChip(); + chipsController.$scope.$applyAsync(); + }); + } + + // Use $timeout to ensure we run AFTER the element has been added to the DOM so we can focus it. + $timeout(function() { + if (!chipsController) { + return; + } + + if (chipsController.shouldFocusLastChip) { + chipsController.focusLastChipThenInput(); + } + }); + } +} + +})(); +(function(){ +"use strict"; + + +MdChipRemove.$inject = ["$timeout"];angular + .module('material.components.chips') + .directive('mdChipRemove', MdChipRemove); + +/** + * @ngdoc directive + * @name mdChipRemove + * @restrict A + * @module material.components.chips + * + * @description + * Indicates that the associated element should be used as the delete button template for all chips. + * The associated element must be a child of `md-chips`. + * + * The provided button template will be appended to each chip and will remove the associated chip + * on click. + * + * The button is not styled or themed based on the theme set on the `md-chips` component. A theme + * class and custom icon can be specified in your template. + * + * You can also specify the `type` of the button in your template. + * + * @usage + * ### With Standard Chips + * + * + * + * + * + * + * ### With Object Chips + * + * + * + * + * + */ + + +/** + * MdChipRemove Directive Definition. + * + * @param $timeout + * @returns {{restrict: string, require: string[], link: Function, scope: boolean}} + * @constructor + */ +function MdChipRemove ($timeout) { + return { + restrict: 'A', + require: '^mdChips', + scope: false, + link: postLink + }; + + function postLink(scope, element, attr, ctrl) { + element.on('click', function(event) { + scope.$apply(function() { + ctrl.removeChip(scope.$$replacedScope.$index); + }); + }); + + // Child elements aren't available until after a $timeout tick as they are hidden by an + // `ng-if`. see http://goo.gl/zIWfuw + $timeout(function() { + element.attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); + element.find('button').attr('tabindex', '-1'); + }); + } +} + +})(); +(function(){ +"use strict"; + + +MdChipTransclude.$inject = ["$compile"];angular + .module('material.components.chips') + .directive('mdChipTransclude', MdChipTransclude); + +function MdChipTransclude ($compile) { + return { + restrict: 'EA', + terminal: true, + link: link, + scope: false + }; + function link (scope, element, attr) { + var ctrl = scope.$parent.$mdChipsCtrl, + newScope = ctrl.parent.$new(false, ctrl.parent); + newScope.$$replacedScope = scope; + newScope.$chip = scope.$chip; + newScope.$index = scope.$index; + newScope.$mdChipsCtrl = ctrl; + + var newHtml = ctrl.$scope.$eval(attr.mdChipTransclude); + + element.html(newHtml); + $compile(element.contents())(newScope); + } +} + +})(); +(function(){ +"use strict"; + +/** + * The default chip append delay. + * + * @type {number} + */ +MdChipsCtrl.$inject = ["$scope", "$attrs", "$mdConstant", "$log", "$element", "$timeout", "$mdUtil", "$mdLiveAnnouncer", "$exceptionHandler"]; +var DEFAULT_CHIP_APPEND_DELAY = 300; + +angular + .module('material.components.chips') + .controller('MdChipsCtrl', MdChipsCtrl); + +/** + * Controller for the MdChips component. Responsible for adding to and + * removing from the list of chips, marking chips as selected, and binding to + * the models of various input components. + * + * @param $scope + * @param $attrs + * @param $mdConstant + * @param $log + * @param $element + * @param $timeout + * @param $mdUtil + * @param $mdLiveAnnouncer + * @param $exceptionHandler + * @constructor + */ +function MdChipsCtrl ($scope, $attrs, $mdConstant, $log, $element, $timeout, $mdUtil, + $mdLiveAnnouncer, $exceptionHandler) { + /** @type {Function} **/ + this.$timeout = $timeout; + + /** @type {Object} */ + this.$mdConstant = $mdConstant; + + /** @type {angular.$scope} */ + this.$scope = $scope; + + /** @type {angular.$scope} */ + this.parent = $scope.$parent; + + /** @type {$mdUtil} */ + this.$mdUtil = $mdUtil; + + /** @type {$log} */ + this.$log = $log; + + /** @type {$mdLiveAnnouncer} */ + this.$mdLiveAnnouncer = $mdLiveAnnouncer; + + /** @type {$exceptionHandler} */ + this.$exceptionHandler = $exceptionHandler; + + /** @type {$element} */ + this.$element = $element; + + /** @type {$attrs} */ + this.$attrs = $attrs; + + /** @type {angular.NgModelController} */ + this.ngModelCtrl = null; + + /** @type {angular.NgModelController} */ + this.userInputNgModelCtrl = null; + + /** @type {MdAutocompleteCtrl} */ + this.autocompleteCtrl = null; + + /** @type {Element} */ + this.userInputElement = null; + + /** @type {Array.} */ + this.items = []; + + /** @type {number} */ + this.selectedChip = -1; + + /** @type {string} */ + this.enableChipEdit = $mdUtil.parseAttributeBoolean($attrs.mdEnableChipEdit); + + /** @type {string} */ + this.addOnBlur = $mdUtil.parseAttributeBoolean($attrs.mdAddOnBlur); + + /** + * The text to be used as the aria-label for the input. + * @type {string} + */ + this.inputAriaLabel = 'Chips input.'; + + /** + * Label text to describe the chips container. Used to give context and instructions to screen + * reader users when the chips container is selected. + * @type {string} + */ + this.containerHint = 'Chips container. Use arrow keys to select chips.'; + + /** + * Label text to describe the chips container when it is empty. Used to give context and + * instructions to screen reader users when the chips container is selected and it contains + * no chips. + * @type {string} + */ + this.containerEmptyHint = + 'Chips container. Enter the text area, then type text, and press enter to add a chip.'; + + /** + * Hidden hint text for how to delete a chip. Used to give context to screen readers. + * @type {string} + */ + this.deleteHint = 'Press delete to remove this chip.'; + + /** + * Hidden label for the delete button. Used to give context to screen readers. + * @type {string} + */ + this.deleteButtonLabel = 'Remove'; + + /** + * Model used by the input element. + * @type {string} + */ + this.chipBuffer = ''; + + /** + * Whether to use the transformChip expression to transform the chip buffer + * before appending it to the list. + * @type {boolean} + */ + this.useTransformChip = false; + + /** + * Whether to use the onAdd expression to notify of chip additions. + * @type {boolean} + */ + this.useOnAdd = false; + + /** + * Whether to use the onRemove expression to notify of chip removals. + * @type {boolean} + */ + this.useOnRemove = false; + + /** + * The ID of the chips wrapper which is used to build unique IDs for the chips and the aria-owns + * attribute. + * + * Defaults to '_md-chips-wrapper-' plus a unique number. + * + * @type {string} + */ + this.wrapperId = ''; + + /** + * Array of unique numbers which will be auto-generated any time the items change, and is used to + * create unique IDs for the aria-owns attribute. + * + * @type {Array} + */ + this.contentIds = []; + + /** + * The index of the chip that should have it's `tabindex` property set to `0` so it is selectable + * via the keyboard. + * + * @type {number|null} + */ + this.ariaTabIndex = null; + + /** + * After appending a chip, the chip will be focused for this number of milliseconds before the + * input is refocused. + * + * **Note:** This is **required** for compatibility with certain screen readers in order for + * them to properly allow keyboard access. + * + * @type {number} + */ + this.chipAppendDelay = DEFAULT_CHIP_APPEND_DELAY; + + /** + * Collection of functions to call to un-register watchers + * + * @type {Array} + */ + this.deRegister = []; + + /** + * The screen reader will announce the chip content followed by this message when a chip is added. + * @type {string} + */ + this.addedMessage = 'added'; + + /** + * The screen reader will announce the chip content followed by this message when a chip is + * removed. + * @type {string} + */ + this.removedMessage = 'removed'; + + this.init(); +} + +/** + * Initializes variables and sets up watchers + */ +MdChipsCtrl.prototype.init = function() { + var ctrl = this; + + // Set the wrapper ID + this.wrapperId = '_md-chips-wrapper-' + this.$mdUtil.nextUid(); + + // If we're using static chips, then we need to initialize a few things. + if (!this.$element.attr('ng-model')) { + this.setupStaticChips(); + } + + // Setup a watcher which manages the role and aria-owns attributes. + // This is never called for static chips since items is not defined. + this.deRegister.push( + this.$scope.$watchCollection('$mdChipsCtrl.items', function() { + // Make sure our input and wrapper have the correct ARIA attributes + ctrl.setupInputAria(); + ctrl.setupWrapperAria(); + }) + ); + + this.deRegister.push( + this.$attrs.$observe('mdChipAppendDelay', function(newValue) { + ctrl.chipAppendDelay = parseInt(newValue) || DEFAULT_CHIP_APPEND_DELAY; + }) + ); +}; + +/** + * Destructor for cleanup + */ +MdChipsCtrl.prototype.$onDestroy = function $onDestroy() { + var $destroyFn; + while (($destroyFn = this.deRegister.pop())) { + $destroyFn.call(this); + } +}; + +/** + * If we have an input, ensure it has the appropriate ARIA attributes. + */ +MdChipsCtrl.prototype.setupInputAria = function() { + var input = this.$element.find('input'); + + // If we have no input, just return + if (!input) { + return; + } + + input.attr('role', 'textbox'); + input.attr('aria-multiline', true); + if (this.inputAriaDescribedBy) { + input.attr('aria-describedby', this.inputAriaDescribedBy); + } + if (this.inputAriaLabelledBy) { + input.attr('aria-labelledby', this.inputAriaLabelledBy); + input.removeAttr('aria-label'); + } else { + input.attr('aria-label', this.inputAriaLabel); + } +}; + +/** + * Ensure our wrapper has the appropriate ARIA attributes. + */ +MdChipsCtrl.prototype.setupWrapperAria = function() { + var ctrl = this, + wrapper = this.$element.find('md-chips-wrap'); + + if (this.items && this.items.length) { + // Dynamically add the listbox role on every change because it must be removed when there are + // no items. + wrapper.attr('role', 'listbox'); + + // Generate some random (but unique) IDs for each chip + this.contentIds = this.items.map(function() { + return ctrl.wrapperId + '-chip-' + ctrl.$mdUtil.nextUid(); + }); + + // Use the contentIDs above to generate the aria-owns attribute + wrapper.attr('aria-owns', this.contentIds.join(' ')); + wrapper.attr('aria-label', this.containerHint); + } else { + // If we have no items, then the role and aria-owns attributes MUST be removed + wrapper.removeAttr('role'); + wrapper.removeAttr('aria-owns'); + wrapper.attr('aria-label', this.containerEmptyHint); + } +}; + +/** + * Apply specific roles and aria attributes for static chips + */ +MdChipsCtrl.prototype.setupStaticChips = function() { + var ctrl = this, i, staticChips; + var wrapper = this.$element.find('md-chips-wrap'); + + this.$timeout(function() { + wrapper.attr('role', 'list'); + staticChips = wrapper[0].children; + for (i = 0; i < staticChips.length; i++) { + staticChips[i].setAttribute('role', 'listitem'); + staticChips[i].setAttribute('aria-setsize', staticChips.length); + } + if (ctrl.inputAriaDescribedBy) { + wrapper.attr('aria-describedby', ctrl.inputAriaDescribedBy); + } + if (ctrl.inputAriaLabelledBy) { + wrapper.attr('aria-labelledby', ctrl.inputAriaLabelledBy); + wrapper.removeAttr('aria-label'); + } else { + wrapper.attr('aria-label', ctrl.inputAriaLabel); + } + }, 10); +}; + +/** + * Handles the keydown event on the input element: by default appends + * the buffer to the chip list, while backspace removes the last chip in the + * list if the current buffer is empty. + * @param {jQuery.Event|KeyboardEvent} event + */ +MdChipsCtrl.prototype.inputKeydown = function(event) { + var chipBuffer = this.getChipBuffer(); + + // If we have an autocomplete, and it handled the event, we have nothing to do + if (this.autocompleteCtrl && event.isDefaultPrevented && event.isDefaultPrevented()) { + return; + } + + if (event.keyCode === this.$mdConstant.KEY_CODE.BACKSPACE) { + // Only select and focus the previous chip, if the current caret position of the + // input element is at the beginning. + if (this.getCursorPosition(event.target) !== 0) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + + if (this.items.length) { + this.selectAndFocusChipSafe(this.items.length - 1); + } + + return; + } + + // By default appends the buffer to the chip list. + if (!this.separatorKeys || this.separatorKeys.length < 1) { + this.separatorKeys = [this.$mdConstant.KEY_CODE.ENTER]; + } + + // Support additional separator key codes in an array of `md-separator-keys`. + if (this.separatorKeys.indexOf(event.keyCode) !== -1) { + if ((this.autocompleteCtrl && this.requireMatch) || !chipBuffer) return; + event.preventDefault(); + + // Only append the chip and reset the chip buffer if the max chips limit isn't reached. + if (this.hasMaxChipsReached()) return; + + this.appendChip(chipBuffer.trim()); + this.resetChipBuffer(); + + return false; + } +}; + +/** + * Returns the cursor position of the specified input element. + * @param {HTMLInputElement} element relevant input element + * @returns {Number} Cursor Position of the input. + */ +MdChipsCtrl.prototype.getCursorPosition = function(element) { + /* + * Figure out whether the current input for the chips buffer is valid for using + * the selectionStart / end property to retrieve the cursor position. + * Some browsers do not allow the use of those attributes, on different input types. + */ + try { + if (element.selectionStart === element.selectionEnd) { + return element.selectionStart; + } + } catch (e) { + if (!element.value) { + return 0; + } + } +}; + + +/** + * Updates the content of the chip at given index + * @param {number} chipIndex + * @param {string} chipContents + */ +MdChipsCtrl.prototype.updateChipContents = function(chipIndex, chipContents) { + if (chipIndex >= 0 && chipIndex < this.items.length) { + this.items[chipIndex] = chipContents; + this.updateNgModel(true); + } +}; + + +/** + * @return {boolean} true if a chip is currently being edited. False otherwise. + */ +MdChipsCtrl.prototype.isEditingChip = function() { + return !!this.$element[0].querySelector('._md-chip-editing'); +}; + +/** + * @param {string|Object} chip contents of a single chip + * @returns {boolean} true if the chip is an Object, false otherwise. + * @private + */ +MdChipsCtrl.prototype._isChipObject = function(chip) { + return angular.isObject(chip); +}; + +/** + * @returns {boolean} true if chips can be removed, false otherwise. + */ +MdChipsCtrl.prototype.isRemovable = function() { + // Return false if we have static chips + if (!this.ngModelCtrl) { + return false; + } + + return this.readonly ? this.removable : + angular.isDefined(this.removable) ? this.removable : true; +}; + +/** + * Handles the keydown event on the chip elements: backspace removes the selected chip, arrow + * keys switch which chip is active. + * @param {KeyboardEvent} event + */ +MdChipsCtrl.prototype.chipKeydown = function (event) { + if (this.getChipBuffer()) return; + if (this.isEditingChip()) return; + + switch (event.keyCode) { + case this.$mdConstant.KEY_CODE.BACKSPACE: + case this.$mdConstant.KEY_CODE.DELETE: + if (this.selectedChip < 0) return; + event.preventDefault(); + // Cancel the delete action only after the event cancel. Otherwise the page will go back. + if (!this.isRemovable()) return; + this.removeAndSelectAdjacentChip(this.selectedChip, event); + break; + case this.$mdConstant.KEY_CODE.LEFT_ARROW: + event.preventDefault(); + // By default, allow selection of -1 which will focus the input; if we're readonly, don't go + // below 0. + if (this.selectedChip < 0 || (this.readonly && this.selectedChip === 0)) { + this.selectedChip = this.items.length; + } + if (this.items.length) this.selectAndFocusChipSafe(this.selectedChip - 1); + break; + case this.$mdConstant.KEY_CODE.RIGHT_ARROW: + event.preventDefault(); + this.selectAndFocusChipSafe(this.selectedChip + 1); + break; + case this.$mdConstant.KEY_CODE.ESCAPE: + case this.$mdConstant.KEY_CODE.TAB: + if (this.selectedChip < 0) return; + event.preventDefault(); + this.onFocus(); + break; + } +}; + +/** + * Get the input's placeholder - uses `placeholder` when list is empty and `secondary-placeholder` + * when the list is non-empty. If `secondary-placeholder` is not provided, `placeholder` is used + * always. + * @returns {string} + */ +MdChipsCtrl.prototype.getPlaceholder = function() { + // Allow `secondary-placeholder` to be blank. + var useSecondary = (this.items && this.items.length && + (this.secondaryPlaceholder === '' || this.secondaryPlaceholder)); + return useSecondary ? this.secondaryPlaceholder : this.placeholder; +}; + +/** + * Removes chip at {@code index} and selects the adjacent chip. + * @param {number} index adjacent chip to select + * @param {Event=} event + */ +MdChipsCtrl.prototype.removeAndSelectAdjacentChip = function(index, event) { + var self = this; + var selIndex = self.getAdjacentChipIndex(index); + var wrap = this.$element[0].querySelector('md-chips-wrap'); + var chip = this.$element[0].querySelector('md-chip[index="' + index + '"]'); + + self.removeChip(index, event); + + // The double-timeout is currently necessary to ensure that the DOM has finalized and the select() + // will find the proper chip since the selection is index-based. + // + // TODO: Investigate calling from within chip $scope.$on('$destroy') to reduce/remove timeouts + self.$timeout(function() { + self.$timeout(function() { + self.selectAndFocusChipSafe(selIndex); + }); + }); +}; + +/** + * Sets the selected chip index to -1. + */ +MdChipsCtrl.prototype.resetSelectedChip = function() { + this.selectedChip = -1; + this.ariaTabIndex = null; +}; + +/** + * Gets the index of an adjacent chip to select after deletion. Adjacency is + * determined as the next chip in the list, unless the target chip is the + * last in the list, then it is the chip immediately preceding the target. If + * there is only one item in the list, -1 is returned (select none). + * The number returned is the index to select AFTER the target has been removed. + * If the current chip is not selected, then -1 is returned to select none. + * @param {number} index + * @returns {number} + */ +MdChipsCtrl.prototype.getAdjacentChipIndex = function(index) { + var len = this.items.length - 1; + return (len === 0) ? -1 : + (index === len) ? index - 1 : index; +}; + +/** + * Append the contents of the buffer to the chip list. This method will first + * call out to the md-transform-chip method, if provided. + * @param {string} newChip chip buffer contents that will be used to create the new chip + */ +MdChipsCtrl.prototype.appendChip = function(newChip) { + this.shouldFocusLastChip = !this.addOnBlur; + if (this.useTransformChip && this.transformChip) { + var transformedChip = this.transformChip({'$chip': newChip}); + + // Check to make sure the chip is defined before assigning it, otherwise, we'll just assume + // they want the string version. + if (angular.isDefined(transformedChip)) { + newChip = transformedChip; + } + } + + // If items contains an identical object to newChip, do not append + if (angular.isObject(newChip)) { + var identical = this.items.some(function(item) { + return angular.equals(newChip, item); + }); + if (identical) return; + } + + // Check for a null (but not undefined), or existing chip and cancel appending + if (newChip == null || this.items.indexOf(newChip) + 1) return; + + // Append the new chip onto our list + var length = this.items.push(newChip); + var index = length - 1; + + this.updateNgModel(); + + // Tell screen reader users that the chip was successfully added. + // TODO add a way for developers to specify which field of the object should be announced here. + var chipContent = angular.isObject(newChip) ? '' : newChip; + this.$mdLiveAnnouncer.announce(chipContent + ' ' + this.addedMessage, 'assertive'); + + // If the md-on-add attribute is specified, send a chip addition event + if (this.useOnAdd && this.onAdd) { + this.onAdd({ '$chip': newChip, '$index': index }); + } +}; + +/** + * Sets whether to use the md-transform-chip expression. This expression is + * bound to scope and controller in {@code MdChipsDirective} as + * {@code transformChip}. Due to the nature of directive scope bindings, the + * controller cannot know on its own/from the scope whether an expression was + * actually provided. + */ +MdChipsCtrl.prototype.useTransformChipExpression = function() { + this.useTransformChip = true; +}; + +/** + * Sets whether to use the md-on-add expression. This expression is + * bound to scope and controller in {@code MdChipsDirective} as + * {@code onAdd}. Due to the nature of directive scope bindings, the + * controller cannot know on its own/from the scope whether an expression was + * actually provided. + */ +MdChipsCtrl.prototype.useOnAddExpression = function() { + this.useOnAdd = true; +}; + +/** + * Sets whether to use the md-on-remove expression. This expression is + * bound to scope and controller in {@code MdChipsDirective} as + * {@code onRemove}. Due to the nature of directive scope bindings, the + * controller cannot know on its own/from the scope whether an expression was + * actually provided. + */ +MdChipsCtrl.prototype.useOnRemoveExpression = function() { + this.useOnRemove = true; +}; + +/** + * Sets whether to use the md-on-select expression. This expression is + * bound to scope and controller in {@code MdChipsDirective} as + * {@code onSelect}. Due to the nature of directive scope bindings, the + * controller cannot know on its own/from the scope whether an expression was + * actually provided. + */ +MdChipsCtrl.prototype.useOnSelectExpression = function() { + this.useOnSelect = true; +}; + +/** + * Gets the input buffer. The input buffer can be the model bound to the + * default input item {@code this.chipBuffer}, the {@code selectedItem} + * model of an {@code md-autocomplete}, or, through some magic, the model + * bound to any input or text area element found within a + * {@code md-input-container} element. + * @return {string} the input buffer + */ +MdChipsCtrl.prototype.getChipBuffer = function() { + var chipBuffer = !this.userInputElement ? this.chipBuffer : + this.userInputNgModelCtrl ? this.userInputNgModelCtrl.$viewValue : + this.userInputElement[0].value; + + // Ensure that the chip buffer is always a string. For example, the input element buffer + // might be falsy. + return angular.isString(chipBuffer) ? chipBuffer : ''; +}; + +/** + * Resets the input buffer for either the internal input or user provided input element. + */ +MdChipsCtrl.prototype.resetChipBuffer = function() { + if (this.userInputElement) { + if (this.userInputNgModelCtrl) { + this.userInputNgModelCtrl.$setViewValue(''); + this.userInputNgModelCtrl.$render(); + } else { + this.userInputElement[0].value = ''; + } + } else { + this.chipBuffer = ''; + } +}; + +/** + * @returns {boolean} true if the max chips limit has been reached, false otherwise. + */ +MdChipsCtrl.prototype.hasMaxChipsReached = function() { + if (angular.isString(this.maxChips)) this.maxChips = parseInt(this.maxChips, 10) || 0; + + return this.maxChips > 0 && this.items.length >= this.maxChips; +}; + +/** + * Updates the validity properties for the ngModel. + * + * TODO add the md-max-chips validator to this.ngModelCtrl.validators so that the validation will + * be performed automatically. + */ +MdChipsCtrl.prototype.validateModel = function() { + this.ngModelCtrl.$setValidity('md-max-chips', !this.hasMaxChipsReached()); + this.ngModelCtrl.$validate(); // rerun any registered validators +}; + +/** + * Function to handle updating the model, validation, and change notification when a chip + * is added, removed, or changed. + * @param {boolean=} skipValidation true to skip calling validateModel() + */ +MdChipsCtrl.prototype.updateNgModel = function(skipValidation) { + if (!skipValidation) { + this.validateModel(); + } + // This will trigger ng-change to fire, even in cases where $setViewValue() would not. + angular.forEach(this.ngModelCtrl.$viewChangeListeners, function(listener) { + try { + listener(); + } catch (e) { + this.$exceptionHandler(e); + } + }); +}; + +/** + * Removes the chip at the given index. + * @param {number} index of chip to remove + * @param {Event=} event optionally passed to the onRemove callback + */ +MdChipsCtrl.prototype.removeChip = function(index, event) { + var removed = this.items.splice(index, 1); + + this.updateNgModel(); + this.ngModelCtrl.$setDirty(); + + // Tell screen reader users that the chip was successfully removed. + // TODO add a way for developers to specify which field of the object should be announced here. + var chipContent = angular.isObject(removed[0]) ? '' : removed[0]; + this.$mdLiveAnnouncer.announce(chipContent + ' ' + this.removedMessage, 'assertive'); + + if (removed && removed.length && this.useOnRemove && this.onRemove) { + this.onRemove({ '$chip': removed[0], '$index': index, '$event': event }); + } +}; + +/** + * @param {number} index location of chip to remove + * @param {Event=} $event + */ +MdChipsCtrl.prototype.removeChipAndFocusInput = function (index, $event) { + this.removeChip(index, $event); + + if (this.autocompleteCtrl) { + // Always hide the autocomplete dropdown before focusing the autocomplete input. + // Wait for the input to move horizontally, because the chip was removed. + // This can lead to an incorrect dropdown position. + this.autocompleteCtrl.hidden = true; + this.$mdUtil.nextTick(this.onFocus.bind(this)); + } else { + this.onFocus(); + } + +}; +/** + * Selects the chip at `index`, + * @param {number} index location of chip to select and focus + */ +MdChipsCtrl.prototype.selectAndFocusChipSafe = function(index) { + // If we have no chips, or are asked to select a chip before the first, just focus the input + if (!this.items.length || index === -1) { + return this.focusInput(); + } + + // If we are asked to select a chip greater than the number of chips... + if (index >= this.items.length) { + if (this.readonly) { + // If we are readonly, jump back to the start (because we have no input) + index = 0; + } else { + // If we are not readonly, we should attempt to focus the input + return this.onFocus(); + } + } + + index = Math.max(index, 0); + index = Math.min(index, this.items.length - 1); + + this.selectChip(index); + this.focusChip(index); +}; + +/** + * Focus last chip, then focus the input. This is needed for screen reader support. + */ +MdChipsCtrl.prototype.focusLastChipThenInput = function() { + var ctrl = this; + + ctrl.shouldFocusLastChip = false; + + ctrl.focusChip(this.items.length - 1); + + ctrl.$timeout(function() { + ctrl.focusInput(); + }, ctrl.chipAppendDelay); +}; + +/** + * Focus the input element. + */ +MdChipsCtrl.prototype.focusInput = function() { + this.selectChip(-1); + this.onFocus(); +}; + +/** + * Marks the chip at the given index as selected. + * @param {number} index location of chip to select + */ +MdChipsCtrl.prototype.selectChip = function(index) { + if (index >= -1 && index <= this.items.length) { + this.selectedChip = index; + + // Fire the onSelect if provided + if (this.useOnSelect && this.onSelect) { + this.onSelect({'$chip': this.items[index] }); + } + } else { + this.$log.warn('Selected Chip index out of bounds; ignoring.'); + } +}; + +/** + * Selects the chip at {@code index} and gives it focus. + * @param {number} index location of chip to select and focus + * @deprecated use MdChipsCtrl.selectAndFocusChipSafe. Will be removed in 1.2. + */ +MdChipsCtrl.prototype.selectAndFocusChip = function(index) { + this.selectChip(index); + if (index !== -1) { + this.focusChip(index); + } +}; + +/** + * Call {@code focus()} on the chip at {@code index} + * @param {number} index location of chip to focus + */ +MdChipsCtrl.prototype.focusChip = function(index) { + var chipContent = this.$element[0].querySelector( + 'md-chip[index="' + index + '"] .md-chip-content' + ); + + this.ariaTabIndex = index; + + chipContent.focus(); +}; + +/** + * Configures the required interactions with the ngModel Controller. + * Specifically, set {@code this.items} to the {@code NgModelController#$viewValue}. + * @param {NgModelController} ngModelCtrl + */ +MdChipsCtrl.prototype.configureNgModel = function(ngModelCtrl) { + this.ngModelCtrl = ngModelCtrl; + + var self = this; + + // in chips the meaning of $isEmpty changes + ngModelCtrl.$isEmpty = function(value) { + return !value || value.length === 0; + }; + + ngModelCtrl.$render = function() { + // model is updated. do something. + self.items = self.ngModelCtrl.$viewValue; + }; +}; + +MdChipsCtrl.prototype.onFocus = function () { + var input = this.$element[0].querySelector('input'); + input && input.focus(); + this.resetSelectedChip(); +}; + +MdChipsCtrl.prototype.onInputFocus = function () { + this.inputHasFocus = true; + + // Make sure we have the appropriate ARIA attributes + this.setupInputAria(); + + // Make sure we don't have any chips selected + this.resetSelectedChip(); +}; + +MdChipsCtrl.prototype.onInputBlur = function () { + this.inputHasFocus = false; + + if (this.shouldAddOnBlur()) { + this.appendChip(this.getChipBuffer().trim()); + this.resetChipBuffer(); + } +}; + +/** + * Configure event bindings on input element. + * @param {angular.element} inputElement + */ +MdChipsCtrl.prototype.configureInput = function configureInput(inputElement) { + // Find the NgModelCtrl for the input element + var ngModelCtrl = inputElement.controller('ngModel'); + var ctrl = this; + + if (ngModelCtrl) { + + // sync touched-state from inner input to chips-element + this.deRegister.push( + this.$scope.$watch( + function() { + return ngModelCtrl.$touched; + }, + function(isTouched) { + isTouched && ctrl.ngModelCtrl.$setTouched(); + } + ) + ); + + // sync dirty-state from inner input to chips-element + this.deRegister.push( + this.$scope.$watch( + function() { + return ngModelCtrl.$dirty; + }, + function(isDirty) { + isDirty && ctrl.ngModelCtrl.$setDirty(); + } + ) + ); + } +}; + +/** + * Configure event bindings on a user-provided input element. + * @param {angular.element} inputElement + */ +MdChipsCtrl.prototype.configureUserInput = function(inputElement) { + this.userInputElement = inputElement; + + // Find the NgModelCtrl for the input element + var ngModelCtrl = inputElement.controller('ngModel'); + // `.controller` will look in the parent as well. + if (ngModelCtrl !== this.ngModelCtrl) { + this.userInputNgModelCtrl = ngModelCtrl; + } + + var scope = this.$scope; + var ctrl = this; + + // Run all of the events using evalAsync because a focus may fire a blur in the same digest loop + var scopeApplyFn = function(event, fn) { + scope.$evalAsync(angular.bind(ctrl, fn, event)); + }; + + // Bind to keydown and focus events of input + inputElement + .attr({ tabindex: 0 }) + .on('keydown', function(event) { scopeApplyFn(event, ctrl.inputKeydown); }) + .on('focus', function(event) { scopeApplyFn(event, ctrl.onInputFocus); }) + .on('blur', function(event) { scopeApplyFn(event, ctrl.onInputBlur); }); +}; + +/** + * @param {MdAutocompleteCtrl} ctrl controller from the autocomplete component + */ +MdChipsCtrl.prototype.configureAutocomplete = function(ctrl) { + if (ctrl) { + this.autocompleteCtrl = ctrl; + // Update the default container empty hint when we're inside of an autocomplete. + if (!this.$element.attr('container-empty-hint')) { + this.containerEmptyHint = 'Chips container with autocompletion. Enter the text area, ' + + 'type text to search, and then use the up and down arrow keys to select an option. ' + + 'Press enter to add the selected option as a chip.'; + this.setupWrapperAria(); + } + + ctrl.registerSelectedItemWatcher(angular.bind(this, function (item) { + if (item) { + // Only append the chip and reset the chip buffer if the max chips limit isn't reached. + if (this.hasMaxChipsReached()) return; + + this.appendChip(item); + this.resetChipBuffer(); + } + })); + + this.$element.find('input') + .on('focus',angular.bind(this, this.onInputFocus)) + .on('blur', angular.bind(this, this.onInputBlur)); + } +}; + +/** + * @returns {boolean} Whether the current chip buffer should be added on input blur or not. + */ +MdChipsCtrl.prototype.shouldAddOnBlur = function() { + + // Update the custom ngModel validators from the chips component. + this.validateModel(); + + var chipBuffer = this.getChipBuffer().trim(); + // If the model value is empty and required is set on the element, then the model will be invalid. + // In that case, we still want to allow adding the chip. The main (but not only) case we want + // to disallow is adding a chip on blur when md-max-chips validation fails. + var isModelValid = this.ngModelCtrl.$isEmpty(this.ngModelCtrl.$modelValue) || + this.ngModelCtrl.$valid; + var isAutocompleteShowing = this.autocompleteCtrl && !this.autocompleteCtrl.hidden; + + if (this.userInputNgModelCtrl) { + isModelValid = isModelValid && this.userInputNgModelCtrl.$valid; + } + + return this.addOnBlur && !this.requireMatch && chipBuffer && isModelValid && + !isAutocompleteShowing; +}; + +/** + * @returns {boolean} true if the input or a chip is focused. False otherwise. + */ +MdChipsCtrl.prototype.hasFocus = function () { + return this.inputHasFocus || this.selectedChip >= 0; +}; + +/** + * @param {number} index location of content id + * @returns {number} unique id for the aria-owns attribute + */ +MdChipsCtrl.prototype.contentIdFor = function(index) { + return this.contentIds[index]; +}; + +})(); +(function(){ +"use strict"; + + + MdChips.$inject = ["$mdTheming", "$mdUtil", "$compile", "$log", "$timeout", "$$mdSvgRegistry"];angular + .module('material.components.chips') + .directive('mdChips', MdChips); + + /** + * @ngdoc directive + * @name mdChips + * @module material.components.chips + * + * @description + * `` is an input component for building lists of strings or objects. The list items are + * displayed as 'chips'. This component can make use of an `` element or an + * `` element. + * + * ### Custom templates + * A custom template may be provided to render the content of each chip. This is achieved by + * specifying an `` element containing the custom content as a child of + * ``. + * + * Note: Any attributes on + * `` will be dropped as only the innerHTML is used for the chip template. The + * variables `$chip` and `$index` are available in the scope of ``, representing + * the chip object and its index in the list of chips, respectively. + * To override the chip delete control, include an element (ideally a button) with the attribute + * `md-chip-remove`. A click listener to remove the chip will be added automatically. The element + * is also placed as a sibling to the chip content (on which there are also click listeners) to + * avoid a nested ng-click situation. + * + * + * + * Sometimes developers want to limit the amount of possible chips.
    + * You can specify the maximum amount of chips by using the following markup. + * + * + * + * + * + * + * In some cases, you have an autocomplete inside of the `md-chips`.
    + * When the maximum amount of chips has been reached, you can also disable the autocomplete + * selection.
    + * Here is an example markup. + * + * + * + * + * + * + * + * ### Accessibility + * + * The `md-chips` component supports keyboard and screen reader users since Version 1.1.2. In + * order to achieve this, we modified the chips behavior to select newly appended chips for + * `300ms` before re-focusing the input and allowing the user to type. + * + * For most users, this delay is small enough that it will not be noticeable but allows certain + * screen readers to function properly (JAWS and NVDA in particular). + * + * We introduced a new `md-chip-append-delay` option to allow developers to better control this + * behavior. + * + * Please refer to the documentation of this option (below) for more information. + * + * @param {expression} ng-model Assignable AngularJS expression to be data-bound to the list of + * chips. The expression should evaluate to a `string` or `Object` Array. The type of this + * array should align with the return value of `md-transform-chip`. + * @param {expression=} ng-change AngularJS expression to be executed on chip addition, removal, + * or content change. + * @param {string=} placeholder Placeholder text that will be forwarded to the input. + * @param {string=} secondary-placeholder Placeholder text that will be forwarded to the input, + * displayed when there is at least one item in the list + * @param {boolean=} md-removable Enables or disables the deletion of chips through the + * removal icon or the Delete/Backspace key. Defaults to true. + * @param {boolean=} readonly Disables list manipulation (deleting or adding list items), hiding + * the input and delete buttons. If no `ng-model` is provided, the chips will automatically be + * marked as readonly.

    + * When `md-removable` is not defined, the `md-remove` behavior will be overwritten and + * disabled. + * @param {boolean=} md-enable-chip-edit Set this to `"true"` to enable editing of chip contents. + * The user can go into edit mode by pressing the `space` or `enter` keys, or by double + * clicking on the chip. Chip editing is only supported for chips using the basic template. + * **Note:** This attribute is only evaluated once; it is not watched. + * @param {boolean=} ng-required Whether ng-model is allowed to be empty or not. + * @param {number=} md-max-chips The maximum number of chips allowed to add through user input. + *

    The validation property `md-max-chips` can be used when the max chips + * amount is reached. + * @param {boolean=} md-add-on-blur When set to `"true"`, the remaining text inside of the input + * will be converted into a new chip on blur. + * **Note:** This attribute is only evaluated once; it is not watched. + * @param {expression} md-transform-chip An expression of form `myFunction($chip)` that when + * called expects one of the following return values: + * - an object representing the `$chip` input string + * - `undefined` to simply add the `$chip` input string, or + * - `null` to prevent the chip from being appended + * @param {expression=} md-on-add An expression which will be called when a chip has been + * added with `$chip` and `$index` available as parameters. + * @param {expression=} md-on-remove An expression which will be called when a chip has been + * removed with `$chip`, `$index`, and `$event` available as parameters. + * @param {expression=} md-on-select An expression which will be called when a chip is selected. + * @param {boolean=} md-require-match If true, and the chips template contains an autocomplete, + * only allow selection of pre-defined chips (i.e. you cannot add new ones). + * @param {string=} input-aria-describedby A space-separated list of element IDs. This should + * contain the IDs of any elements that describe this autocomplete. Screen readers will read + * the content of these elements at the end of announcing that the chips input has been + * selected and describing its current state. The descriptive elements do not need to be + * visible on the page. + * @param {string=} input-aria-labelledby A space-separated list of element IDs. The ideal use + * case is that this would contain the ID of a `
    \ + \ +
    \ + {{$chip[$mdContactChipsCtrl.contactName]}}\ +
    \ +
    \ + {{$chip[$mdContactChipsCtrl.contactName]}}\ +
    \ +
    \ +
    '; + + +/** + * MDContactChips Directive Definition + * + * @param $mdTheming + * @param $mdUtil + * @returns {*} + * @ngInject + */ +function MdContactChips($mdTheming, $mdUtil) { + return { + template: function(element, attrs) { + return MD_CONTACT_CHIPS_TEMPLATE; + }, + restrict: 'E', + controller: 'MdContactChipsCtrl', + controllerAs: '$mdContactChipsCtrl', + bindToController: true, + compile: compile, + scope: { + contactQuery: '&mdContacts', + placeholder: '@?', + secondaryPlaceholder: '@?', + contactName: '@mdContactName', + contactImage: '@mdContactImage', + contactEmail: '@mdContactEmail', + contacts: '=ngModel', + ngChange: '&?', + requireMatch: '=?mdRequireMatch', + minLength: '=?mdMinLength', + highlightFlags: '@?mdHighlightFlags', + chipAppendDelay: '@?mdChipAppendDelay', + separatorKeys: '=?mdSeparatorKeys', + removedMessage: '@?mdRemovedMessage', + inputAriaDescribedBy: '@?inputAriaDescribedby', + inputAriaLabelledBy: '@?inputAriaLabelledby', + inputAriaLabel: '@?', + containerHint: '@?', + containerEmptyHint: '@?', + deleteHint: '@?' + } + }; + + function compile(element, attr) { + return function postLink(scope, element, attrs, controllers) { + var contactChipsController = controllers; + + $mdUtil.initOptionalProperties(scope, attr); + $mdTheming(element); + + element.attr('tabindex', '-1'); + + attrs.$observe('mdChipAppendDelay', function(newValue) { + contactChipsController.chipAppendDelay = newValue; + }); + }; + } +} + +})(); +(function(){ +"use strict"; + +(function () { + "use strict"; + + /** + * Use a RegExp to check if the `md-colors=""` is static string + * or one that should be observed and dynamically interpolated. + */ + MdColorsDirective.$inject = ["$mdColors", "$mdUtil", "$log", "$parse"]; + MdColorsService.$inject = ["$mdTheming", "$mdUtil", "$log"]; + var STATIC_COLOR_EXPRESSION = /^{((\s|,)*?["'a-zA-Z-]+?\s*?:\s*?('|")[a-zA-Z0-9-.]*('|"))+\s*}$/; + var colorPalettes = null; + + /** + * @ngdoc module + * @name material.components.colors + * + * @description + * Define $mdColors service and a `md-colors=""` attribute directive + */ + angular + .module('material.components.colors', ['material.core']) + .directive('mdColors', MdColorsDirective) + .service('$mdColors', MdColorsService); + + /** + * @ngdoc service + * @name $mdColors + * @module material.components.colors + * + * @description + * By default, defining a theme does not make its colors available for applying to non AngularJS + * Material elements. The `$mdColors` service is used by the `md-color` directive to convert a + * set of color expressions to RGBA values and then apply those values to the element as CSS + * property values. + * + * @usage + * Getting a color based on a theme + * + * + * angular.controller('myCtrl', function ($mdColors) { + * var color = $mdColors.getThemeColor('myTheme-primary-900-0.5'); + * ... + * }); + * + * + * Applying a color from a palette to an element + * + * app.directive('myDirective', function($mdColors) { + * return { + * ... + * link: function (scope, elem) { + * $mdColors.applyThemeColors(elem, {color: 'red-A200-0.2'}); + * } + * } + * }); + * + */ + function MdColorsService($mdTheming, $mdUtil, $log) { + colorPalettes = colorPalettes || Object.keys($mdTheming.PALETTES); + + // Publish service instance + return { + applyThemeColors: applyThemeColors, + getThemeColor: getThemeColor, + hasTheme: hasTheme + }; + + // ******************************************** + // Internal Methods + // ******************************************** + + /** + * @ngdoc method + * @name $mdColors#applyThemeColors + * + * @description + * Lookup a set of colors by hue, theme, and palette, then apply those colors + * with the provided opacity (via `rgba()`) to the specified CSS property. + * + * @param {angular.element} element the element to apply the styles to + * @param {Object} colorExpression Keys are CSS properties and values are strings representing + * the `theme-palette-hue-opacity` of the desired color. For example: + * `{'color': 'red-A200-0.3', 'background-color': 'myTheme-primary-700-0.8'}`. Theme, hue, and + * opacity are optional. + */ + function applyThemeColors(element, colorExpression) { + try { + if (colorExpression) { + // Assign the calculate RGBA color values directly as inline CSS + element.css(interpolateColors(colorExpression)); + } + } catch (e) { + $log.error(e.message); + } + } + + /** + * @ngdoc method + * @name $mdColors#getThemeColor + * + * @description + * Get a parsed RGBA color using a string representing the `theme-palette-hue-opacity` of the + * desired color. + * + * @param {string} expression color expression like `'red-A200-0.3'` or + * `'myTheme-primary-700-0.8'`. Theme, hue, and opacity are optional. + * @returns {string} a CSS color value like `rgba(211, 47, 47, 0.8)` + */ + function getThemeColor(expression) { + var color = extractColorOptions(expression); + + return parseColor(color); + } + + /** + * Return the parsed color + * @param {{hue: *, theme: any, palette: *, opacity: (*|string|number)}} color hash map of color + * definitions + * @param {boolean=} contrast whether use contrast color for foreground. Defaults to false. + * @returns {string} rgba color string + */ + function parseColor(color, contrast) { + contrast = contrast || false; + var rgbValues = $mdTheming.PALETTES[color.palette][color.hue]; + + rgbValues = contrast ? rgbValues.contrast : rgbValues.value; + + return $mdUtil.supplant('rgba({0}, {1}, {2}, {3})', + [rgbValues[0], rgbValues[1], rgbValues[2], rgbValues[3] || color.opacity] + ); + } + + /** + * Convert the color expression into an object with scope-interpolated values + * Then calculate the rgba() values based on the theme color parts + * @param {Object} themeColors json object, keys are css properties and values are string of + * the wanted color, for example: `{color: 'red-A200-0.3'}`. + * @return {Object} Hashmap of CSS properties with associated `rgba()` string values + */ + function interpolateColors(themeColors) { + var rgbColors = {}; + + var hasColorProperty = themeColors.hasOwnProperty('color'); + + angular.forEach(themeColors, function (value, key) { + var color = extractColorOptions(value); + var hasBackground = key.indexOf('background') > -1; + + rgbColors[key] = parseColor(color); + if (hasBackground && !hasColorProperty) { + rgbColors.color = parseColor(color, true); + } + }); + + return rgbColors; + } + + /** + * Check if expression has defined theme + * For instance: + * 'myTheme-primary' => true + * 'red-800' => false + * @param {string} expression color expression like 'red-800', 'red-A200-0.3', + * 'myTheme-primary', or 'myTheme-primary-400' + * @return {boolean} true if the expression has a theme part, false otherwise. + */ + function hasTheme(expression) { + return angular.isDefined($mdTheming.THEMES[expression.split('-')[0]]); + } + + /** + * For the evaluated expression, extract the color parts into a hash map + * @param {string} expression color expression like 'red-800', 'red-A200-0.3', + * 'myTheme-primary', or 'myTheme-primary-400' + * @returns {{hue: *, theme: any, palette: *, opacity: (*|string|number)}} + */ + function extractColorOptions(expression) { + var parts = expression.split('-'); + var hasTheme = angular.isDefined($mdTheming.THEMES[parts[0]]); + var theme = hasTheme ? parts.splice(0, 1)[0] : $mdTheming.defaultTheme(); + + return { + theme: theme, + palette: extractPalette(parts, theme), + hue: extractHue(parts, theme), + opacity: parts[2] || 1 + }; + } + + /** + * Calculate the theme palette name + * @param {Array} parts + * @param {string} theme name + * @return {string} + */ + function extractPalette(parts, theme) { + // If the next section is one of the palettes we assume it's a two word palette + // Two word palette can be also written in camelCase, forming camelCase to dash-case + + var isTwoWord = parts.length > 1 && colorPalettes.indexOf(parts[1]) !== -1; + var palette = parts[0].replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); + + if (isTwoWord) palette = parts[0] + '-' + parts.splice(1, 1); + + if (colorPalettes.indexOf(palette) === -1) { + // If the palette is not in the palette list it's one of primary/accent/warn/background + var scheme = $mdTheming.THEMES[theme].colors[palette]; + if (!scheme) { + throw new Error($mdUtil.supplant( + 'mdColors: couldn\'t find \'{palette}\' in the palettes.', + {palette: palette})); + } + palette = scheme.name; + } + + return palette; + } + + /** + * @param {Array} parts + * @param {string} theme name + * @return {*} + */ + function extractHue(parts, theme) { + var themeColors = $mdTheming.THEMES[theme].colors; + + if (parts[1] === 'hue') { + var hueNumber = parseInt(parts.splice(2, 1)[0], 10); + + if (hueNumber < 1 || hueNumber > 3) { + throw new Error($mdUtil.supplant( + 'mdColors: \'hue-{hueNumber}\' is not a valid hue, can be only \'hue-1\', \'hue-2\' and \'hue-3\'', + {hueNumber: hueNumber})); + } + parts[1] = 'hue-' + hueNumber; + + if (!(parts[0] in themeColors)) { + throw new Error($mdUtil.supplant( + 'mdColors: \'hue-x\' can only be used with [{availableThemes}], but was used with \'{usedTheme}\'', + { + availableThemes: Object.keys(themeColors).join(', '), + usedTheme: parts[0] + })); + } + + return themeColors[parts[0]].hues[parts[1]]; + } + + return parts[1] || themeColors[parts[0] in themeColors ? parts[0] : 'primary'].hues['default']; + } + } + + /** + * @ngdoc directive + * @name mdColors + * @module material.components.colors + * + * @restrict A + * + * @description + * `mdColors` directive will apply the theme-based color expression as RGBA CSS style values. + * + * The format will be similar to the colors defined in the Sass files: + * + * ## `[?theme]-[palette]-[?hue]-[?opacity]` + * - [theme] - default value is the default theme + * - [palette] - can be either palette name or primary/accent/warn/background + * - [hue] - default is 500 (hue-x can be used with primary/accent/warn/background) + * - [opacity] - default is 1 + * + * + * > `?` indicates optional parameter + * + * @usage + * + *
    + *
    + * Color demo + *
    + *
    + *
    + * + * The `mdColors` directive will automatically watch for changes in the expression if it recognizes + * an interpolation expression or a function. For performance options, you can use `::` prefix to + * the `md-colors` expression to indicate a one-time data binding. + * + * + * + * + * + */ + function MdColorsDirective($mdColors, $mdUtil, $log, $parse) { + return { + restrict: 'A', + require: ['^?mdTheme'], + compile: function (tElem, tAttrs) { + var shouldWatch = shouldColorsWatch(); + + return function (scope, element, attrs, ctrl) { + var mdThemeController = ctrl[0]; + + var lastColors = {}; + + /** + * @param {string=} theme + * @return {Object} colors found in the specified theme + */ + var parseColors = function (theme) { + if (typeof theme !== 'string') { + theme = ''; + } + + if (!attrs.mdColors) { + attrs.mdColors = '{}'; + } + + /** + * Json.parse() does not work because the keys are not quoted; + * use $parse to convert to a hash map + */ + var colors = $parse(attrs.mdColors)(scope); + + /** + * If mdTheme is defined higher up the DOM tree, + * we add mdTheme's theme to the colors which don't specify a theme. + * + * @example + * + *
    + *
    + * Color demo + *
    + *
    + *
    + * + * 'primary-600' will be changed to 'myTheme-primary-600', + * but 'mySecondTheme-accent-200' will not be changed since it has a theme defined. + */ + if (mdThemeController) { + Object.keys(colors).forEach(function (prop) { + var color = colors[prop]; + if (!$mdColors.hasTheme(color)) { + colors[prop] = (theme || mdThemeController.$mdTheme) + '-' + color; + } + }); + } + + cleanElement(colors); + + return colors; + }; + + /** + * @param {Object} colors + */ + var cleanElement = function (colors) { + if (!angular.equals(colors, lastColors)) { + var keys = Object.keys(lastColors); + + if (lastColors.background && !keys.color) { + keys.push('color'); + } + + keys.forEach(function (key) { + element.css(key, ''); + }); + } + + lastColors = colors; + }; + + /** + * Registering for mgTheme changes and asking mdTheme controller run our callback whenever + * a theme changes. + */ + var unregisterChanges = angular.noop; + + if (mdThemeController) { + unregisterChanges = mdThemeController.registerChanges(function (theme) { + $mdColors.applyThemeColors(element, parseColors(theme)); + }); + } + + scope.$on('$destroy', function () { + unregisterChanges(); + }); + + try { + if (shouldWatch) { + scope.$watch(parseColors, angular.bind(this, + $mdColors.applyThemeColors, element + ), true); + } + else { + $mdColors.applyThemeColors(element, parseColors()); + } + + } + catch (e) { + $log.error(e.message); + } + + }; + + /** + * @return {boolean} + */ + function shouldColorsWatch() { + // Simulate 1x binding and mark mdColorsWatch == false + var rawColorExpression = tAttrs.mdColors; + var bindOnce = rawColorExpression.indexOf('::') > -1; + var isStatic = bindOnce ? true : STATIC_COLOR_EXPRESSION.test(tAttrs.mdColors); + + // Remove it for the postLink... + tAttrs.mdColors = rawColorExpression.replace('::', ''); + + var hasWatchAttr = angular.isDefined(tAttrs.mdColorsWatch); + + return (bindOnce || isStatic) ? false : + hasWatchAttr ? $mdUtil.parseAttributeBoolean(tAttrs.mdColorsWatch) : true; + } + } + }; + } +})(); + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.content + * + * @description + * Scrollable content + */ +mdContentDirective.$inject = ["$mdTheming"]; +angular.module('material.components.content', [ + 'material.core' +]) + .directive('mdContent', mdContentDirective); + +/** + * @ngdoc directive + * @name mdContent + * @module material.components.content + * + * @restrict E + * + * @description + * + * The `` directive is a container element useful for scrollable content. It achieves + * this by setting the CSS `overflow` property to `auto` so that content can properly scroll. + * + * In general, `` components are not designed to be nested inside one another. If + * possible, it is better to make them siblings. This often results in a better user experience as + * having nested scrollbars may confuse the user. + * + * ## Troubleshooting + * + * In some cases, you may wish to apply the `md-no-momentum` class to ensure that Safari's + * momentum scrolling is disabled. Momentum scrolling can cause flickering issues while scrolling + * SVG icons and some other components. + * + * Additionally, we now also offer the `md-no-flicker` class which can be applied to any element + * and uses a Webkit-specific filter of `blur(0px)` that forces GPU rendering of all elements + * inside (which eliminates the flicker on iOS devices). + * + * _Note: Forcing an element to render on the GPU can have unintended side-effects, especially + * related to the z-index of elements. Please use with caution and only on the elements needed._ + * + * @usage + * + * Add the `[layout-padding]` attribute to make the content padded. + * + * + * + * Lorem ipsum dolor sit amet, ne quod novum mei. + * + * + */ + +function mdContentDirective($mdTheming) { + return { + restrict: 'E', + controller: ['$scope', '$element', ContentController], + link: function(scope, element) { + element.addClass('_md'); // private md component indicator for styling + + $mdTheming(element); + scope.$broadcast('$mdContentLoaded', element); + + iosScrollFix(element[0]); + } + }; + + function ContentController($scope, $element) { + this.$scope = $scope; + this.$element = $element; + } +} + +function iosScrollFix(node) { + // IOS FIX: + // If we scroll where there is no more room for the webview to scroll, + // by default the webview itself will scroll up and down, this looks really + // bad. So if we are scrolling to the very top or bottom, add/subtract one + angular.element(node).on('$md.pressdown', function(ev) { + // Only touch events + if (ev.pointer.type !== 't') return; + // Don't let a child content's touchstart ruin it for us. + if (ev.$materialScrollFixed) return; + ev.$materialScrollFixed = true; + + if (node.scrollTop === 0) { + node.scrollTop = 1; + } else if (node.scrollHeight === node.scrollTop + node.offsetHeight) { + node.scrollTop -= 1; + } + }); +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.datepicker + * @description Module for the datepicker component. + */ + +angular.module('material.components.datepicker', [ + 'material.core', + 'material.components.icon', + 'material.components.virtualRepeat' +]); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + /** + * @ngdoc directive + * @name mdCalendar + * @module material.components.datepicker + * + * @param {Date} ng-model The component's model. Should be a Date object. + * @param {Date=} md-min-date Expression representing the minimum date. + * @param {Date=} md-max-date Expression representing the maximum date. + * @param {(function(Date): boolean)=} md-date-filter Function expecting a date and returning a + * boolean whether it can be selected or not. + * @param {String=} md-current-view Current view of the calendar. Can be either "month" or "year". + * @param {String=} md-mode Restricts the user to only selecting a value from a particular view. + * This option can be used if the user is only supposed to choose from a certain date type + * (e.g. only selecting the month). Can be either "month" or "day". **Note** that this will + * overwrite the `md-current-view` value. + * + * @description + * `` is a component that renders a calendar that can be used to select a date. + * It is a part of the `` pane, however it can also be used on it's own. + * + * @usage + * + * + * + * + */ + CalendarCtrl.$inject = ["$element", "$scope", "$$mdDateUtil", "$mdUtil", "$mdConstant", "$mdTheming", "$$rAF", "$attrs", "$mdDateLocale"]; + angular.module('material.components.datepicker') + .directive('mdCalendar', calendarDirective); + + // POST RELEASE + // TODO(jelbourn): Mac Cmd + left / right == Home / End + // TODO(jelbourn): Refactor month element creation to use cloneNode (performance). + // TODO(jelbourn): Define virtual scrolling constants (compactness) users can override. + // TODO(jelbourn): Animated month transition on ng-model change (virtual-repeat) + // TODO(jelbourn): Scroll snapping (virtual repeat) + // TODO(jelbourn): Remove superfluous row from short months (virtual-repeat) + // TODO(jelbourn): Month headers stick to top when scrolling. + // TODO(jelbourn): Previous month opacity is lowered when partially scrolled out of view. + // TODO(jelbourn): Support md-calendar standalone on a page (as a tabstop w/ aria-live + // announcement and key handling). + // Read-only calendar (not just date-picker). + + function calendarDirective() { + return { + template: function(tElement, tAttr) { + // TODO(crisbeto): This is a workaround that allows the calendar to work, without + // a datepicker, until issue #8585 gets resolved. It can safely be removed + // afterwards. This ensures that the virtual repeater scrolls to the proper place on load by + // deferring the execution until the next digest. It's necessary only if the calendar is used + // without a datepicker, otherwise it's already wrapped in an ngIf. + var extraAttrs = tAttr.hasOwnProperty('ngIf') ? '' : 'ng-if="calendarCtrl.isInitialized"'; + var template = '' + + '
    ' + + '' + + '' + + '
    '; + + return template; + }, + scope: { + minDate: '=mdMinDate', + maxDate: '=mdMaxDate', + dateFilter: '=mdDateFilter', + + // These need to be prefixed, because Angular resets + // any changes to the value due to bindToController. + _mode: '@mdMode', + _currentView: '@mdCurrentView' + }, + require: ['ngModel', 'mdCalendar'], + controller: CalendarCtrl, + controllerAs: 'calendarCtrl', + bindToController: true, + link: function(scope, element, attrs, controllers) { + var ngModelCtrl = controllers[0]; + var mdCalendarCtrl = controllers[1]; + mdCalendarCtrl.configureNgModel(ngModelCtrl); + } + }; + } + + /** + * Occasionally the hideVerticalScrollbar method might read an element's + * width as 0, because it hasn't been laid out yet. This value will be used + * as a fallback, in order to prevent scenarios where the element's width + * would otherwise have been set to 0. This value is the "usual" width of a + * calendar within a floating calendar pane. + */ + var FALLBACK_WIDTH = 340; + + /** Next identifier for calendar instance. */ + var nextUniqueId = 0; + + /** Maps the `md-mode` values to their corresponding calendar views. */ + var MODE_MAP = { + day: 'month', + month: 'year' + }; + + /** + * Controller for the mdCalendar component. + * @ngInject @constructor + */ + function CalendarCtrl($element, $scope, $$mdDateUtil, $mdUtil, + $mdConstant, $mdTheming, $$rAF, $attrs, $mdDateLocale) { + + $mdTheming($element); + + /** @final {!angular.JQLite} */ + this.$element = $element; + + /** @final {!angular.Scope} */ + this.$scope = $scope; + + /** @final */ + this.dateUtil = $$mdDateUtil; + + /** @final */ + this.$mdUtil = $mdUtil; + + /** @final */ + this.keyCode = $mdConstant.KEY_CODE; + + /** @final */ + this.$$rAF = $$rAF; + + /** @final */ + this.$mdDateLocale = $mdDateLocale; + + /** @final {Date} */ + this.today = this.dateUtil.createDateAtMidnight(); + + /** @type {!angular.NgModelController} */ + this.ngModelCtrl = null; + + /** @type {String} Class applied to the selected date cell. */ + this.SELECTED_DATE_CLASS = 'md-calendar-selected-date'; + + /** @type {String} Class applied to the cell for today. */ + this.TODAY_CLASS = 'md-calendar-date-today'; + + /** @type {String} Class applied to the focused cell. */ + this.FOCUSED_DATE_CLASS = 'md-focus'; + + /** @final {number} Unique ID for this calendar instance. */ + this.id = nextUniqueId++; + + /** + * The date that is currently focused or showing in the calendar. This will initially be set + * to the ng-model value if set, otherwise to today. It will be updated as the user navigates + * to other months. The cell corresponding to the displayDate does not necesarily always have + * focus in the document (such as for cases when the user is scrolling the calendar). + * @type {Date} + */ + this.displayDate = null; + + /** + * The selected date. Keep track of this separately from the ng-model value so that we + * can know, when the ng-model value changes, what the previous value was before it's updated + * in the component's UI. + * + * @type {Date} + */ + this.selectedDate = null; + + /** + * The first date that can be rendered by the calendar. The default is taken + * from the mdDateLocale provider and is limited by the mdMinDate. + * @type {Date} + */ + this.firstRenderableDate = null; + + /** + * The last date that can be rendered by the calendar. The default comes + * from the mdDateLocale provider and is limited by the maxDate. + * @type {Date} + */ + this.lastRenderableDate = null; + + /** + * Used to toggle initialize the root element in the next digest. + * @type {Boolean} + */ + this.isInitialized = false; + + /** + * Cache for the width of the element without a scrollbar. Used to hide the scrollbar later on + * and to avoid extra reflows when switching between views. + * @type {Number} + */ + this.width = 0; + + /** + * Caches the width of the scrollbar in order to be used when hiding it and to avoid extra reflows. + * @type {Number} + */ + this.scrollbarWidth = 0; + + // Unless the user specifies so, the calendar should not be a tab stop. + // This is necessary because ngAria might add a tabindex to anything with an ng-model + // (based on whether or not the user has turned that particular feature on/off). + if (!$attrs.tabindex) { + $element.attr('tabindex', '-1'); + } + + var boundKeyHandler = angular.bind(this, this.handleKeyEvent); + + // If use the md-calendar directly in the body without datepicker, + // handleKeyEvent will disable other inputs on the page. + // So only apply the handleKeyEvent on the body when the md-calendar inside datepicker, + // otherwise apply on the calendar element only. + + var handleKeyElement; + if ($element.parent().hasClass('md-datepicker-calendar')) { + handleKeyElement = angular.element(document.body); + } else { + handleKeyElement = $element; + } + + // Bind the keydown handler to the body, in order to handle cases where the focused + // element gets removed from the DOM and stops propagating click events. + handleKeyElement.on('keydown', boundKeyHandler); + + $scope.$on('$destroy', function() { + handleKeyElement.off('keydown', boundKeyHandler); + }); + + // For AngularJS 1.4 and older, where there are no lifecycle hooks but bindings are pre-assigned, + // manually call the $onInit hook. + if (angular.version.major === 1 && angular.version.minor <= 4) { + this.$onInit(); + } + + } + + /** + * AngularJS Lifecycle hook for newer AngularJS versions. + * Bindings are not guaranteed to have been assigned in the controller, but they are in the $onInit hook. + */ + CalendarCtrl.prototype.$onInit = function() { + /** + * The currently visible calendar view. Note the prefix on the scope value, + * which is necessary, because the datepicker seems to reset the real one value if the + * calendar is open, but the `currentView` on the datepicker's scope is empty. + * @type {String} + */ + if (this._mode && MODE_MAP.hasOwnProperty(this._mode)) { + this.currentView = MODE_MAP[this._mode]; + this.mode = this._mode; + } else { + this.currentView = this._currentView || 'month'; + this.mode = null; + } + + var dateLocale = this.$mdDateLocale; + + if (this.minDate && this.minDate > dateLocale.firstRenderableDate) { + this.firstRenderableDate = this.minDate; + } else { + this.firstRenderableDate = dateLocale.firstRenderableDate; + } + + if (this.maxDate && this.maxDate < dateLocale.lastRenderableDate) { + this.lastRenderableDate = this.maxDate; + } else { + this.lastRenderableDate = dateLocale.lastRenderableDate; + } + }; + + /** + * Sets up the controller's reference to ngModelController. + * @param {!angular.NgModelController} ngModelCtrl + */ + CalendarCtrl.prototype.configureNgModel = function(ngModelCtrl) { + var self = this; + + self.ngModelCtrl = ngModelCtrl; + + self.$mdUtil.nextTick(function() { + self.isInitialized = true; + }); + + ngModelCtrl.$render = function() { + var value = this.$viewValue; + + // Notify the child scopes of any changes. + self.$scope.$broadcast('md-calendar-parent-changed', value); + + // Set up the selectedDate if it hasn't been already. + if (!self.selectedDate) { + self.selectedDate = value; + } + + // Also set up the displayDate. + if (!self.displayDate) { + self.displayDate = self.selectedDate || self.today; + } + }; + }; + + /** + * Sets the ng-model value for the calendar and emits a change event. + * @param {Date} date + */ + CalendarCtrl.prototype.setNgModelValue = function(date) { + var value = this.dateUtil.createDateAtMidnight(date); + this.focus(value); + this.$scope.$emit('md-calendar-change', value); + this.ngModelCtrl.$setViewValue(value); + this.ngModelCtrl.$render(); + return value; + }; + + /** + * Sets the current view that should be visible in the calendar + * @param {string} newView View name to be set. + * @param {number|Date} time Date object or a timestamp for the new display date. + */ + CalendarCtrl.prototype.setCurrentView = function(newView, time) { + var self = this; + + self.$mdUtil.nextTick(function() { + self.currentView = newView; + + if (time) { + self.displayDate = angular.isDate(time) ? time : new Date(time); + } + }); + }; + + /** + * Focus the cell corresponding to the given date. + * @param {Date} date The date to be focused. + */ + CalendarCtrl.prototype.focus = function(date) { + if (this.dateUtil.isValidDate(date)) { + var previousFocus = this.$element[0].querySelector('.' + this.FOCUSED_DATE_CLASS); + if (previousFocus) { + previousFocus.classList.remove(this.FOCUSED_DATE_CLASS); + } + + var cellId = this.getDateId(date, this.currentView); + var cell = document.getElementById(cellId); + if (cell) { + cell.classList.add(this.FOCUSED_DATE_CLASS); + cell.focus(); + this.displayDate = date; + } + } else { + var rootElement = this.$element[0].querySelector('[ng-switch]'); + + if (rootElement) { + rootElement.focus(); + } + } + }; + + /** + * Highlights a date cell on the calendar and changes the selected date. + * @param {Date=} date Date to be marked as selected. + */ + CalendarCtrl.prototype.changeSelectedDate = function(date) { + var selectedDateClass = this.SELECTED_DATE_CLASS; + var prevDateCell = this.$element[0].querySelector('.' + selectedDateClass); + + // Remove the selected class from the previously selected date, if any. + if (prevDateCell) { + prevDateCell.classList.remove(selectedDateClass); + prevDateCell.setAttribute('aria-selected', 'false'); + } + + // Apply the select class to the new selected date if it is set. + if (date) { + var dateCell = document.getElementById(this.getDateId(date, this.currentView)); + if (dateCell) { + dateCell.classList.add(selectedDateClass); + dateCell.setAttribute('aria-selected', 'true'); + } + } + + this.selectedDate = date; + }; + + /** + * Normalizes the key event into an action name. The action will be broadcast + * to the child controllers. + * @param {KeyboardEvent} event + * @returns {String} The action that should be taken, or null if the key + * does not match a calendar shortcut. + */ + CalendarCtrl.prototype.getActionFromKeyEvent = function(event) { + var keyCode = this.keyCode; + + switch (event.which) { + case keyCode.ENTER: return 'select'; + + case keyCode.RIGHT_ARROW: return 'move-right'; + case keyCode.LEFT_ARROW: return 'move-left'; + + case keyCode.DOWN_ARROW: return event.metaKey ? 'move-page-down' : 'move-row-down'; + case keyCode.UP_ARROW: return event.metaKey ? 'move-page-up' : 'move-row-up'; + + case keyCode.PAGE_DOWN: return 'move-page-down'; + case keyCode.PAGE_UP: return 'move-page-up'; + + case keyCode.HOME: return 'start'; + case keyCode.END: return 'end'; + + default: return null; + } + }; + + /** + * Handles a key event in the calendar with the appropriate action. The action will either + * be to select the focused date or to navigate to focus a new date. + * @param {KeyboardEvent} event + */ + CalendarCtrl.prototype.handleKeyEvent = function(event) { + var self = this; + + this.$scope.$apply(function() { + // Capture escape and emit back up so that a wrapping component + // (such as a date-picker) can decide to close. + if (event.which == self.keyCode.ESCAPE || event.which == self.keyCode.TAB) { + self.$scope.$emit('md-calendar-close'); + + if (event.which == self.keyCode.TAB) { + event.preventDefault(); + } + + return; + } + + // Broadcast the action that any child controllers should take. + var action = self.getActionFromKeyEvent(event); + if (action) { + event.preventDefault(); + event.stopPropagation(); + self.$scope.$broadcast('md-calendar-parent-action', action); + } + }); + }; + + /** + * Hides the vertical scrollbar on the calendar scroller of a child controller by + * setting the width on the calendar scroller and the `overflow: hidden` wrapper + * around the scroller, and then setting a padding-right on the scroller equal + * to the width of the browser's scrollbar. + * + * This will cause a reflow. + * + * @param {object} childCtrl The child controller whose scrollbar should be hidden. + */ + CalendarCtrl.prototype.hideVerticalScrollbar = function(childCtrl) { + var self = this; + var element = childCtrl.$element[0]; + var scrollMask = element.querySelector('.md-calendar-scroll-mask'); + + if (self.width > 0) { + setWidth(); + } else { + self.$$rAF(function() { + var scroller = childCtrl.calendarScroller; + + self.scrollbarWidth = scroller.offsetWidth - scroller.clientWidth; + self.width = element.querySelector('table').offsetWidth; + setWidth(); + }); + } + + function setWidth() { + var width = self.width || FALLBACK_WIDTH; + var scrollbarWidth = self.scrollbarWidth; + var scroller = childCtrl.calendarScroller; + + scrollMask.style.width = width + 'px'; + scroller.style.width = (width + scrollbarWidth) + 'px'; + scroller.style.paddingRight = scrollbarWidth + 'px'; + } + }; + + /** + * Gets an identifier for a date unique to the calendar instance for internal + * purposes. Not to be displayed. + * @param {Date} date The date for which the id is being generated + * @param {string} namespace Namespace for the id. (month, year etc.) + * @returns {string} + */ + CalendarCtrl.prototype.getDateId = function(date, namespace) { + if (!namespace) { + throw new Error('A namespace for the date id has to be specified.'); + } + + return [ + 'md', + this.id, + namespace, + date.getFullYear(), + date.getMonth(), + date.getDate() + ].join('-'); + }; + + /** + * Util to trigger an extra digest on a parent scope, in order to to ensure that + * any child virtual repeaters have updated. This is necessary, because the virtual + * repeater doesn't update the $index the first time around since the content isn't + * in place yet. The case, in which this is an issue, is when the repeater has less + * than a page of content (e.g. a month or year view has a min or max date). + */ + CalendarCtrl.prototype.updateVirtualRepeat = function() { + var scope = this.$scope; + var virtualRepeatResizeListener = scope.$on('$md-resize-enable', function() { + if (!scope.$$phase) { + scope.$apply(); + } + + virtualRepeatResizeListener(); + }); + }; +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + CalendarMonthCtrl.$inject = ["$element", "$scope", "$animate", "$q", "$$mdDateUtil", "$mdDateLocale"]; + angular.module('material.components.datepicker') + .directive('mdCalendarMonth', calendarDirective); + + /** + * Height of one calendar month tbody. This must be made known to the virtual-repeat and is + * subsequently used for scrolling to specific months. + */ + var TBODY_HEIGHT = 265; + + /** + * Height of a calendar month with a single row. This is needed to calculate the offset for + * rendering an extra month in virtual-repeat that only contains one row. + */ + var TBODY_SINGLE_ROW_HEIGHT = 45; + + /** Private directive that represents a list of months inside the calendar. */ + function calendarDirective() { + return { + template: + '' + + '
    ' + + '' + + '' + + '' + + + // The ensures that the will always have the + // proper height, even if it's empty. If it's content is + // compiled, the will be overwritten. + '' + + '' + + '
    ' + + '
    ' + + '
    ', + require: ['^^mdCalendar', 'mdCalendarMonth'], + controller: CalendarMonthCtrl, + controllerAs: 'monthCtrl', + bindToController: true, + link: function(scope, element, attrs, controllers) { + var calendarCtrl = controllers[0]; + var monthCtrl = controllers[1]; + monthCtrl.initialize(calendarCtrl); + } + }; + } + + /** + * Controller for the calendar month component. + * @ngInject @constructor + */ + function CalendarMonthCtrl($element, $scope, $animate, $q, + $$mdDateUtil, $mdDateLocale) { + + /** @final {!angular.JQLite} */ + this.$element = $element; + + /** @final {!angular.Scope} */ + this.$scope = $scope; + + /** @final {!angular.$animate} */ + this.$animate = $animate; + + /** @final {!angular.$q} */ + this.$q = $q; + + /** @final */ + this.dateUtil = $$mdDateUtil; + + /** @final */ + this.dateLocale = $mdDateLocale; + + /** @final {HTMLElement} */ + this.calendarScroller = $element[0].querySelector('.md-virtual-repeat-scroller'); + + /** @type {boolean} */ + this.isInitialized = false; + + /** @type {boolean} */ + this.isMonthTransitionInProgress = false; + + var self = this; + + /** + * Handles a click event on a date cell. + * Created here so that every cell can use the same function instance. + * @this {HTMLTableCellElement} The cell that was clicked. + */ + this.cellClickHandler = function() { + var timestamp = $$mdDateUtil.getTimestampFromNode(this); + self.$scope.$apply(function() { + self.calendarCtrl.setNgModelValue(timestamp); + }); + }; + + /** + * Handles click events on the month headers. Switches + * the calendar to the year view. + * @this {HTMLTableCellElement} The cell that was clicked. + */ + this.headerClickHandler = function() { + self.calendarCtrl.setCurrentView('year', $$mdDateUtil.getTimestampFromNode(this)); + }; + } + + /** Initialization **/ + + /** + * Initialize the controller by saving a reference to the calendar and + * setting up the object that will be iterated by the virtual repeater. + */ + CalendarMonthCtrl.prototype.initialize = function(calendarCtrl) { + /** + * Dummy array-like object for virtual-repeat to iterate over. The length is the total + * number of months that can be viewed. We add 2 months: one to include the current month + * and one for the last dummy month. + * + * This is shorter than ideal because of a (potential) Firefox bug + * https://bugzilla.mozilla.org/show_bug.cgi?id=1181658. + */ + + this.items = { + length: this.dateUtil.getMonthDistance( + calendarCtrl.firstRenderableDate, + calendarCtrl.lastRenderableDate + ) + 2 + }; + + this.calendarCtrl = calendarCtrl; + this.attachScopeListeners(); + calendarCtrl.updateVirtualRepeat(); + + // Fire the initial render, since we might have missed it the first time it fired. + calendarCtrl.ngModelCtrl && calendarCtrl.ngModelCtrl.$render(); + }; + + /** + * Gets the "index" of the currently selected date as it would be in the virtual-repeat. + * @returns {number} + */ + CalendarMonthCtrl.prototype.getSelectedMonthIndex = function() { + var calendarCtrl = this.calendarCtrl; + + return this.dateUtil.getMonthDistance( + calendarCtrl.firstRenderableDate, + calendarCtrl.displayDate || calendarCtrl.selectedDate || calendarCtrl.today + ); + }; + + /** + * Change the date that is being shown in the calendar. If the given date is in a different + * month, the displayed month will be transitioned. + * @param {Date} date + */ + CalendarMonthCtrl.prototype.changeDisplayDate = function(date) { + // Initialization is deferred until this function is called because we want to reflect + // the starting value of ngModel. + if (!this.isInitialized) { + this.buildWeekHeader(); + this.calendarCtrl.hideVerticalScrollbar(this); + this.isInitialized = true; + return this.$q.when(); + } + + // If trying to show an invalid date or a transition is in progress, do nothing. + if (!this.dateUtil.isValidDate(date) || this.isMonthTransitionInProgress) { + return this.$q.when(); + } + + this.isMonthTransitionInProgress = true; + var animationPromise = this.animateDateChange(date); + + this.calendarCtrl.displayDate = date; + + var self = this; + animationPromise.then(function() { + self.isMonthTransitionInProgress = false; + }); + + return animationPromise; + }; + + /** + * Animates the transition from the calendar's current month to the given month. + * @param {Date} date + * @returns {angular.$q.Promise} The animation promise. + */ + CalendarMonthCtrl.prototype.animateDateChange = function(date) { + if (this.dateUtil.isValidDate(date)) { + var monthDistance = this.dateUtil.getMonthDistance(this.calendarCtrl.firstRenderableDate, date); + this.calendarScroller.scrollTop = monthDistance * TBODY_HEIGHT; + } + + return this.$q.when(); + }; + + /** + * Builds and appends a day-of-the-week header to the calendar. + * This should only need to be called once during initialization. + */ + CalendarMonthCtrl.prototype.buildWeekHeader = function() { + var firstDayOfWeek = this.dateLocale.firstDayOfWeek; + var shortDays = this.dateLocale.shortDays; + + var row = document.createElement('tr'); + for (var i = 0; i < 7; i++) { + var th = document.createElement('th'); + th.textContent = shortDays[(i + firstDayOfWeek) % 7]; + row.appendChild(th); + } + + this.$element.find('thead').append(row); + }; + + /** + * Attaches listeners for the scope events that are broadcast by the calendar. + */ + CalendarMonthCtrl.prototype.attachScopeListeners = function() { + var self = this; + + self.$scope.$on('md-calendar-parent-changed', function(event, value) { + self.calendarCtrl.changeSelectedDate(value); + self.changeDisplayDate(value); + }); + + self.$scope.$on('md-calendar-parent-action', angular.bind(this, this.handleKeyEvent)); + }; + + /** + * Handles the month-specific keyboard interactions. + * @param {Object} event Scope event object passed by the calendar. + * @param {String} action Action, corresponding to the key that was pressed. + */ + CalendarMonthCtrl.prototype.handleKeyEvent = function(event, action) { + var calendarCtrl = this.calendarCtrl; + var displayDate = calendarCtrl.displayDate; + + if (action === 'select') { + calendarCtrl.setNgModelValue(displayDate); + } else { + var date = null; + var dateUtil = this.dateUtil; + + switch (action) { + case 'move-right': date = dateUtil.incrementDays(displayDate, 1); break; + case 'move-left': date = dateUtil.incrementDays(displayDate, -1); break; + + case 'move-page-down': date = dateUtil.incrementMonths(displayDate, 1); break; + case 'move-page-up': date = dateUtil.incrementMonths(displayDate, -1); break; + + case 'move-row-down': date = dateUtil.incrementDays(displayDate, 7); break; + case 'move-row-up': date = dateUtil.incrementDays(displayDate, -7); break; + + case 'start': date = dateUtil.getFirstDateOfMonth(displayDate); break; + case 'end': date = dateUtil.getLastDateOfMonth(displayDate); break; + } + + if (date) { + date = this.dateUtil.clampDate(date, calendarCtrl.minDate, calendarCtrl.maxDate); + + this.changeDisplayDate(date).then(function() { + calendarCtrl.focus(date); + }); + } + } + }; +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + mdCalendarMonthBodyDirective.$inject = ["$compile", "$$mdSvgRegistry"]; + CalendarMonthBodyCtrl.$inject = ["$element", "$$mdDateUtil", "$mdDateLocale"]; + angular.module('material.components.datepicker') + .directive('mdCalendarMonthBody', mdCalendarMonthBodyDirective); + + /** + * Private directive consumed by md-calendar-month. Having this directive lets the calender use + * md-virtual-repeat and also cleanly separates the month DOM construction functions from + * the rest of the calendar controller logic. + * @ngInject + */ + function mdCalendarMonthBodyDirective($compile, $$mdSvgRegistry) { + var ARROW_ICON = $compile('')({})[0]; + + return { + require: ['^^mdCalendar', '^^mdCalendarMonth', 'mdCalendarMonthBody'], + scope: { offset: '=mdMonthOffset' }, + controller: CalendarMonthBodyCtrl, + controllerAs: 'mdMonthBodyCtrl', + bindToController: true, + link: function(scope, element, attrs, controllers) { + var calendarCtrl = controllers[0]; + var monthCtrl = controllers[1]; + var monthBodyCtrl = controllers[2]; + + monthBodyCtrl.calendarCtrl = calendarCtrl; + monthBodyCtrl.monthCtrl = monthCtrl; + monthBodyCtrl.arrowIcon = ARROW_ICON.cloneNode(true); + + // The virtual-repeat re-uses the same DOM elements, so there are only a limited number + // of repeated items that are linked, and then those elements have their bindings updated. + // Since the months are not generated by bindings, we simply regenerate the entire thing + // when the binding (offset) changes. + scope.$watch(function() { return monthBodyCtrl.offset; }, function(offset) { + if (angular.isNumber(offset)) { + monthBodyCtrl.generateContent(); + } + }); + } + }; + } + + /** + * Controller for a single calendar month. + * @ngInject @constructor + */ + function CalendarMonthBodyCtrl($element, $$mdDateUtil, $mdDateLocale) { + /** @final {!angular.JQLite} */ + this.$element = $element; + + /** @final */ + this.dateUtil = $$mdDateUtil; + + /** @final */ + this.dateLocale = $mdDateLocale; + + /** @type {Object} Reference to the month view. */ + this.monthCtrl = null; + + /** @type {Object} Reference to the calendar. */ + this.calendarCtrl = null; + + /** + * Number of months from the start of the month "items" that the currently rendered month + * occurs. Set via angular data binding. + * @type {number} + */ + this.offset = null; + + /** + * Date cell to focus after appending the month to the document. + * @type {HTMLElement} + */ + this.focusAfterAppend = null; + } + + /** Generate and append the content for this month to the directive element. */ + CalendarMonthBodyCtrl.prototype.generateContent = function() { + var date = this.dateUtil.incrementMonths(this.calendarCtrl.firstRenderableDate, this.offset); + + this.$element + .empty() + .append(this.buildCalendarForMonth(date)); + + if (this.focusAfterAppend) { + this.focusAfterAppend.classList.add(this.calendarCtrl.FOCUSED_DATE_CLASS); + this.focusAfterAppend.focus(); + this.focusAfterAppend = null; + } + }; + + /** + * Creates a single cell to contain a date in the calendar with all appropriate + * attributes and classes added. If a date is given, the cell content will be set + * based on the date. + * @param {Date=} opt_date + * @returns {HTMLElement} + */ + CalendarMonthBodyCtrl.prototype.buildDateCell = function(opt_date) { + var monthCtrl = this.monthCtrl; + var calendarCtrl = this.calendarCtrl; + + // TODO(jelbourn): cloneNode is likely a faster way of doing this. + var cell = document.createElement('td'); + cell.tabIndex = -1; + cell.classList.add('md-calendar-date'); + cell.setAttribute('role', 'gridcell'); + + if (opt_date) { + cell.setAttribute('tabindex', '-1'); + cell.setAttribute('aria-label', this.dateLocale.longDateFormatter(opt_date)); + cell.id = calendarCtrl.getDateId(opt_date, 'month'); + + // Use `data-timestamp` attribute because IE10 does not support the `dataset` property. + cell.setAttribute('data-timestamp', opt_date.getTime()); + + // TODO(jelourn): Doing these comparisons for class addition during generation might be slow. + // It may be better to finish the construction and then query the node and add the class. + if (this.dateUtil.isSameDay(opt_date, calendarCtrl.today)) { + cell.classList.add(calendarCtrl.TODAY_CLASS); + } + + if (this.dateUtil.isValidDate(calendarCtrl.selectedDate) && + this.dateUtil.isSameDay(opt_date, calendarCtrl.selectedDate)) { + cell.classList.add(calendarCtrl.SELECTED_DATE_CLASS); + cell.setAttribute('aria-selected', 'true'); + } + + var cellText = this.dateLocale.dates[opt_date.getDate()]; + + if (this.isDateEnabled(opt_date)) { + // Add a indicator for select, hover, and focus states. + var selectionIndicator = document.createElement('span'); + selectionIndicator.classList.add('md-calendar-date-selection-indicator'); + selectionIndicator.textContent = cellText; + cell.appendChild(selectionIndicator); + cell.addEventListener('click', monthCtrl.cellClickHandler); + + if (calendarCtrl.displayDate && this.dateUtil.isSameDay(opt_date, calendarCtrl.displayDate)) { + this.focusAfterAppend = cell; + } + } else { + cell.classList.add('md-calendar-date-disabled'); + cell.textContent = cellText; + } + } + + return cell; + }; + + /** + * Check whether date is in range and enabled + * @param {Date=} opt_date + * @return {boolean} Whether the date is enabled. + */ + CalendarMonthBodyCtrl.prototype.isDateEnabled = function(opt_date) { + return this.dateUtil.isDateWithinRange(opt_date, + this.calendarCtrl.minDate, this.calendarCtrl.maxDate) && + (!angular.isFunction(this.calendarCtrl.dateFilter) + || this.calendarCtrl.dateFilter(opt_date)); + }; + + /** + * Builds a `tr` element for the calendar grid. + * @param rowNumber The week number within the month. + * @returns {HTMLElement} + */ + CalendarMonthBodyCtrl.prototype.buildDateRow = function(rowNumber) { + var row = document.createElement('tr'); + row.setAttribute('role', 'row'); + + // Because of an NVDA bug (with Firefox), the row needs an aria-label in order + // to prevent the entire row being read aloud when the user moves between rows. + // See http://community.nvda-project.org/ticket/4643. + row.setAttribute('aria-label', this.dateLocale.weekNumberFormatter(rowNumber)); + + return row; + }; + + /** + * Builds the content for the given date's month. + * @param {Date=} opt_dateInMonth + * @returns {DocumentFragment} A document fragment containing the elements. + */ + CalendarMonthBodyCtrl.prototype.buildCalendarForMonth = function(opt_dateInMonth) { + var date = this.dateUtil.isValidDate(opt_dateInMonth) ? opt_dateInMonth : new Date(); + + var firstDayOfMonth = this.dateUtil.getFirstDateOfMonth(date); + var firstDayOfTheWeek = this.getLocaleDay_(firstDayOfMonth); + var numberOfDaysInMonth = this.dateUtil.getNumberOfDaysInMonth(date); + + // Store rows for the month in a document fragment so that we can append them all at once. + var monthBody = document.createDocumentFragment(); + + var rowNumber = 1; + var row = this.buildDateRow(rowNumber); + monthBody.appendChild(row); + + // If this is the final month in the list of items, only the first week should render, + // so we should return immediately after the first row is complete and has been + // attached to the body. + var isFinalMonth = this.offset === this.monthCtrl.items.length - 1; + + // Add a label for the month. If the month starts on a Sun/Mon/Tues, the month label + // goes on a row above the first of the month. Otherwise, the month label takes up the first + // two cells of the first row. + var blankCellOffset = 0; + var monthLabelCell = document.createElement('td'); + var monthLabelCellContent = document.createElement('span'); + var calendarCtrl = this.calendarCtrl; + + monthLabelCellContent.textContent = this.dateLocale.monthHeaderFormatter(date); + monthLabelCell.appendChild(monthLabelCellContent); + monthLabelCell.classList.add('md-calendar-month-label'); + // If the entire month is after the max date, render the label as a disabled state. + if (calendarCtrl.maxDate && firstDayOfMonth > calendarCtrl.maxDate) { + monthLabelCell.classList.add('md-calendar-month-label-disabled'); + // If the user isn't supposed to be able to change views, render the + // label as usual, but disable the clicking functionality. + } else if (!calendarCtrl.mode) { + monthLabelCell.addEventListener('click', this.monthCtrl.headerClickHandler); + monthLabelCell.setAttribute('data-timestamp', firstDayOfMonth.getTime()); + monthLabelCell.setAttribute('aria-label', this.dateLocale.monthFormatter(date)); + monthLabelCell.classList.add('md-calendar-label-clickable'); + monthLabelCell.appendChild(this.arrowIcon.cloneNode(true)); + } + + if (firstDayOfTheWeek <= 2) { + monthLabelCell.setAttribute('colspan', '7'); + + var monthLabelRow = this.buildDateRow(); + monthLabelRow.appendChild(monthLabelCell); + monthBody.insertBefore(monthLabelRow, row); + + if (isFinalMonth) { + return monthBody; + } + } else { + blankCellOffset = 3; + monthLabelCell.setAttribute('colspan', '3'); + row.appendChild(monthLabelCell); + } + + // Add a blank cell for each day of the week that occurs before the first of the month. + // For example, if the first day of the month is a Tuesday, add blank cells for Sun and Mon. + // The blankCellOffset is needed in cases where the first N cells are used by the month label. + for (var i = blankCellOffset; i < firstDayOfTheWeek; i++) { + row.appendChild(this.buildDateCell()); + } + + // Add a cell for each day of the month, keeping track of the day of the week so that + // we know when to start a new row. + var dayOfWeek = firstDayOfTheWeek; + var iterationDate = firstDayOfMonth; + for (var d = 1; d <= numberOfDaysInMonth; d++) { + // If we've reached the end of the week, start a new row. + if (dayOfWeek === 7) { + // We've finished the first row, so we're done if this is the final month. + if (isFinalMonth) { + return monthBody; + } + dayOfWeek = 0; + rowNumber++; + row = this.buildDateRow(rowNumber); + monthBody.appendChild(row); + } + + iterationDate.setDate(d); + var cell = this.buildDateCell(iterationDate); + row.appendChild(cell); + + dayOfWeek++; + } + + // Ensure that the last row of the month has 7 cells. + while (row.childNodes.length < 7) { + row.appendChild(this.buildDateCell()); + } + + // Ensure that all months have 6 rows. This is necessary for now because the virtual-repeat + // requires that all items have exactly the same height. + while (monthBody.childNodes.length < 6) { + var whitespaceRow = this.buildDateRow(); + for (var j = 0; j < 7; j++) { + whitespaceRow.appendChild(this.buildDateCell()); + } + monthBody.appendChild(whitespaceRow); + } + + return monthBody; + }; + + /** + * Gets the day-of-the-week index for a date for the current locale. + * @private + * @param {Date} date + * @returns {number} The column index of the date in the calendar. + */ + CalendarMonthBodyCtrl.prototype.getLocaleDay_ = function(date) { + return (date.getDay() + (7 - this.dateLocale.firstDayOfWeek)) % 7; + }; +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + CalendarYearCtrl.$inject = ["$element", "$scope", "$animate", "$q", "$$mdDateUtil", "$mdUtil"]; + angular.module('material.components.datepicker') + .directive('mdCalendarYear', calendarDirective); + + /** + * Height of one calendar year tbody. This must be made known to the virtual-repeat and is + * subsequently used for scrolling to specific years. + */ + var TBODY_HEIGHT = 88; + + /** Private component, representing a list of years in the calendar. */ + function calendarDirective() { + return { + template: + '
    ' + + '' + + '' + + '' + + // The ensures that the will have the proper + // height, even though it may be empty. + '' + + '' + + '
    ' + + '
    ' + + '
    ', + require: ['^^mdCalendar', 'mdCalendarYear'], + controller: CalendarYearCtrl, + controllerAs: 'yearCtrl', + bindToController: true, + link: function(scope, element, attrs, controllers) { + var calendarCtrl = controllers[0]; + var yearCtrl = controllers[1]; + yearCtrl.initialize(calendarCtrl); + } + }; + } + + /** + * Controller for the mdCalendar component. + * @ngInject @constructor + */ + function CalendarYearCtrl($element, $scope, $animate, $q, + $$mdDateUtil, $mdUtil) { + + /** @final {!angular.JQLite} */ + this.$element = $element; + + /** @final {!angular.Scope} */ + this.$scope = $scope; + + /** @final {!angular.$animate} */ + this.$animate = $animate; + + /** @final {!angular.$q} */ + this.$q = $q; + + /** @final */ + this.dateUtil = $$mdDateUtil; + + /** @final {HTMLElement} */ + this.calendarScroller = $element[0].querySelector('.md-virtual-repeat-scroller'); + + /** @type {boolean} */ + this.isInitialized = false; + + /** @type {boolean} */ + this.isMonthTransitionInProgress = false; + + /** @final */ + this.$mdUtil = $mdUtil; + + var self = this; + + /** + * Handles a click event on a date cell. + * Created here so that every cell can use the same function instance. + * @this {HTMLTableCellElement} The cell that was clicked. + */ + this.cellClickHandler = function() { + self.onTimestampSelected($$mdDateUtil.getTimestampFromNode(this)); + }; + } + + /** + * Initialize the controller by saving a reference to the calendar and + * setting up the object that will be iterated by the virtual repeater. + */ + CalendarYearCtrl.prototype.initialize = function(calendarCtrl) { + /** + * Dummy array-like object for virtual-repeat to iterate over. The length is the total + * number of years that can be viewed. We add 1 extra in order to include the current year. + */ + + this.items = { + length: this.dateUtil.getYearDistance( + calendarCtrl.firstRenderableDate, + calendarCtrl.lastRenderableDate + ) + 1 + }; + + this.calendarCtrl = calendarCtrl; + this.attachScopeListeners(); + calendarCtrl.updateVirtualRepeat(); + + // Fire the initial render, since we might have missed it the first time it fired. + calendarCtrl.ngModelCtrl && calendarCtrl.ngModelCtrl.$render(); + }; + + /** + * Gets the "index" of the currently selected date as it would be in the virtual-repeat. + * @returns {number} + */ + CalendarYearCtrl.prototype.getFocusedYearIndex = function() { + var calendarCtrl = this.calendarCtrl; + + return this.dateUtil.getYearDistance( + calendarCtrl.firstRenderableDate, + calendarCtrl.displayDate || calendarCtrl.selectedDate || calendarCtrl.today + ); + }; + + /** + * Change the date that is highlighted in the calendar. + * @param {Date} date + */ + CalendarYearCtrl.prototype.changeDate = function(date) { + // Initialization is deferred until this function is called because we want to reflect + // the starting value of ngModel. + if (!this.isInitialized) { + this.calendarCtrl.hideVerticalScrollbar(this); + this.isInitialized = true; + return this.$q.when(); + } else if (this.dateUtil.isValidDate(date) && !this.isMonthTransitionInProgress) { + var self = this; + var animationPromise = this.animateDateChange(date); + + self.isMonthTransitionInProgress = true; + self.calendarCtrl.displayDate = date; + + return animationPromise.then(function() { + self.isMonthTransitionInProgress = false; + }); + } + }; + + /** + * Animates the transition from the calendar's current month to the given month. + * @param {Date} date + * @returns {angular.$q.Promise} The animation promise. + */ + CalendarYearCtrl.prototype.animateDateChange = function(date) { + if (this.dateUtil.isValidDate(date)) { + var monthDistance = this.dateUtil.getYearDistance(this.calendarCtrl.firstRenderableDate, date); + this.calendarScroller.scrollTop = monthDistance * TBODY_HEIGHT; + } + + return this.$q.when(); + }; + + /** + * Handles the year-view-specific keyboard interactions. + * @param {Object} event Scope event object passed by the calendar. + * @param {String} action Action, corresponding to the key that was pressed. + */ + CalendarYearCtrl.prototype.handleKeyEvent = function(event, action) { + var self = this; + var calendarCtrl = self.calendarCtrl; + var displayDate = calendarCtrl.displayDate; + + if (action === 'select') { + self.changeDate(displayDate).then(function() { + self.onTimestampSelected(displayDate); + }); + } else { + var date = null; + var dateUtil = self.dateUtil; + + switch (action) { + case 'move-right': date = dateUtil.incrementMonths(displayDate, 1); break; + case 'move-left': date = dateUtil.incrementMonths(displayDate, -1); break; + + case 'move-row-down': date = dateUtil.incrementMonths(displayDate, 6); break; + case 'move-row-up': date = dateUtil.incrementMonths(displayDate, -6); break; + } + + if (date) { + var min = calendarCtrl.minDate ? dateUtil.getFirstDateOfMonth(calendarCtrl.minDate) : null; + var max = calendarCtrl.maxDate ? dateUtil.getFirstDateOfMonth(calendarCtrl.maxDate) : null; + date = dateUtil.getFirstDateOfMonth(self.dateUtil.clampDate(date, min, max)); + + self.changeDate(date).then(function() { + calendarCtrl.focus(date); + }); + } + } + }; + + /** + * Attaches listeners for the scope events that are broadcast by the calendar. + */ + CalendarYearCtrl.prototype.attachScopeListeners = function() { + var self = this; + + self.$scope.$on('md-calendar-parent-changed', function(event, value) { + self.calendarCtrl.changeSelectedDate(value ? self.dateUtil.getFirstDateOfMonth(value) : value); + self.changeDate(value); + }); + + self.$scope.$on('md-calendar-parent-action', angular.bind(self, self.handleKeyEvent)); + }; + + /** + * Handles the behavior when a date is selected. Depending on the `mode` + * of the calendar, this can either switch back to the calendar view or + * set the model value. + * @param {number} timestamp The selected timestamp. + */ + CalendarYearCtrl.prototype.onTimestampSelected = function(timestamp) { + var calendarCtrl = this.calendarCtrl; + + if (calendarCtrl.mode) { + this.$mdUtil.nextTick(function() { + calendarCtrl.setNgModelValue(timestamp); + }); + } else { + calendarCtrl.setCurrentView('month', timestamp); + } + }; +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + CalendarYearBodyCtrl.$inject = ["$element", "$$mdDateUtil", "$mdDateLocale"]; + angular.module('material.components.datepicker') + .directive('mdCalendarYearBody', mdCalendarYearDirective); + + /** + * Private component, consumed by the md-calendar-year, which separates the DOM construction logic + * and allows for the year view to use md-virtual-repeat. + */ + function mdCalendarYearDirective() { + return { + require: ['^^mdCalendar', '^^mdCalendarYear', 'mdCalendarYearBody'], + scope: { offset: '=mdYearOffset' }, + controller: CalendarYearBodyCtrl, + controllerAs: 'mdYearBodyCtrl', + bindToController: true, + link: function(scope, element, attrs, controllers) { + var calendarCtrl = controllers[0]; + var yearCtrl = controllers[1]; + var yearBodyCtrl = controllers[2]; + + yearBodyCtrl.calendarCtrl = calendarCtrl; + yearBodyCtrl.yearCtrl = yearCtrl; + + scope.$watch(function() { return yearBodyCtrl.offset; }, function(offset) { + if (angular.isNumber(offset)) { + yearBodyCtrl.generateContent(); + } + }); + } + }; + } + + /** + * Controller for a single year. + * @ngInject @constructor + */ + function CalendarYearBodyCtrl($element, $$mdDateUtil, $mdDateLocale) { + /** @final {!angular.JQLite} */ + this.$element = $element; + + /** @final */ + this.dateUtil = $$mdDateUtil; + + /** @final */ + this.dateLocale = $mdDateLocale; + + /** @type {Object} Reference to the calendar. */ + this.calendarCtrl = null; + + /** @type {Object} Reference to the year view. */ + this.yearCtrl = null; + + /** + * Number of months from the start of the month "items" that the currently rendered month + * occurs. Set via angular data binding. + * @type {number} + */ + this.offset = null; + + /** + * Date cell to focus after appending the month to the document. + * @type {HTMLElement} + */ + this.focusAfterAppend = null; + } + + /** Generate and append the content for this year to the directive element. */ + CalendarYearBodyCtrl.prototype.generateContent = function() { + var date = this.dateUtil.incrementYears(this.calendarCtrl.firstRenderableDate, this.offset); + + this.$element + .empty() + .append(this.buildCalendarForYear(date)); + + if (this.focusAfterAppend) { + this.focusAfterAppend.classList.add(this.calendarCtrl.FOCUSED_DATE_CLASS); + this.focusAfterAppend.focus(); + this.focusAfterAppend = null; + } + }; + + /** + * Creates a single cell to contain a year in the calendar. + * @param {number} year Four-digit year. + * @param {number} month Zero-indexed month. + * @returns {HTMLElement} + */ + CalendarYearBodyCtrl.prototype.buildMonthCell = function(year, month) { + var calendarCtrl = this.calendarCtrl; + var yearCtrl = this.yearCtrl; + var cell = this.buildBlankCell(); + + // Represent this month/year as a date. + var firstOfMonth = new Date(year, month, 1); + cell.setAttribute('aria-label', this.dateLocale.monthFormatter(firstOfMonth)); + cell.id = calendarCtrl.getDateId(firstOfMonth, 'year'); + + // Use `data-timestamp` attribute because IE10 does not support the `dataset` property. + cell.setAttribute('data-timestamp', String(firstOfMonth.getTime())); + + if (this.dateUtil.isSameMonthAndYear(firstOfMonth, calendarCtrl.today)) { + cell.classList.add(calendarCtrl.TODAY_CLASS); + } + + if (this.dateUtil.isValidDate(calendarCtrl.selectedDate) && + this.dateUtil.isSameMonthAndYear(firstOfMonth, calendarCtrl.selectedDate)) { + cell.classList.add(calendarCtrl.SELECTED_DATE_CLASS); + cell.setAttribute('aria-selected', 'true'); + } + + var cellText = this.dateLocale.shortMonths[month]; + + if (this.dateUtil.isMonthWithinRange( + firstOfMonth, calendarCtrl.minDate, calendarCtrl.maxDate) && + (!angular.isFunction(this.calendarCtrl.dateFilter) || + this.calendarCtrl.dateFilter(firstOfMonth))) { + var selectionIndicator = document.createElement('span'); + selectionIndicator.classList.add('md-calendar-date-selection-indicator'); + selectionIndicator.textContent = cellText; + cell.appendChild(selectionIndicator); + cell.addEventListener('click', yearCtrl.cellClickHandler); + + if (calendarCtrl.displayDate && + this.dateUtil.isSameMonthAndYear(firstOfMonth, calendarCtrl.displayDate)) { + this.focusAfterAppend = cell; + } + } else { + cell.classList.add('md-calendar-date-disabled'); + cell.textContent = cellText; + } + + return cell; + }; + + /** + * Builds a blank cell. + * @return {HTMLElement} + */ + CalendarYearBodyCtrl.prototype.buildBlankCell = function() { + var cell = document.createElement('td'); + cell.tabIndex = -1; + cell.classList.add('md-calendar-date'); + cell.setAttribute('role', 'gridcell'); + + cell.setAttribute('tabindex', '-1'); + return cell; + }; + + /** + * Builds the content for the given year. + * @param {Date} date Date for which the content should be built. + * @returns {DocumentFragment} A document fragment containing the months within the year. + */ + CalendarYearBodyCtrl.prototype.buildCalendarForYear = function(date) { + // Store rows for the month in a document fragment so that we can append them all at once. + var year = date.getFullYear(); + var yearBody = document.createDocumentFragment(); + + var monthCell, i; + // First row contains label and Jan-Jun. + var firstRow = document.createElement('tr'); + var labelCell = document.createElement('td'); + labelCell.className = 'md-calendar-month-label'; + labelCell.textContent = year; + firstRow.appendChild(labelCell); + + for (i = 0; i < 6; i++) { + firstRow.appendChild(this.buildMonthCell(year, i)); + } + yearBody.appendChild(firstRow); + + // Second row contains a blank cell and Jul-Dec. + var secondRow = document.createElement('tr'); + secondRow.appendChild(this.buildBlankCell()); + for (i = 6; i < 12; i++) { + secondRow.appendChild(this.buildMonthCell(year, i)); + } + yearBody.appendChild(secondRow); + + return yearBody; + }; +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + /** + * @ngdoc service + * @name $mdDateLocaleProvider + * @module material.components.datepicker + * + * @description + * The `$mdDateLocaleProvider` is the provider that creates the `$mdDateLocale` service. + * This provider that allows the user to specify messages, formatters, and parsers for date + * internationalization. The `$mdDateLocale` service itself is consumed by AngularJS Material + * components that deal with dates (i.e. {@link api/directive/mdDatepicker mdDatepicker}). + * + * @property {Array} months Array of month names (in order). + * @property {Array} shortMonths Array of abbreviated month names. + * @property {Array} days Array of the days of the week (in order). + * @property {Array} shortDays Array of abbreviated days of the week. + * @property {Array} dates Array of dates of the month. Only necessary for locales + * using a numeral system other than [1, 2, 3...]. + * @property {Array} firstDayOfWeek The first day of the week. Sunday = 0, Monday = 1, + * etc. + * @property {function(string): Date} parseDate Function that converts a date string to a Date + * object (the date portion). + * @property {function(Date, string): string} formatDate Function to format a date object to a + * string. The datepicker directive also provides the time zone, if it was specified. + * @property {function(Date): string} monthHeaderFormatter Function that returns the label for + * a month given a date. + * @property {function(Date): string} monthFormatter Function that returns the full name of a month + * for a given date. + * @property {function(number): string} weekNumberFormatter Function that returns a label for + * a week given the week number. + * @property {function(Date): string} longDateFormatter Function that formats a date into a long + * `aria-label` that is read by the screen reader when the focused date changes. + * @property {string} msgCalendar Translation of the label "Calendar" for the current locale. + * @property {string} msgOpenCalendar Translation of the button label "Open calendar" for the + * current locale. + * @property {Date} firstRenderableDate The date from which the datepicker calendar will begin + * rendering. Note that this will be ignored if a minimum date is set. + * Defaults to January 1st 1880. + * @property {Date} lastRenderableDate The last date that will be rendered by the datepicker + * calendar. Note that this will be ignored if a maximum date is set. + * Defaults to January 1st 2130. + * @property {function(string): boolean} isDateComplete Function to determine whether a string + * makes sense to be parsed to a `Date` object. Returns `true` if the date appears to be complete + * and parsing should occur. By default, this checks for 3 groups of text or numbers separated + * by delimiters. This means that by default, date strings must include a month, day, and year + * to be parsed and for the model to be updated. + * + * @usage + * + * myAppModule.config(function($mdDateLocaleProvider) { + * + * // Example of a French localization. + * $mdDateLocaleProvider.months = ['janvier', 'février', 'mars', ...]; + * $mdDateLocaleProvider.shortMonths = ['janv', 'févr', 'mars', ...]; + * $mdDateLocaleProvider.days = ['dimanche', 'lundi', 'mardi', ...]; + * $mdDateLocaleProvider.shortDays = ['Di', 'Lu', 'Ma', ...]; + * + * // Can change week display to start on Monday. + * $mdDateLocaleProvider.firstDayOfWeek = 1; + * + * // Optional. + * $mdDateLocaleProvider.dates = [1, 2, 3, 4, 5, 6, ...]; + * + * // Example uses moment.js to parse and format dates. + * $mdDateLocaleProvider.parseDate = function(dateString) { + * var m = moment(dateString, 'L', true); + * return m.isValid() ? m.toDate() : new Date(NaN); + * }; + * + * $mdDateLocaleProvider.formatDate = function(date) { + * var m = moment(date); + * return m.isValid() ? m.format('L') : ''; + * }; + * + * // Allow only a day and month to be specified. + * // This is required if using the 'M/D' format with moment.js. + * $mdDateLocaleProvider.isDateComplete = function(dateString) { + * dateString = dateString.trim(); + * + * // Look for two chunks of content (either numbers or text) separated by delimiters. + * var re = /^(([a-zA-Z]{3,}|[0-9]{1,4})([ .,]+|[/-]))([a-zA-Z]{3,}|[0-9]{1,4})/; + * return re.test(dateString); + * }; + * + * $mdDateLocaleProvider.monthHeaderFormatter = function(date) { + * return myShortMonths[date.getMonth()] + ' ' + date.getFullYear(); + * }; + * + * // In addition to date display, date components also need localized messages + * // for aria-labels for screen-reader users. + * + * $mdDateLocaleProvider.weekNumberFormatter = function(weekNumber) { + * return 'Semaine ' + weekNumber; + * }; + * + * $mdDateLocaleProvider.msgCalendar = 'Calendrier'; + * $mdDateLocaleProvider.msgOpenCalendar = 'Ouvrir le calendrier'; + * + * // You can also set when your calendar begins and ends. + * $mdDateLocaleProvider.firstRenderableDate = new Date(1776, 6, 4); + * $mdDateLocaleProvider.lastRenderableDate = new Date(2012, 11, 21); + * }); + * + * + */ + angular.module('material.components.datepicker').config(["$provide", function($provide) { + // TODO(jelbourn): Assert provided values are correctly formatted. Need assertions. + + /** @constructor */ + function DateLocaleProvider() { + /** Array of full month names. E.g., ['January', 'February', ...] */ + this.months = null; + + /** Array of abbreviated month names. E.g., ['Jan', 'Feb', ...] */ + this.shortMonths = null; + + /** Array of full day of the week names. E.g., ['Monday', 'Tuesday', ...] */ + this.days = null; + + /** Array of abbreviated dat of the week names. E.g., ['M', 'T', ...] */ + this.shortDays = null; + + /** Array of dates of a month (1 - 31). Characters might be different in some locales. */ + this.dates = null; + + /** Index of the first day of the week. 0 = Sunday, 1 = Monday, etc. */ + this.firstDayOfWeek = 0; + + /** + * Function that converts the date portion of a Date to a string. + * @type {(function(Date): string)} + */ + this.formatDate = null; + + /** + * Function that converts a date string to a Date object (the date portion) + * @type {function(string): Date} + */ + this.parseDate = null; + + /** + * Function that formats a Date into a month header string. + * @type {function(Date): string} + */ + this.monthHeaderFormatter = null; + + /** + * Function that formats a week number into a label for the week. + * @type {function(number): string} + */ + this.weekNumberFormatter = null; + + /** + * Function that formats a date into a long aria-label that is read + * when the focused date changes. + * @type {function(Date): string} + */ + this.longDateFormatter = null; + + /** + * Function to determine whether a string makes sense to be + * parsed to a Date object. + * @type {function(string): boolean} + */ + this.isDateComplete = null; + + /** + * ARIA label for the calendar "dialog" used in the datepicker. + * @type {string} + */ + this.msgCalendar = ''; + + /** + * ARIA label for the datepicker's "Open calendar" buttons. + * @type {string} + */ + this.msgOpenCalendar = ''; + } + + /** + * Factory function that returns an instance of the dateLocale service. + * @ngInject + * @param $locale + * @returns {DateLocale} + */ + DateLocaleProvider.prototype.$get = function($locale, $filter) { + /** + * Default date-to-string formatting function. + * @param {!Date} date + * @param {string=} timezone + * @returns {string} + */ + function defaultFormatDate(date, timezone) { + if (!date) { + return ''; + } + + // All of the dates created through ng-material *should* be set to midnight. + // If we encounter a date where the localeTime shows at 11pm instead of midnight, + // we have run into an issue with DST where we need to increment the hour by one: + // var d = new Date(1992, 9, 8, 0, 0, 0); + // d.toLocaleString(); // == "10/7/1992, 11:00:00 PM" + var localeTime = date.toLocaleTimeString(); + var formatDate = date; + if (date.getHours() === 0 && + (localeTime.indexOf('11:') !== -1 || localeTime.indexOf('23:') !== -1)) { + formatDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 1, 0, 0); + } + + return $filter('date')(formatDate, 'M/d/yyyy', timezone); + } + + /** + * Default string-to-date parsing function. + * @param {string} dateString + * @returns {!Date} + */ + function defaultParseDate(dateString) { + return new Date(dateString); + } + + /** + * Default function to determine whether a string makes sense to be + * parsed to a Date object. + * + * This is very permissive and is just a basic sanity check to ensure that + * things like single integers aren't able to be parsed into dates. + * @param {string} dateString + * @returns {boolean} + */ + function defaultIsDateComplete(dateString) { + dateString = dateString.trim(); + + // Looks for three chunks of content (either numbers or text) separated + // by delimiters. + var re = /^(([a-zA-Z]{3,}|[0-9]{1,4})([ .,]+|[/-])){2}([a-zA-Z]{3,}|[0-9]{1,4})$/; + return re.test(dateString); + } + + /** + * Default date-to-string formatter to get a month header. + * @param {!Date} date + * @returns {string} + */ + function defaultMonthHeaderFormatter(date) { + return service.shortMonths[date.getMonth()] + ' ' + date.getFullYear(); + } + + /** + * Default formatter for a month. + * @param {!Date} date + * @returns {string} + */ + function defaultMonthFormatter(date) { + return service.months[date.getMonth()] + ' ' + date.getFullYear(); + } + + /** + * Default week number formatter. + * @param number + * @returns {string} + */ + function defaultWeekNumberFormatter(number) { + return 'Week ' + number; + } + + /** + * Default formatter for date cell aria-labels. + * @param {!Date} date + * @returns {string} + */ + function defaultLongDateFormatter(date) { + // Example: 'Thursday June 18 2015' + return [ + service.days[date.getDay()], + service.months[date.getMonth()], + service.dates[date.getDate()], + date.getFullYear() + ].join(' '); + } + + // The default "short" day strings are the first character of each day, + // e.g., "Monday" => "M". + var defaultShortDays = $locale.DATETIME_FORMATS.SHORTDAY.map(function(day) { + return day.substring(0, 1); + }); + + // The default dates are simply the numbers 1 through 31. + var defaultDates = Array(32); + for (var i = 1; i <= 31; i++) { + defaultDates[i] = i; + } + + // Default ARIA messages are in English (US). + var defaultMsgCalendar = 'Calendar'; + var defaultMsgOpenCalendar = 'Open calendar'; + + // Default start/end dates that are rendered in the calendar. + var defaultFirstRenderableDate = new Date(1880, 0, 1); + var defaultLastRendereableDate = new Date(defaultFirstRenderableDate.getFullYear() + 250, 0, 1); + + var service = { + months: this.months || $locale.DATETIME_FORMATS.MONTH, + shortMonths: this.shortMonths || $locale.DATETIME_FORMATS.SHORTMONTH, + days: this.days || $locale.DATETIME_FORMATS.DAY, + shortDays: this.shortDays || defaultShortDays, + dates: this.dates || defaultDates, + firstDayOfWeek: this.firstDayOfWeek || 0, + formatDate: this.formatDate || defaultFormatDate, + parseDate: this.parseDate || defaultParseDate, + isDateComplete: this.isDateComplete || defaultIsDateComplete, + monthHeaderFormatter: this.monthHeaderFormatter || defaultMonthHeaderFormatter, + monthFormatter: this.monthFormatter || defaultMonthFormatter, + weekNumberFormatter: this.weekNumberFormatter || defaultWeekNumberFormatter, + longDateFormatter: this.longDateFormatter || defaultLongDateFormatter, + msgCalendar: this.msgCalendar || defaultMsgCalendar, + msgOpenCalendar: this.msgOpenCalendar || defaultMsgOpenCalendar, + firstRenderableDate: this.firstRenderableDate || defaultFirstRenderableDate, + lastRenderableDate: this.lastRenderableDate || defaultLastRendereableDate + }; + + return service; + }; + DateLocaleProvider.prototype.$get.$inject = ["$locale", "$filter"]; + + $provide.provider('$mdDateLocale', new DateLocaleProvider()); + }]); +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + /** + * Utility for performing date calculations to facilitate operation of the calendar and + * datepicker. + */ + angular.module('material.components.datepicker').factory('$$mdDateUtil', function() { + return { + getFirstDateOfMonth: getFirstDateOfMonth, + getNumberOfDaysInMonth: getNumberOfDaysInMonth, + getDateInNextMonth: getDateInNextMonth, + getDateInPreviousMonth: getDateInPreviousMonth, + isInNextMonth: isInNextMonth, + isInPreviousMonth: isInPreviousMonth, + getDateMidpoint: getDateMidpoint, + isSameMonthAndYear: isSameMonthAndYear, + getWeekOfMonth: getWeekOfMonth, + incrementDays: incrementDays, + incrementMonths: incrementMonths, + getLastDateOfMonth: getLastDateOfMonth, + isSameDay: isSameDay, + getMonthDistance: getMonthDistance, + isValidDate: isValidDate, + setDateTimeToMidnight: setDateTimeToMidnight, + createDateAtMidnight: createDateAtMidnight, + isDateWithinRange: isDateWithinRange, + incrementYears: incrementYears, + getYearDistance: getYearDistance, + clampDate: clampDate, + getTimestampFromNode: getTimestampFromNode, + isMonthWithinRange: isMonthWithinRange + }; + + /** + * Gets the first day of the month for the given date's month. + * @param {Date} date + * @returns {Date} + */ + function getFirstDateOfMonth(date) { + return new Date(date.getFullYear(), date.getMonth(), 1); + } + + /** + * Gets the number of days in the month for the given date's month. + * @param date + * @returns {number} + */ + function getNumberOfDaysInMonth(date) { + return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); + } + + /** + * Get an arbitrary date in the month after the given date's month. + * @param date + * @returns {Date} + */ + function getDateInNextMonth(date) { + return new Date(date.getFullYear(), date.getMonth() + 1, 1); + } + + /** + * Get an arbitrary date in the month before the given date's month. + * @param date + * @returns {Date} + */ + function getDateInPreviousMonth(date) { + return new Date(date.getFullYear(), date.getMonth() - 1, 1); + } + + /** + * Gets whether two dates have the same month and year. + * @param {Date} d1 + * @param {Date} d2 + * @returns {boolean} + */ + function isSameMonthAndYear(d1, d2) { + return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth(); + } + + /** + * Gets whether two dates are the same day (not not necesarily the same time). + * @param {Date} d1 + * @param {Date} d2 + * @returns {boolean} + */ + function isSameDay(d1, d2) { + return d1.getDate() == d2.getDate() && isSameMonthAndYear(d1, d2); + } + + /** + * Gets whether a date is in the month immediately after some date. + * @param {Date} startDate The date from which to compare. + * @param {Date} endDate The date to check. + * @returns {boolean} + */ + function isInNextMonth(startDate, endDate) { + var nextMonth = getDateInNextMonth(startDate); + return isSameMonthAndYear(nextMonth, endDate); + } + + /** + * Gets whether a date is in the month immediately before some date. + * @param {Date} startDate The date from which to compare. + * @param {Date} endDate The date to check. + * @returns {boolean} + */ + function isInPreviousMonth(startDate, endDate) { + var previousMonth = getDateInPreviousMonth(startDate); + return isSameMonthAndYear(endDate, previousMonth); + } + + /** + * Gets the midpoint between two dates. + * @param {Date} d1 + * @param {Date} d2 + * @returns {Date} + */ + function getDateMidpoint(d1, d2) { + return createDateAtMidnight((d1.getTime() + d2.getTime()) / 2); + } + + /** + * Gets the week of the month that a given date occurs in. + * @param {Date} date + * @returns {number} Index of the week of the month (zero-based). + */ + function getWeekOfMonth(date) { + var firstDayOfMonth = getFirstDateOfMonth(date); + return Math.floor((firstDayOfMonth.getDay() + date.getDate() - 1) / 7); + } + + /** + * Gets a new date incremented by the given number of days. Number of days can be negative. + * @param {Date} date + * @param {number} numberOfDays + * @returns {Date} + */ + function incrementDays(date, numberOfDays) { + return new Date(date.getFullYear(), date.getMonth(), date.getDate() + numberOfDays); + } + + /** + * Gets a new date incremented by the given number of months. Number of months can be negative. + * If the date of the given month does not match the target month, the date will be set to the + * last day of the month. + * @param {Date} date + * @param {number} numberOfMonths + * @returns {Date} + */ + function incrementMonths(date, numberOfMonths) { + // If the same date in the target month does not actually exist, the Date object will + // automatically advance *another* month by the number of missing days. + // For example, if you try to go from Jan. 30 to Feb. 30, you'll end up on March 2. + // So, we check if the month overflowed and go to the last day of the target month instead. + var dateInTargetMonth = new Date(date.getFullYear(), date.getMonth() + numberOfMonths, 1); + var numberOfDaysInMonth = getNumberOfDaysInMonth(dateInTargetMonth); + if (numberOfDaysInMonth < date.getDate()) { + dateInTargetMonth.setDate(numberOfDaysInMonth); + } else { + dateInTargetMonth.setDate(date.getDate()); + } + + return dateInTargetMonth; + } + + /** + * Get the integer distance between two months. This *only* considers the month and year + * portion of the Date instances. + * + * @param {Date} start + * @param {Date} end + * @returns {number} Number of months between `start` and `end`. If `end` is before `start` + * chronologically, this number will be negative. + */ + function getMonthDistance(start, end) { + return (12 * (end.getFullYear() - start.getFullYear())) + (end.getMonth() - start.getMonth()); + } + + /** + * Gets the last day of the month for the given date. + * @param {Date} date + * @returns {Date} + */ + function getLastDateOfMonth(date) { + return new Date(date.getFullYear(), date.getMonth(), getNumberOfDaysInMonth(date)); + } + + /** + * Checks whether a date is valid. + * @param {Date} date + * @return {boolean} Whether the date is a valid Date. + */ + function isValidDate(date) { + return date && date.getTime && !isNaN(date.getTime()); + } + + /** + * Sets a date's time to midnight. + * @param {Date} date + */ + function setDateTimeToMidnight(date) { + if (isValidDate(date)) { + date.setHours(0, 0, 0, 0); + } + } + + /** + * Creates a date with the time set to midnight. + * Drop-in replacement for two forms of the Date constructor: + * 1. No argument for Date representing now. + * 2. Single-argument value representing number of seconds since Unix Epoch + * or a Date object. + * @param {number|Date=} opt_value + * @return {Date} New date with time set to midnight. + */ + function createDateAtMidnight(opt_value) { + var date; + if (angular.isUndefined(opt_value)) { + date = new Date(); + } else { + date = new Date(opt_value); + } + setDateTimeToMidnight(date); + return date; + } + + /** + * Checks if a date is within a min and max range, ignoring the time component. + * If minDate or maxDate are not dates, they are ignored. + * @param {Date} date + * @param {Date} minDate + * @param {Date} maxDate + */ + function isDateWithinRange(date, minDate, maxDate) { + var dateAtMidnight = createDateAtMidnight(date); + var minDateAtMidnight = isValidDate(minDate) ? createDateAtMidnight(minDate) : null; + var maxDateAtMidnight = isValidDate(maxDate) ? createDateAtMidnight(maxDate) : null; + return (!minDateAtMidnight || minDateAtMidnight <= dateAtMidnight) && + (!maxDateAtMidnight || maxDateAtMidnight >= dateAtMidnight); + } + + /** + * Gets a new date incremented by the given number of years. Number of years can be negative. + * See `incrementMonths` for notes on overflow for specific dates. + * @param {Date} date + * @param {number} numberOfYears + * @returns {Date} + */ + function incrementYears(date, numberOfYears) { + return incrementMonths(date, numberOfYears * 12); + } + + /** + * Get the integer distance between two years. This *only* considers the year portion of the + * Date instances. + * + * @param {Date} start + * @param {Date} end + * @returns {number} Number of months between `start` and `end`. If `end` is before `start` + * chronologically, this number will be negative. + */ + function getYearDistance(start, end) { + return end.getFullYear() - start.getFullYear(); + } + + /** + * Clamps a date between a minimum and a maximum date. + * @param {Date} date Date to be clamped + * @param {Date=} minDate Minimum date + * @param {Date=} maxDate Maximum date + * @return {Date} + */ + function clampDate(date, minDate, maxDate) { + var boundDate = date; + if (minDate && date < minDate) { + boundDate = new Date(minDate.getTime()); + } + if (maxDate && date > maxDate) { + boundDate = new Date(maxDate.getTime()); + } + return boundDate; + } + + /** + * Extracts and parses the timestamp from a DOM node. + * @param {HTMLElement} node Node from which the timestamp will be extracted. + * @return {number} Time since epoch. + */ + function getTimestampFromNode(node) { + if (node && node.hasAttribute('data-timestamp')) { + return Number(node.getAttribute('data-timestamp')); + } + } + + /** + * Checks if a month is within a min and max range, ignoring the date and time components. + * If minDate or maxDate are not dates, they are ignored. + * @param {Date} date + * @param {Date} minDate + * @param {Date} maxDate + */ + function isMonthWithinRange(date, minDate, maxDate) { + var month = date.getMonth(); + var year = date.getFullYear(); + + return (!minDate || minDate.getFullYear() < year || minDate.getMonth() <= month) && + (!maxDate || maxDate.getFullYear() > year || maxDate.getMonth() >= month); + } + }); +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + // TODO(jelbourn): forward more attributes to the internal input (required, autofocus, etc.) + // TODO(jelbourn): something better for mobile (calendar panel takes up entire screen?) + // TODO(jelbourn): input behavior (masking? auto-complete?) + + DatePickerCtrl.$inject = ["$scope", "$element", "$attrs", "$window", "$mdConstant", "$mdTheming", "$mdUtil", "$mdDateLocale", "$$mdDateUtil", "$$rAF", "$filter", "$timeout"]; + datePickerDirective.$inject = ["$$mdSvgRegistry", "$mdUtil", "$mdAria", "inputDirective"]; + angular.module('material.components.datepicker') + .directive('mdDatepicker', datePickerDirective); + + /** + * @ngdoc directive + * @name mdDatepicker + * @module material.components.datepicker + * + * @param {Date} ng-model The component's model. Expects either a JavaScript Date object or a + * value that can be parsed into one (e.g. a ISO 8601 string). + * @param {Object=} ng-model-options Allows tuning of the way in which `ng-model` is being + * updated. Also allows for a timezone to be specified. + * + * Read more at the ngModelOptions docs. + * @param {expression=} ng-change Expression evaluated when the model value changes. + * @param {expression=} ng-focus Expression evaluated when the input is focused or the calendar + * is opened. + * @param {expression=} ng-blur Expression evaluated when focus is removed from the input or the + * calendar is closed. + * @param {boolean=} ng-disabled Whether the datepicker is disabled. + * @param {boolean=} ng-required Whether a value is required for the datepicker. + * @param {Date=} md-min-date Expression representing a min date (inclusive). + * @param {Date=} md-max-date Expression representing a max date (inclusive). + * @param {(function(Date): boolean)=} md-date-filter Function expecting a date and returning a + * boolean whether it can be selected or not. + * @param {String=} md-placeholder The date input placeholder value. + * @param {String=} md-open-on-focus When present, the calendar will be opened when the input + * is focused. + * @param {Boolean=} md-is-open Expression that can be used to open the datepicker's calendar + * on-demand. + * @param {String=} md-current-view Default open view of the calendar pane. Can be either + * "month" or "year". + * @param {String=} md-mode Restricts the user to only selecting a value from a particular view. + * This option can be used if the user is only supposed to choose from a certain date type + * (e.g. only selecting the month). + * Can be either "month" or "day". **Note** that this will overwrite the `md-current-view` value. + * + * @param {String=} md-hide-icons Determines which datepicker icons should be hidden. Note that + * this may cause the datepicker to not align properly with other components. + * **Use at your own risk.** Possible values are: + * * `"all"` - Hides all icons. + * * `"calendar"` - Only hides the calendar icon. + * * `"triangle"` - Only hides the triangle icon. + * @param {Object=} md-date-locale Allows for the values from the `$mdDateLocaleProvider` to be + * ovewritten on a per-element basis (e.g. `msgOpenCalendar` can be overwritten with + * `md-date-locale="{ msgOpenCalendar: 'Open a special calendar' }"`). + * + * @description + * `` is a component used to select a single date. + * For information on how to configure internationalization for the date picker, + * see {@link api/service/$mdDateLocaleProvider $mdDateLocaleProvider}. + * + * This component supports + * [ngMessages](https://docs.angularjs.org/api/ngMessages/directive/ngMessages). + * Supported attributes are: + * * `required`: whether a required date is not set. + * * `mindate`: whether the selected date is before the minimum allowed date. + * * `maxdate`: whether the selected date is after the maximum allowed date. + * * `debounceInterval`: ms to delay input processing (since last debounce reset); + * default value 500ms + * + * @usage + * + * + * + * + */ + + function datePickerDirective($$mdSvgRegistry, $mdUtil, $mdAria, inputDirective) { + return { + template: function(tElement, tAttrs) { + // Buttons are not in the tab order because users can open the calendar via keyboard + // interaction on the text input, and multiple tab stops for one component (picker) + // may be confusing. + var hiddenIcons = tAttrs.mdHideIcons; + var ariaLabelValue = tAttrs.ariaLabel || tAttrs.mdPlaceholder; + + var calendarButton = (hiddenIcons === 'all' || hiddenIcons === 'calendar') ? '' : + ''; + + var triangleButton = ''; + + if (hiddenIcons !== 'all' && hiddenIcons !== 'triangle') { + triangleButton = '' + + '' + + '
    ' + + '
    '; + + tElement.addClass(HAS_TRIANGLE_ICON_CLASS); + } + + return calendarButton + + '
    ' + + ' ' + + triangleButton + + '
    ' + + + // This pane will be detached from here and re-attached to the document body. + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ' + + '' + + '' + + '
    ' + + '
    '; + }, + require: ['ngModel', 'mdDatepicker', '?^mdInputContainer', '?^form'], + scope: { + minDate: '=mdMinDate', + maxDate: '=mdMaxDate', + placeholder: '@mdPlaceholder', + currentView: '@mdCurrentView', + mode: '@mdMode', + dateFilter: '=mdDateFilter', + isOpen: '=?mdIsOpen', + debounceInterval: '=mdDebounceInterval', + dateLocale: '=mdDateLocale' + }, + controller: DatePickerCtrl, + controllerAs: 'ctrl', + bindToController: true, + link: function(scope, element, attr, controllers) { + var ngModelCtrl = controllers[0]; + var mdDatePickerCtrl = controllers[1]; + var mdInputContainer = controllers[2]; + var parentForm = controllers[3]; + var mdNoAsterisk = $mdUtil.parseAttributeBoolean(attr.mdNoAsterisk); + + mdDatePickerCtrl.configureNgModel(ngModelCtrl, mdInputContainer, inputDirective); + + if (mdInputContainer) { + // We need to move the spacer after the datepicker itself, + // because md-input-container adds it after the + // md-datepicker-input by default. The spacer gets wrapped in a + // div, because it floats and gets aligned next to the datepicker. + // There are easier ways of working around this with CSS (making the + // datepicker 100% wide, change the `display` etc.), however they + // break the alignment with any other form controls. + var spacer = element[0].querySelector('.md-errors-spacer'); + + if (spacer) { + element.after(angular.element('
    ').append(spacer)); + } + + mdInputContainer.setHasPlaceholder(attr.mdPlaceholder); + mdInputContainer.input = element; + mdInputContainer.element + .addClass(INPUT_CONTAINER_CLASS) + .toggleClass(HAS_CALENDAR_ICON_CLASS, attr.mdHideIcons !== 'calendar' && attr.mdHideIcons !== 'all'); + + if (!mdInputContainer.label) { + $mdAria.expect(element, 'aria-label', attr.mdPlaceholder); + } else if (!mdNoAsterisk) { + attr.$observe('required', function(value) { + mdInputContainer.label.toggleClass('md-required', !!value); + }); + } + + scope.$watch(mdInputContainer.isErrorGetter || function() { + return ngModelCtrl.$invalid && (ngModelCtrl.$touched || (parentForm && parentForm.$submitted)); + }, mdInputContainer.setInvalid); + } else if (parentForm) { + // If invalid, highlights the input when the parent form is submitted. + var parentSubmittedWatcher = scope.$watch(function() { + return parentForm.$submitted; + }, function(isSubmitted) { + if (isSubmitted) { + mdDatePickerCtrl.updateErrorState(); + parentSubmittedWatcher(); + } + }); + } + } + }; + } + + /** Additional offset for the input's `size` attribute, which is updated based on its content. */ + var EXTRA_INPUT_SIZE = 3; + + /** Class applied to the container if the date is invalid. */ + var INVALID_CLASS = 'md-datepicker-invalid'; + + /** Class applied to the datepicker when it's open. */ + var OPEN_CLASS = 'md-datepicker-open'; + + /** Class applied to the md-input-container, if a datepicker is placed inside it */ + var INPUT_CONTAINER_CLASS = '_md-datepicker-floating-label'; + + /** Class to be applied when the calendar icon is enabled. */ + var HAS_CALENDAR_ICON_CLASS = '_md-datepicker-has-calendar-icon'; + + /** Class to be applied when the triangle icon is enabled. */ + var HAS_TRIANGLE_ICON_CLASS = '_md-datepicker-has-triangle-icon'; + + /** Default time in ms to debounce input event by. */ + var DEFAULT_DEBOUNCE_INTERVAL = 500; + + /** + * Height of the calendar pane used to check if the pane is going outside the boundary of + * the viewport. See calendar.scss for how $md-calendar-height is computed; an extra 20px is + * also added to space the pane away from the exact edge of the screen. + * + * This is computed statically now, but can be changed to be measured if the circumstances + * of calendar sizing are changed. + */ + var CALENDAR_PANE_HEIGHT = 368; + + /** + * Width of the calendar pane used to check if the pane is going outside the boundary of + * the viewport. See calendar.scss for how $md-calendar-width is computed; an extra 20px is + * also added to space the pane away from the exact edge of the screen. + * + * This is computed statically now, but can be changed to be measured if the circumstances + * of calendar sizing are changed. + */ + var CALENDAR_PANE_WIDTH = 360; + + /** Used for checking whether the current user agent is on iOS or Android. */ + var IS_MOBILE_REGEX = /ipad|iphone|ipod|android/i; + + /** + * Controller for md-datepicker. + * + * @ngInject @constructor + */ + function DatePickerCtrl($scope, $element, $attrs, $window, $mdConstant, $mdTheming, $mdUtil, + $mdDateLocale, $$mdDateUtil, $$rAF, $filter, $timeout) { + + /** @final */ + this.$window = $window; + + /** @final */ + this.dateUtil = $$mdDateUtil; + + /** @final */ + this.$mdConstant = $mdConstant; + + /** @final */ + this.$mdUtil = $mdUtil; + + /** @final */ + this.$$rAF = $$rAF; + + /** @final */ + this.$mdDateLocale = $mdDateLocale; + + /** @final */ + this.$timeout = $timeout; + + /** + * The root document element. This is used for attaching a top-level click handler to + * close the calendar panel when a click outside said panel occurs. We use `documentElement` + * instead of body because, when scrolling is disabled, some browsers consider the body element + * to be completely off the screen and propagate events directly to the html element. + * @type {!angular.JQLite} + */ + this.documentElement = angular.element(document.documentElement); + + /** @type {!angular.NgModelController} */ + this.ngModelCtrl = null; + + /** @type {HTMLInputElement} */ + this.inputElement = $element[0].querySelector('input'); + + /** @final {!angular.JQLite} */ + this.ngInputElement = angular.element(this.inputElement); + + /** @type {HTMLElement} */ + this.inputContainer = $element[0].querySelector('.md-datepicker-input-container'); + + /** @type {HTMLElement} Floating calendar pane. */ + this.calendarPane = $element[0].querySelector('.md-datepicker-calendar-pane'); + + /** @type {HTMLElement} Calendar icon button. */ + this.calendarButton = $element[0].querySelector('.md-datepicker-button'); + + /** + * Element covering everything but the input in the top of the floating calendar pane. + * @type {!angular.JQLite} + */ + this.inputMask = angular.element($element[0].querySelector('.md-datepicker-input-mask-opaque')); + + /** @final {!angular.JQLite} */ + this.$element = $element; + + /** @final {!angular.Attributes} */ + this.$attrs = $attrs; + + /** @final {!angular.Scope} */ + this.$scope = $scope; + + /** @type {Date} */ + this.date = null; + + /** @type {boolean} */ + this.isFocused = false; + + /** @type {boolean} */ + this.isDisabled; + this.setDisabled($element[0].disabled || angular.isString($attrs.disabled)); + + /** @type {boolean} Whether the date-picker's calendar pane is open. */ + this.isCalendarOpen = false; + + /** @type {boolean} Whether the calendar should open when the input is focused. */ + this.openOnFocus = $attrs.hasOwnProperty('mdOpenOnFocus'); + + /** @final */ + this.mdInputContainer = null; + + /** + * Element from which the calendar pane was opened. Keep track of this so that we can return + * focus to it when the pane is closed. + * @type {HTMLElement} + */ + this.calendarPaneOpenedFrom = null; + + /** @type {String} Unique id for the calendar pane. */ + this.calendarPaneId = 'md-date-pane-' + $mdUtil.nextUid(); + + /** Pre-bound click handler is saved so that the event listener can be removed. */ + this.bodyClickHandler = angular.bind(this, this.handleBodyClick); + + /** + * Name of the event that will trigger a close. Necessary to sniff the browser, because + * the resize event doesn't make sense on mobile and can have a negative impact since it + * triggers whenever the browser zooms in on a focused input. + */ + this.windowEventName = IS_MOBILE_REGEX.test( + navigator.userAgent || navigator.vendor || window.opera + ) ? 'orientationchange' : 'resize'; + + /** Pre-bound close handler so that the event listener can be removed. */ + this.windowEventHandler = $mdUtil.debounce(angular.bind(this, this.closeCalendarPane), 100); + + /** Pre-bound handler for the window blur event. Allows for it to be removed later. */ + this.windowBlurHandler = angular.bind(this, this.handleWindowBlur); + + /** The built-in AngularJS date filter. */ + this.ngDateFilter = $filter('date'); + + /** @type {Number} Extra margin for the left side of the floating calendar pane. */ + this.leftMargin = 20; + + /** @type {Number} Extra margin for the top of the floating calendar. Gets determined on the first open. */ + this.topMargin = null; + + // Unless the user specifies so, the datepicker should not be a tab stop. + // This is necessary because ngAria might add a tabindex to anything with an ng-model + // (based on whether or not the user has turned that particular feature on/off). + if ($attrs.tabindex) { + this.ngInputElement.attr('tabindex', $attrs.tabindex); + $attrs.$set('tabindex', null); + } else { + $attrs.$set('tabindex', '-1'); + } + + $attrs.$set('aria-owns', this.calendarPaneId); + + $mdTheming($element); + $mdTheming(angular.element(this.calendarPane)); + + var self = this; + + $scope.$on('$destroy', function() { + self.detachCalendarPane(); + }); + + if ($attrs.mdIsOpen) { + $scope.$watch('ctrl.isOpen', function(shouldBeOpen) { + if (shouldBeOpen) { + self.openCalendarPane({ + target: self.inputElement + }); + } else { + self.closeCalendarPane(); + } + }); + } + + // For AngularJS 1.4 and older, where there are no lifecycle hooks but bindings are pre-assigned, + // manually call the $onInit hook. + if (angular.version.major === 1 && angular.version.minor <= 4) { + this.$onInit(); + } + + } + + /** + * AngularJS Lifecycle hook for newer AngularJS versions. + * Bindings are not guaranteed to have been assigned in the controller, but they are in the $onInit hook. + */ + DatePickerCtrl.prototype.$onInit = function() { + + /** + * Holds locale-specific formatters, parsers, labels etc. Allows + * the user to override specific ones from the $mdDateLocale provider. + * @type {!Object} + */ + this.locale = this.dateLocale ? angular.extend({}, this.$mdDateLocale, this.dateLocale) : this.$mdDateLocale; + + this.installPropertyInterceptors(); + this.attachChangeListeners(); + this.attachInteractionListeners(); + }; + + /** + * Sets up the controller's reference to ngModelController and + * applies AngularJS's `input[type="date"]` directive. + * @param {!angular.NgModelController} ngModelCtrl Instance of the ngModel controller. + * @param {Object} mdInputContainer Instance of the mdInputContainer controller. + * @param {Object} inputDirective Config for AngularJS's `input` directive. + */ + DatePickerCtrl.prototype.configureNgModel = function(ngModelCtrl, mdInputContainer, inputDirective) { + this.ngModelCtrl = ngModelCtrl; + this.mdInputContainer = mdInputContainer; + + // The input needs to be [type="date"] in order to be picked up by AngularJS. + this.$attrs.$set('type', 'date'); + + // Invoke the `input` directive link function, adding a stub for the element. + // This allows us to re-use AngularJS's logic for setting the timezone via ng-model-options. + // It works by calling the link function directly which then adds the proper `$parsers` and + // `$formatters` to the ngModel controller. + inputDirective[0].link.pre(this.$scope, { + on: angular.noop, + val: angular.noop, + 0: {} + }, this.$attrs, [ngModelCtrl]); + + var self = this; + + // Responds to external changes to the model value. + self.ngModelCtrl.$formatters.push(function(value) { + var parsedValue = angular.isDefined(value) ? value : null; + + if (!(value instanceof Date)) { + parsedValue = Date.parse(value); + + // `parsedValue` is the time since epoch if valid or `NaN` if invalid. + if (!isNaN(parsedValue) && angular.isNumber(parsedValue)) { + value = new Date(parsedValue); + } + + if (value && !(value instanceof Date)) { + throw Error( + 'The ng-model for md-datepicker must be a Date instance or a value ' + + 'that can be parsed into a date. Currently the model is of type: ' + typeof value + ); + } + } + + self.onExternalChange(value); + + return value; + }); + + // Responds to external error state changes (e.g. ng-required based on another input). + ngModelCtrl.$viewChangeListeners.unshift(angular.bind(this, this.updateErrorState)); + + // Forwards any events from the input to the root element. This is necessary to get `updateOn` + // working for events that don't bubble (e.g. 'blur') since AngularJS binds the handlers to + // the ``. + var updateOn = self.$mdUtil.getModelOption(ngModelCtrl, 'updateOn'); + + if (updateOn) { + this.ngInputElement.on( + updateOn, + angular.bind(this.$element, this.$element.triggerHandler, updateOn) + ); + } + }; + + /** + * Attach event listeners for both the text input and the md-calendar. + * Events are used instead of ng-model so that updates don't infinitely update the other + * on a change. This should also be more performant than using a $watch. + */ + DatePickerCtrl.prototype.attachChangeListeners = function() { + var self = this; + + self.$scope.$on('md-calendar-change', function(event, date) { + self.setModelValue(date); + self.onExternalChange(date); + self.closeCalendarPane(); + }); + + self.ngInputElement.on('input', angular.bind(self, self.resizeInputElement)); + + var debounceInterval = angular.isDefined(this.debounceInterval) ? + this.debounceInterval : DEFAULT_DEBOUNCE_INTERVAL; + self.ngInputElement.on('input', self.$mdUtil.debounce(self.handleInputEvent, + debounceInterval, self)); + }; + + /** Attach event listeners for user interaction. */ + DatePickerCtrl.prototype.attachInteractionListeners = function() { + var self = this; + var $scope = this.$scope; + var keyCodes = this.$mdConstant.KEY_CODE; + + // Add event listener through angular so that we can triggerHandler in unit tests. + self.ngInputElement.on('keydown', function(event) { + if (event.altKey && event.keyCode === keyCodes.DOWN_ARROW) { + self.openCalendarPane(event); + $scope.$digest(); + } + }); + + if (self.openOnFocus) { + self.ngInputElement.on('focus', angular.bind(self, self.openCalendarPane)); + self.ngInputElement.on('click', function(event) { + event.stopPropagation(); + }); + self.ngInputElement.on('pointerdown',function(event) { + if (event.target && event.target.setPointerCapture) { + event.target.setPointerCapture(event.pointerId); + } + }); + + angular.element(self.$window).on('blur', self.windowBlurHandler); + + $scope.$on('$destroy', function() { + angular.element(self.$window).off('blur', self.windowBlurHandler); + }); + } + + $scope.$on('md-calendar-close', function() { + self.closeCalendarPane(); + }); + }; + + /** + * Capture properties set to the date-picker and imperatively handle internal changes. + * This is done to avoid setting up additional $watches. + */ + DatePickerCtrl.prototype.installPropertyInterceptors = function() { + var self = this; + + if (this.$attrs.ngDisabled) { + // The expression is to be evaluated against the directive element's scope and not + // the directive's isolate scope. + var scope = this.$scope.$parent; + + if (scope) { + scope.$watch(this.$attrs.ngDisabled, function(isDisabled) { + self.setDisabled(isDisabled); + }); + } + } + + Object.defineProperty(this, 'placeholder', { + get: function() { return self.inputElement.placeholder; }, + set: function(value) { self.inputElement.placeholder = value || ''; } + }); + }; + + /** + * Sets whether the date-picker is disabled. + * @param {boolean} isDisabled + */ + DatePickerCtrl.prototype.setDisabled = function(isDisabled) { + this.isDisabled = isDisabled; + this.inputElement.disabled = isDisabled; + + if (this.calendarButton) { + this.calendarButton.disabled = isDisabled; + } + }; + + /** + * Sets the custom ngModel.$error flags to be consumed by ngMessages. Flags are: + * - mindate: whether the selected date is before the minimum date. + * - maxdate: whether the selected flag is after the maximum date. + * - filtered: whether the selected date is allowed by the custom filtering function. + * - valid: whether the entered text input is a valid date + * + * The 'required' flag is handled automatically by ngModel. + * + * @param {Date=} opt_date Date to check. If not given, defaults to the datepicker's model value. + */ + DatePickerCtrl.prototype.updateErrorState = function(opt_date) { + var date = opt_date || this.date; + + // Clear any existing errors to get rid of anything that's no longer relevant. + this.clearErrorState(); + + if (this.dateUtil.isValidDate(date)) { + // Force all dates to midnight in order to ignore the time portion. + date = this.dateUtil.createDateAtMidnight(date); + + if (this.dateUtil.isValidDate(this.minDate)) { + var minDate = this.dateUtil.createDateAtMidnight(this.minDate); + this.ngModelCtrl.$setValidity('mindate', date >= minDate); + } + + if (this.dateUtil.isValidDate(this.maxDate)) { + var maxDate = this.dateUtil.createDateAtMidnight(this.maxDate); + this.ngModelCtrl.$setValidity('maxdate', date <= maxDate); + } + + if (angular.isFunction(this.dateFilter)) { + this.ngModelCtrl.$setValidity('filtered', this.dateFilter(date)); + } + } else { + // The date is seen as "not a valid date" if there is *something* set + // (i.e.., not null or undefined), but that something isn't a valid date. + this.ngModelCtrl.$setValidity('valid', date == null); + } + + var input = this.inputElement.value; + var parsedDate = this.locale.parseDate(input); + + if (!this.isInputValid(input, parsedDate) && this.ngModelCtrl.$valid) { + this.ngModelCtrl.$setValidity('valid', date == null); + } + + angular.element(this.inputContainer).toggleClass(INVALID_CLASS, !this.ngModelCtrl.$valid); + }; + + /** + * Check to see if the input is valid as the validation should fail if the model is invalid + * + * @param {String} inputString + * @param {Date} parsedDate + * @return {boolean} Whether the input is valid + */ + DatePickerCtrl.prototype.isInputValid = function (inputString, parsedDate) { + return inputString === '' || ( + this.dateUtil.isValidDate(parsedDate) && + this.locale.isDateComplete(inputString) && + this.isDateEnabled(parsedDate) + ); + }; + + /** Clears any error flags set by `updateErrorState`. */ + DatePickerCtrl.prototype.clearErrorState = function() { + this.inputContainer.classList.remove(INVALID_CLASS); + ['mindate', 'maxdate', 'filtered', 'valid'].forEach(function(field) { + this.ngModelCtrl.$setValidity(field, true); + }, this); + }; + + /** Resizes the input element based on the size of its content. */ + DatePickerCtrl.prototype.resizeInputElement = function() { + this.inputElement.size = this.inputElement.value.length + EXTRA_INPUT_SIZE; + }; + + /** + * Sets the model value if the user input is a valid date. + * Adds an invalid class to the input element if not. + */ + DatePickerCtrl.prototype.handleInputEvent = function() { + var inputString = this.inputElement.value; + var parsedDate = inputString ? this.locale.parseDate(inputString) : null; + this.dateUtil.setDateTimeToMidnight(parsedDate); + + // An input string is valid if it is either empty (representing no date) + // or if it parses to a valid date that the user is allowed to select. + var isValidInput = this.isInputValid(inputString, parsedDate); + + // The datepicker's model is only updated when there is a valid input. + if (isValidInput) { + this.setModelValue(parsedDate); + this.date = parsedDate; + } + + this.updateErrorState(parsedDate); + }; + + /** + * Check whether date is in range and enabled + * @param {Date=} opt_date + * @return {boolean} Whether the date is enabled. + */ + DatePickerCtrl.prototype.isDateEnabled = function(opt_date) { + return this.dateUtil.isDateWithinRange(opt_date, this.minDate, this.maxDate) && + (!angular.isFunction(this.dateFilter) || this.dateFilter(opt_date)); + }; + + /** Position and attach the floating calendar to the document. */ + DatePickerCtrl.prototype.attachCalendarPane = function() { + var calendarPane = this.calendarPane; + var body = document.body; + + calendarPane.style.transform = ''; + this.$element.addClass(OPEN_CLASS); + this.mdInputContainer && this.mdInputContainer.element.addClass(OPEN_CLASS); + angular.element(body).addClass('md-datepicker-is-showing'); + + var elementRect = this.inputContainer.getBoundingClientRect(); + var bodyRect = body.getBoundingClientRect(); + + if (!this.topMargin || this.topMargin < 0) { + this.topMargin = (this.inputMask.parent().prop('clientHeight') - this.ngInputElement.prop('clientHeight')) / 2; + } + + // Check to see if the calendar pane would go off the screen. If so, adjust position + // accordingly to keep it within the viewport. + var paneTop = elementRect.top - bodyRect.top - this.topMargin; + var paneLeft = elementRect.left - bodyRect.left - this.leftMargin; + + // If ng-material has disabled body scrolling (for example, if a dialog is open), + // then it's possible that the already-scrolled body has a negative top/left. In this case, + // we want to treat the "real" top as (0 - bodyRect.top). In a normal scrolling situation, + // though, the top of the viewport should just be the body's scroll position. + var viewportTop = (bodyRect.top < 0 && document.body.scrollTop == 0) ? + -bodyRect.top : + document.body.scrollTop; + + var viewportLeft = (bodyRect.left < 0 && document.body.scrollLeft == 0) ? + -bodyRect.left : + document.body.scrollLeft; + + var viewportBottom = viewportTop + this.$window.innerHeight; + var viewportRight = viewportLeft + this.$window.innerWidth; + + // Creates an overlay with a hole the same size as element. We remove a pixel or two + // on each end to make it overlap slightly. The overlay's background is added in + // the theme in the form of a box-shadow with a huge spread. + this.inputMask.css({ + position: 'absolute', + left: this.leftMargin + 'px', + top: this.topMargin + 'px', + width: (elementRect.width - 1) + 'px', + height: (elementRect.height - 2) + 'px' + }); + + // If the right edge of the pane would be off the screen and shifting it left by the + // difference would not go past the left edge of the screen. If the calendar pane is too + // big to fit on the screen at all, move it to the left of the screen and scale the entire + // element down to fit. + if (paneLeft + CALENDAR_PANE_WIDTH > viewportRight) { + if (viewportRight - CALENDAR_PANE_WIDTH > 0) { + paneLeft = viewportRight - CALENDAR_PANE_WIDTH; + } else { + paneLeft = viewportLeft; + var scale = this.$window.innerWidth / CALENDAR_PANE_WIDTH; + calendarPane.style.transform = 'scale(' + scale + ')'; + } + + calendarPane.classList.add('md-datepicker-pos-adjusted'); + } + + // If the bottom edge of the pane would be off the screen and shifting it up by the + // difference would not go past the top edge of the screen. + if (paneTop + CALENDAR_PANE_HEIGHT > viewportBottom && + viewportBottom - CALENDAR_PANE_HEIGHT > viewportTop) { + paneTop = viewportBottom - CALENDAR_PANE_HEIGHT; + calendarPane.classList.add('md-datepicker-pos-adjusted'); + } + + calendarPane.style.left = paneLeft + 'px'; + calendarPane.style.top = paneTop + 'px'; + document.body.appendChild(calendarPane); + + // Add CSS class after one frame to trigger open animation. + this.$$rAF(function() { + calendarPane.classList.add('md-pane-open'); + }); + }; + + /** Detach the floating calendar pane from the document. */ + DatePickerCtrl.prototype.detachCalendarPane = function() { + this.$element.removeClass(OPEN_CLASS); + this.mdInputContainer && this.mdInputContainer.element.removeClass(OPEN_CLASS); + angular.element(document.body).removeClass('md-datepicker-is-showing'); + this.calendarPane.classList.remove('md-pane-open'); + this.calendarPane.classList.remove('md-datepicker-pos-adjusted'); + + if (this.isCalendarOpen) { + this.$mdUtil.enableScrolling(); + } + + if (this.calendarPane.parentNode) { + // Use native DOM removal because we do not want any of the + // angular state of this element to be disposed. + this.calendarPane.parentNode.removeChild(this.calendarPane); + } + }; + + /** + * Open the floating calendar pane. + * @param {Event} event + */ + DatePickerCtrl.prototype.openCalendarPane = function(event) { + if (!this.isCalendarOpen && !this.isDisabled && !this.inputFocusedOnWindowBlur) { + this.isCalendarOpen = this.isOpen = true; + this.calendarPaneOpenedFrom = event.target; + + // Because the calendar pane is attached directly to the body, it is possible that the + // rest of the component (input, etc) is in a different scrolling container, such as + // an md-content. This means that, if the container is scrolled, the pane would remain + // stationary. To remedy this, we disable scrolling while the calendar pane is open, which + // also matches the native behavior for things like `', + ' ', + ' ', + ' ', + ' ', + ' {{ dialog.cancel }}', + ' ', + ' ', + ' {{ dialog.ok }}', + ' ', + ' ', + '' + ].join('').replace(/\s\s+/g, ''), + controller: MdDialogController, + controllerAs: 'dialog', + bindToController: true, + }; + } + + /** + * Controller for the md-dialog interim elements + * @ngInject + */ + function MdDialogController($mdDialog, $mdConstant) { + // For compatibility with AngularJS 1.6+, we should always use the $onInit hook in + // interimElements. The $mdCompiler simulates the $onInit hook for all versions. + this.$onInit = function() { + var isPrompt = this.$type == 'prompt'; + + if (isPrompt && this.initialValue) { + this.result = this.initialValue; + } + + this.hide = function() { + $mdDialog.hide(isPrompt ? this.result : true); + }; + this.abort = function() { + $mdDialog.cancel(); + }; + this.keypress = function($event) { + var invalidPrompt = isPrompt && this.required && !angular.isDefined(this.result); + + if ($event.keyCode === $mdConstant.KEY_CODE.ENTER && !invalidPrompt) { + $mdDialog.hide(this.result); + } + }; + }; + } + + /* @ngInject */ + function dialogDefaultOptions($mdDialog, $mdAria, $mdUtil, $mdConstant, $animate, $document, $window, $rootElement, + $log, $injector, $mdTheming, $interpolate, $mdInteraction) { + + return { + hasBackdrop: true, + isolateScope: true, + onCompiling: beforeCompile, + onShow: onShow, + onShowing: beforeShow, + onRemove: onRemove, + clickOutsideToClose: false, + escapeToClose: true, + targetEvent: null, + closeTo: null, + openFrom: null, + focusOnOpen: true, + disableParentScroll: true, + autoWrap: true, + fullscreen: false, + transformTemplate: function(template, options) { + // Make the dialog container focusable, because otherwise the focus will be always redirected to + // an element outside of the container, and the focus trap won't work probably.. + // Also the tabindex is needed for the `escapeToClose` functionality, because + // the keyDown event can't be triggered when the focus is outside of the container. + var startSymbol = $interpolate.startSymbol(); + var endSymbol = $interpolate.endSymbol(); + var theme = startSymbol + (options.themeWatch ? '' : '::') + 'theme' + endSymbol; + var themeAttr = (options.hasTheme) ? 'md-theme="'+theme+'"': ''; + return '
    ' + validatedTemplate(template) + '
    '; + + /** + * The specified template should contain a wrapper element.... + */ + function validatedTemplate(template) { + if (options.autoWrap && !/<\/md-dialog>/g.test(template)) { + return '' + (template || '') + ''; + } else { + return template || ''; + } + } + } + }; + + function beforeCompile(options) { + // Automatically apply the theme, if the user didn't specify a theme explicitly. + // Those option changes need to be done, before the compilation has started, because otherwise + // the option changes will be not available in the $mdCompilers locales. + options.defaultTheme = $mdTheming.defaultTheme(); + + detectTheming(options); + } + + function beforeShow(scope, element, options, controller) { + + if (controller) { + var mdHtmlContent = controller.htmlContent || options.htmlContent || ''; + var mdTextContent = controller.textContent || options.textContent || + controller.content || options.content || ''; + + if (mdHtmlContent && !$injector.has('$sanitize')) { + throw Error('The ngSanitize module must be loaded in order to use htmlContent.'); + } + + if (mdHtmlContent && mdTextContent) { + throw Error('md-dialog cannot have both `htmlContent` and `textContent`'); + } + + // Only assign the content if nothing throws, otherwise it'll still be compiled. + controller.mdHtmlContent = mdHtmlContent; + controller.mdTextContent = mdTextContent; + } + } + + /** Show method for dialogs */ + function onShow(scope, element, options, controller) { + angular.element($document[0].body).addClass('md-dialog-is-showing'); + + var dialogElement = element.find('md-dialog'); + + // Once a dialog has `ng-cloak` applied on his template the dialog animation will not work properly. + // This is a very common problem, so we have to notify the developer about this. + if (dialogElement.hasClass('ng-cloak')) { + var message = '$mdDialog: using `` will affect the dialog opening animations.'; + $log.warn(message, element[0]); + } + + captureParentAndFromToElements(options); + configureAria(dialogElement, options); + showBackdrop(scope, element, options); + activateListeners(element, options); + + return dialogPopIn(element, options) + .then(function() { + lockScreenReader(element, options); + warnDeprecatedActions(); + focusOnOpen(); + }); + + /** + * Check to see if they used the deprecated .md-actions class and log a warning + */ + function warnDeprecatedActions() { + if (element[0].querySelector('.md-actions')) { + $log.warn('Using a class of md-actions is deprecated, please use .'); + } + } + + /** + * For alerts, focus on content... otherwise focus on + * the close button (or equivalent) + */ + function focusOnOpen() { + if (options.focusOnOpen) { + var target = $mdUtil.findFocusTarget(element) || findCloseButton() || dialogElement; + target.focus(); + } + + /** + * If no element with class dialog-close, try to find the last + * button child in md-actions and assume it is a close button. + * + * If we find no actions at all, log a warning to the console. + */ + function findCloseButton() { + return element[0].querySelector('.dialog-close, md-dialog-actions button:last-child'); + } + } + } + + /** + * Remove function for all dialogs + */ + function onRemove(scope, element, options) { + options.deactivateListeners(); + options.unlockScreenReader(); + options.hideBackdrop(options.$destroy); + + // Remove the focus traps that we added earlier for keeping focus within the dialog. + if (topFocusTrap && topFocusTrap.parentNode) { + topFocusTrap.parentNode.removeChild(topFocusTrap); + } + + if (bottomFocusTrap && bottomFocusTrap.parentNode) { + bottomFocusTrap.parentNode.removeChild(bottomFocusTrap); + } + + // For navigation $destroy events, do a quick, non-animated removal, + // but for normal closes (from clicks, etc) animate the removal + return options.$destroy ? detachAndClean() : animateRemoval().then(detachAndClean); + + /** + * For normal closes, animate the removal. + * For forced closes (like $destroy events), skip the animations + */ + function animateRemoval() { + return dialogPopOut(element, options); + } + + /** + * Detach the element + */ + function detachAndClean() { + angular.element($document[0].body).removeClass('md-dialog-is-showing'); + + // Reverse the container stretch if using a content element. + if (options.contentElement) { + options.reverseContainerStretch(); + } + + // Exposed cleanup function from the $mdCompiler. + options.cleanupElement(); + + // Restores the focus to the origin element if the last interaction upon opening was a keyboard. + if (!options.$destroy && options.originInteraction === 'keyboard') { + options.origin.focus(); + } + } + } + + function detectTheming(options) { + // Once the user specifies a targetEvent, we will automatically try to find the correct + // nested theme. + var targetEl; + if (options.targetEvent && options.targetEvent.target) { + targetEl = angular.element(options.targetEvent.target); + } + + var themeCtrl = targetEl && targetEl.controller('mdTheme'); + + options.hasTheme = (!!themeCtrl); + + if (!options.hasTheme) { + return; + } + + options.themeWatch = themeCtrl.$shouldWatch; + + var theme = options.theme || themeCtrl.$mdTheme; + + if (theme) { + options.scope.theme = theme; + } + + var unwatch = themeCtrl.registerChanges(function (newTheme) { + options.scope.theme = newTheme; + + if (!options.themeWatch) { + unwatch(); + } + }); + } + + /** + * Capture originator/trigger/from/to element information (if available) + * and the parent container for the dialog; defaults to the $rootElement + * unless overridden in the options.parent + */ + function captureParentAndFromToElements(options) { + options.origin = angular.extend({ + element: null, + bounds: null, + focus: angular.noop + }, options.origin || {}); + + options.parent = getDomElement(options.parent, $rootElement); + options.closeTo = getBoundingClientRect(getDomElement(options.closeTo)); + options.openFrom = getBoundingClientRect(getDomElement(options.openFrom)); + + if (options.targetEvent) { + options.origin = getBoundingClientRect(options.targetEvent.target, options.origin); + options.originInteraction = $mdInteraction.getLastInteractionType(); + } + + + /** + * Identify the bounding RECT for the target element + * + */ + function getBoundingClientRect (element, orig) { + var source = angular.element((element || {})); + if (source && source.length) { + // Compute and save the target element's bounding rect, so that if the + // element is hidden when the dialog closes, we can shrink the dialog + // back to the same position it expanded from. + // + // Checking if the source is a rect object or a DOM element + var bounds = {top:0,left:0,height:0,width:0}; + var hasFn = angular.isFunction(source[0].getBoundingClientRect); + + return angular.extend(orig || {}, { + element : hasFn ? source : undefined, + bounds : hasFn ? source[0].getBoundingClientRect() : angular.extend({}, bounds, source[0]), + focus : angular.bind(source, source.focus), + }); + } + } + + /** + * If the specifier is a simple string selector, then query for + * the DOM element. + */ + function getDomElement(element, defaultElement) { + if (angular.isString(element)) { + element = $document[0].querySelector(element); + } + + // If we have a reference to a raw dom element, always wrap it in jqLite + return angular.element(element || defaultElement); + } + + } + + /** + * Listen for escape keys and outside clicks to auto close + */ + function activateListeners(element, options) { + var window = angular.element($window); + var onWindowResize = $mdUtil.debounce(function() { + stretchDialogContainerToViewport(element, options); + }, 60); + + var removeListeners = []; + var smartClose = function() { + // Only 'confirm' dialogs have a cancel button... escape/clickOutside will + // cancel or fallback to hide. + var closeFn = (options.$type == 'alert') ? $mdDialog.hide : $mdDialog.cancel; + $mdUtil.nextTick(closeFn, true); + }; + + if (options.escapeToClose) { + var parentTarget = options.parent; + var keyHandlerFn = function(ev) { + if (ev.keyCode === $mdConstant.KEY_CODE.ESCAPE) { + ev.stopImmediatePropagation(); + ev.preventDefault(); + + smartClose(); + } + }; + + // Add keydown listeners + element.on('keydown', keyHandlerFn); + parentTarget.on('keydown', keyHandlerFn); + + // Queue remove listeners function + removeListeners.push(function() { + + element.off('keydown', keyHandlerFn); + parentTarget.off('keydown', keyHandlerFn); + + }); + } + + // Register listener to update dialog on window resize + window.on('resize', onWindowResize); + + removeListeners.push(function() { + window.off('resize', onWindowResize); + }); + + if (options.clickOutsideToClose) { + var target = element; + var sourceElem; + + // Keep track of the element on which the mouse originally went down + // so that we can only close the backdrop when the 'click' started on it. + // A simple 'click' handler does not work, + // it sets the target object as the element the mouse went down on. + var mousedownHandler = function(ev) { + sourceElem = ev.target; + }; + + // We check if our original element and the target is the backdrop + // because if the original was the backdrop and the target was inside the dialog + // we don't want to dialog to close. + var mouseupHandler = function(ev) { + if (sourceElem === target[0] && ev.target === target[0]) { + ev.stopPropagation(); + ev.preventDefault(); + + smartClose(); + } + }; + + // Add listeners + target.on('mousedown', mousedownHandler); + target.on('mouseup', mouseupHandler); + + // Queue remove listeners function + removeListeners.push(function() { + target.off('mousedown', mousedownHandler); + target.off('mouseup', mouseupHandler); + }); + } + + // Attach specific `remove` listener handler + options.deactivateListeners = function() { + removeListeners.forEach(function(removeFn) { + removeFn(); + }); + options.deactivateListeners = null; + }; + } + + /** + * Show modal backdrop element... + */ + function showBackdrop(scope, element, options) { + + if (options.disableParentScroll) { + // !! DO this before creating the backdrop; since disableScrollAround() + // configures the scroll offset; which is used by mdBackDrop postLink() + options.restoreScroll = $mdUtil.disableScrollAround(element, options.parent); + } + + if (options.hasBackdrop) { + options.backdrop = $mdUtil.createBackdrop(scope, "md-dialog-backdrop md-opaque"); + $animate.enter(options.backdrop, options.parent); + } + + /** + * Hide modal backdrop element... + */ + options.hideBackdrop = function hideBackdrop($destroy) { + if (options.backdrop) { + if ($destroy) options.backdrop.remove(); + else $animate.leave(options.backdrop); + } + + + if (options.disableParentScroll) { + options.restoreScroll && options.restoreScroll(); + delete options.restoreScroll; + } + + options.hideBackdrop = null; + }; + } + + /** + * Inject ARIA-specific attributes appropriate for Dialogs + */ + function configureAria(element, options) { + + var role = (options.$type === 'alert') ? 'alertdialog' : 'dialog'; + var dialogContent = element.find('md-dialog-content'); + var existingDialogId = element.attr('id'); + var dialogContentId = 'dialogContent_' + (existingDialogId || $mdUtil.nextUid()); + + element.attr({ + 'role': role, + 'tabIndex': '-1' + }); + + if (dialogContent.length === 0) { + dialogContent = element; + // If the dialog element already had an ID, don't clobber it. + if (existingDialogId) { + dialogContentId = existingDialogId; + } + } + + dialogContent.attr('id', dialogContentId); + element.attr('aria-describedby', dialogContentId); + + if (options.ariaLabel) { + $mdAria.expect(element, 'aria-label', options.ariaLabel); + } + else { + $mdAria.expectAsync(element, 'aria-label', function() { + // If dialog title is specified, set aria-label with it + // See https://github.com/angular/material/issues/10582 + if (options.title) { + return options.title; + } else { + var words = dialogContent.text().split(/\s+/); + if (words.length > 3) words = words.slice(0, 3).concat('...'); + return words.join(' '); + } + }); + } + + // Set up elements before and after the dialog content to capture focus and + // redirect back into the dialog. + topFocusTrap = document.createElement('div'); + topFocusTrap.classList.add('md-dialog-focus-trap'); + topFocusTrap.tabIndex = 0; + + bottomFocusTrap = topFocusTrap.cloneNode(false); + + // When focus is about to move out of the dialog, we want to intercept it and redirect it + // back to the dialog element. + var focusHandler = function() { + element.focus(); + }; + topFocusTrap.addEventListener('focus', focusHandler); + bottomFocusTrap.addEventListener('focus', focusHandler); + + // The top focus trap inserted immeidately before the md-dialog element (as a sibling). + // The bottom focus trap is inserted at the very end of the md-dialog element (as a child). + element[0].parentNode.insertBefore(topFocusTrap, element[0]); + element.after(bottomFocusTrap); + } + + /** + * Prevents screen reader interaction behind modal window + * on swipe interfaces + */ + function lockScreenReader(element, options) { + var isHidden = true; + + // get raw DOM node + walkDOM(element[0]); + + options.unlockScreenReader = function () { + isHidden = false; + walkDOM(element[0]); + + options.unlockScreenReader = null; + }; + + /** + * Get all of an element's parent elements up the DOM tree + * @return {Array} The parent elements + */ + function getParents(element) { + var parents = []; + while (element.parentNode) { + if (element === document.body) { + return parents; + } + var children = element.parentNode.children; + for (var i = 0; i < children.length; i++) { + // skip over child if it is an ascendant of the dialog + // a script or style tag, or a live region. + if (element !== children[i] && + !isNodeOneOf(children[i], ['SCRIPT', 'STYLE']) && + !children[i].hasAttribute('aria-live')) { + parents.push(children[i]); + } + } + element = element.parentNode; + } + return parents; + } + + /** + * Walk DOM to apply or remove aria-hidden on sibling nodes + * and parent sibling nodes + */ + function walkDOM(element) { + var elements = getParents(element); + for (var i = 0; i < elements.length; i++) { + elements[i].setAttribute('aria-hidden', isHidden); + } + } + } + + /** + * Ensure the dialog container fill-stretches to the viewport + */ + function stretchDialogContainerToViewport(container, options) { + var isFixed = $window.getComputedStyle($document[0].body).position == 'fixed'; + var backdrop = options.backdrop ? $window.getComputedStyle(options.backdrop[0]) : null; + var height = backdrop ? Math.min($document[0].body.clientHeight, Math.ceil(Math.abs(parseInt(backdrop.height, 10)))) : 0; + + var previousStyles = { + top: container.css('top'), + height: container.css('height') + }; + + // If the body is fixed, determine the distance to the viewport in relative from the parent. + var parentTop = Math.abs(options.parent[0].getBoundingClientRect().top); + + container.css({ + top: (isFixed ? parentTop : 0) + 'px', + height: height ? height + 'px' : '100%' + }); + + return function() { + // Reverts the modified styles back to the previous values. + // This is needed for contentElements, which should have the same styles after close + // as before. + container.css(previousStyles); + }; + } + + /** + * Dialog open and pop-in animation + */ + function dialogPopIn(container, options) { + // Add the `md-dialog-container` to the DOM + options.parent.append(container); + options.reverseContainerStretch = stretchDialogContainerToViewport(container, options); + + var dialogEl = container.find('md-dialog'); + var animator = $mdUtil.dom.animator; + var buildTranslateToOrigin = animator.calculateZoomToOrigin; + var translateOptions = {transitionInClass: 'md-transition-in', transitionOutClass: 'md-transition-out'}; + var from = animator.toTransformCss(buildTranslateToOrigin(dialogEl, options.openFrom || options.origin)); + var to = animator.toTransformCss(""); // defaults to center display (or parent or $rootElement) + + dialogEl.toggleClass('md-dialog-fullscreen', !!options.fullscreen); + + return animator + .translate3d(dialogEl, from, to, translateOptions) + .then(function(animateReversal) { + + // Build a reversal translate function synced to this translation... + options.reverseAnimate = function() { + delete options.reverseAnimate; + + if (options.closeTo) { + // Using the opposite classes to create a close animation to the closeTo element + translateOptions = {transitionInClass: 'md-transition-out', transitionOutClass: 'md-transition-in'}; + from = to; + to = animator.toTransformCss(buildTranslateToOrigin(dialogEl, options.closeTo)); + + return animator + .translate3d(dialogEl, from, to,translateOptions); + } + + return animateReversal( + to = animator.toTransformCss( + // in case the origin element has moved or is hidden, + // let's recalculate the translateCSS + buildTranslateToOrigin(dialogEl, options.origin) + ) + ); + + }; + + // Function to revert the generated animation styles on the dialog element. + // Useful when using a contentElement instead of a template. + options.clearAnimate = function() { + delete options.clearAnimate; + + // Remove the transition classes, added from $animateCSS, since those can't be removed + // by reversely running the animator. + dialogEl.removeClass([ + translateOptions.transitionOutClass, + translateOptions.transitionInClass + ].join(' ')); + + // Run the animation reversely to remove the previous added animation styles. + return animator.translate3d(dialogEl, to, animator.toTransformCss(''), {}); + }; + + return true; + }); + } + + /** + * Dialog close and pop-out animation + */ + function dialogPopOut(container, options) { + return options.reverseAnimate().then(function() { + if (options.contentElement) { + // When we use a contentElement, we want the element to be the same as before. + // That means, that we have to clear all the animation properties, like transform. + options.clearAnimate(); + } + }); + } + + /** + * Utility function to filter out raw DOM nodes + */ + function isNodeOneOf(elem, nodeTypeArray) { + if (nodeTypeArray.indexOf(elem.nodeName) !== -1) { + return true; + } + } + + } +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.divider + * @description Divider module! + */ +MdDividerDirective.$inject = ["$mdTheming"]; +angular.module('material.components.divider', [ + 'material.core' +]) + .directive('mdDivider', MdDividerDirective); + +/** + * @ngdoc directive + * @name mdDivider + * @module material.components.divider + * @restrict E + * + * @description + * Dividers group and separate content within lists and page layouts using strong visual and spatial distinctions. This divider is a thin rule, lightweight enough to not distract the user from content. + * + * @param {boolean=} md-inset Add this attribute to activate the inset divider style. + * @usage + * + * + * + * + * + * + */ +function MdDividerDirective($mdTheming) { + return { + restrict: 'E', + link: $mdTheming + }; +} + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + /** + * @ngdoc module + * @name material.components.fabActions + */ + MdFabActionsDirective.$inject = ["$mdUtil"]; + angular + .module('material.components.fabActions', ['material.core']) + .directive('mdFabActions', MdFabActionsDirective); + + /** + * @ngdoc directive + * @name mdFabActions + * @module material.components.fabActions + * + * @restrict E + * + * @description + * The `` directive is used inside of a `` or + * `` directive to mark an element (or elements) as the actions and setup the + * proper event listeners. + * + * @usage + * See the `` or `` directives for example usage. + */ + function MdFabActionsDirective($mdUtil) { + return { + restrict: 'E', + + require: ['^?mdFabSpeedDial', '^?mdFabToolbar'], + + compile: function(element, attributes) { + var children = element.children(); + + var hasNgRepeat = $mdUtil.prefixer().hasAttribute(children, 'ng-repeat'); + + // Support both ng-repeat and static content + if (hasNgRepeat) { + children.addClass('md-fab-action-item'); + } else { + // Wrap every child in a new div and add a class that we can scale/fling independently + children.wrap('
    '); + } + } + }; + } + +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + MdFabController.$inject = ["$scope", "$element", "$animate", "$mdUtil", "$mdConstant", "$timeout"]; + angular.module('material.components.fabShared', ['material.core']) + .controller('MdFabController', MdFabController); + + function MdFabController($scope, $element, $animate, $mdUtil, $mdConstant, $timeout) { + var vm = this; + var initialAnimationAttempts = 0; + + // NOTE: We use async eval(s) below to avoid conflicts with any existing digest loops + + vm.open = function() { + $scope.$evalAsync("vm.isOpen = true"); + }; + + vm.close = function() { + // Async eval to avoid conflicts with existing digest loops + $scope.$evalAsync("vm.isOpen = false"); + + // Focus the trigger when the element closes so users can still tab to the next item + $element.find('md-fab-trigger')[0].focus(); + }; + + // Toggle the open/close state when the trigger is clicked + vm.toggle = function() { + $scope.$evalAsync("vm.isOpen = !vm.isOpen"); + }; + + /* + * AngularJS Lifecycle hook for newer AngularJS versions. + * Bindings are not guaranteed to have been assigned in the controller, but they are in the $onInit hook. + */ + vm.$onInit = function() { + setupDefaults(); + setupListeners(); + setupWatchers(); + + fireInitialAnimations(); + }; + + // For AngularJS 1.4 and older, where there are no lifecycle hooks but bindings are pre-assigned, + // manually call the $onInit hook. + if (angular.version.major === 1 && angular.version.minor <= 4) { + this.$onInit(); + } + + function setupDefaults() { + // Set the default direction to 'down' if none is specified + vm.direction = vm.direction || 'down'; + + // Set the default to be closed + vm.isOpen = vm.isOpen || false; + + // Start the keyboard interaction at the first action + resetActionIndex(); + + // Add an animations waiting class so we know not to run + $element.addClass('md-animations-waiting'); + } + + function setupListeners() { + var eventTypes = [ + 'click', 'focusin', 'focusout' + ]; + + // Add our listeners + angular.forEach(eventTypes, function(eventType) { + $element.on(eventType, parseEvents); + }); + + // Remove our listeners when destroyed + $scope.$on('$destroy', function() { + angular.forEach(eventTypes, function(eventType) { + $element.off(eventType, parseEvents); + }); + + // remove any attached keyboard handlers in case element is removed while + // speed dial is open + disableKeyboard(); + }); + } + + var closeTimeout; + function parseEvents(event) { + // If the event is a click, just handle it + if (event.type == 'click') { + handleItemClick(event); + } + + // If we focusout, set a timeout to close the element + if (event.type == 'focusout' && !closeTimeout) { + closeTimeout = $timeout(function() { + vm.close(); + }, 100, false); + } + + // If we see a focusin and there is a timeout about to run, cancel it so we stay open + if (event.type == 'focusin' && closeTimeout) { + $timeout.cancel(closeTimeout); + closeTimeout = null; + } + } + + function resetActionIndex() { + vm.currentActionIndex = -1; + } + + function setupWatchers() { + // Watch for changes to the direction and update classes/attributes + $scope.$watch('vm.direction', function(newDir, oldDir) { + // Add the appropriate classes so we can target the direction in the CSS + $animate.removeClass($element, 'md-' + oldDir); + $animate.addClass($element, 'md-' + newDir); + + // Reset the action index since it may have changed + resetActionIndex(); + }); + + var trigger, actions; + + // Watch for changes to md-open + $scope.$watch('vm.isOpen', function(isOpen) { + // Reset the action index since it may have changed + resetActionIndex(); + + // We can't get the trigger/actions outside of the watch because the component hasn't been + // linked yet, so we wait until the first watch fires to cache them. + if (!trigger || !actions) { + trigger = getTriggerElement(); + actions = getActionsElement(); + } + + if (isOpen) { + enableKeyboard(); + } else { + disableKeyboard(); + } + + var toAdd = isOpen ? 'md-is-open' : ''; + var toRemove = isOpen ? '' : 'md-is-open'; + + // Set the proper ARIA attributes + trigger.attr('aria-haspopup', true); + trigger.attr('aria-expanded', isOpen); + actions.attr('aria-hidden', !isOpen); + + // Animate the CSS classes + $animate.setClass($element, toAdd, toRemove); + }); + } + + function fireInitialAnimations() { + // If the element is actually visible on the screen + if ($element[0].scrollHeight > 0) { + // Fire our animation + $animate.addClass($element, '_md-animations-ready').then(function() { + // Remove the waiting class + $element.removeClass('md-animations-waiting'); + }); + } + + // Otherwise, try for up to 1 second before giving up + else if (initialAnimationAttempts < 10) { + $timeout(fireInitialAnimations, 100); + + // Increment our counter + initialAnimationAttempts = initialAnimationAttempts + 1; + } + } + + function enableKeyboard() { + $element.on('keydown', keyPressed); + + // On the next tick, setup a check for outside clicks; we do this on the next tick to avoid + // clicks/touches that result in the isOpen attribute changing (e.g. a bound radio button) + $mdUtil.nextTick(function() { + angular.element(document).on('click touchend', checkForOutsideClick); + }); + + // TODO: On desktop, we should be able to reset the indexes so you cannot tab through, but + // this breaks accessibility, especially on mobile, since you have no arrow keys to press + // resetActionTabIndexes(); + } + + function disableKeyboard() { + $element.off('keydown', keyPressed); + angular.element(document).off('click touchend', checkForOutsideClick); + } + + function checkForOutsideClick(event) { + if (event.target) { + var closestTrigger = $mdUtil.getClosest(event.target, 'md-fab-trigger'); + var closestActions = $mdUtil.getClosest(event.target, 'md-fab-actions'); + + if (!closestTrigger && !closestActions) { + vm.close(); + } + } + } + + function keyPressed(event) { + switch (event.which) { + case $mdConstant.KEY_CODE.ESCAPE: vm.close(); event.preventDefault(); return false; + case $mdConstant.KEY_CODE.LEFT_ARROW: doKeyLeft(event); return false; + case $mdConstant.KEY_CODE.UP_ARROW: doKeyUp(event); return false; + case $mdConstant.KEY_CODE.RIGHT_ARROW: doKeyRight(event); return false; + case $mdConstant.KEY_CODE.DOWN_ARROW: doKeyDown(event); return false; + } + } + + function doActionPrev(event) { + focusAction(event, -1); + } + + function doActionNext(event) { + focusAction(event, 1); + } + + function focusAction(event, direction) { + var actions = resetActionTabIndexes(); + + // Increment/decrement the counter with restrictions + vm.currentActionIndex = vm.currentActionIndex + direction; + vm.currentActionIndex = Math.min(actions.length - 1, vm.currentActionIndex); + vm.currentActionIndex = Math.max(0, vm.currentActionIndex); + + // Focus the element + var focusElement = angular.element(actions[vm.currentActionIndex]).children()[0]; + angular.element(focusElement).attr('tabindex', 0); + focusElement.focus(); + + // Make sure the event doesn't bubble and cause something else + event.preventDefault(); + event.stopImmediatePropagation(); + } + + function resetActionTabIndexes() { + // Grab all of the actions + var actions = getActionsElement()[0].querySelectorAll('.md-fab-action-item'); + + // Disable all other actions for tabbing + angular.forEach(actions, function(action) { + angular.element(angular.element(action).children()[0]).attr('tabindex', -1); + }); + + return actions; + } + + function doKeyLeft(event) { + if (vm.direction === 'left') { + doActionNext(event); + } else { + doActionPrev(event); + } + } + + function doKeyUp(event) { + if (vm.direction === 'down') { + doActionPrev(event); + } else { + doActionNext(event); + } + } + + function doKeyRight(event) { + if (vm.direction === 'left') { + doActionPrev(event); + } else { + doActionNext(event); + } + } + + function doKeyDown(event) { + if (vm.direction === 'up') { + doActionPrev(event); + } else { + doActionNext(event); + } + } + + function isTrigger(element) { + return $mdUtil.getClosest(element, 'md-fab-trigger'); + } + + function isAction(element) { + return $mdUtil.getClosest(element, 'md-fab-actions'); + } + + function handleItemClick(event) { + if (isTrigger(event.target)) { + vm.toggle(); + } + + if (isAction(event.target)) { + vm.close(); + } + } + + function getTriggerElement() { + return $element.find('md-fab-trigger'); + } + + function getActionsElement() { + return $element.find('md-fab-actions'); + } + } +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + /** + * The duration of the CSS animation in milliseconds. + * + * @type {number} + */ + MdFabSpeedDialFlingAnimation.$inject = ["$timeout"]; + MdFabSpeedDialScaleAnimation.$inject = ["$timeout"]; + var cssAnimationDuration = 300; + + /** + * @ngdoc module + * @name material.components.fabSpeedDial + */ + angular + // Declare our module + .module('material.components.fabSpeedDial', [ + 'material.core', + 'material.components.fabShared', + 'material.components.fabActions' + ]) + + // Register our directive + .directive('mdFabSpeedDial', MdFabSpeedDialDirective) + + // Register our custom animations + .animation('.md-fling', MdFabSpeedDialFlingAnimation) + .animation('.md-scale', MdFabSpeedDialScaleAnimation) + + // Register a service for each animation so that we can easily inject them into unit tests + .service('mdFabSpeedDialFlingAnimation', MdFabSpeedDialFlingAnimation) + .service('mdFabSpeedDialScaleAnimation', MdFabSpeedDialScaleAnimation); + + /** + * @ngdoc directive + * @name mdFabSpeedDial + * @module material.components.fabSpeedDial + * + * @restrict E + * + * @description + * The `` directive is used to present a series of popup elements (usually + * ``s) for quick access to common actions. + * + * There are currently two animations available by applying one of the following classes to + * the component: + * + * - `md-fling` - The speed dial items appear from underneath the trigger and move into their + * appropriate positions. + * - `md-scale` - The speed dial items appear in their proper places by scaling from 0% to 100%. + * + * You may also easily position the trigger by applying one one of the following classes to the + * `` element: + * - `md-fab-top-left` + * - `md-fab-top-right` + * - `md-fab-bottom-left` + * - `md-fab-bottom-right` + * + * These CSS classes use `position: absolute`, so you need to ensure that the container element + * also uses `position: absolute` or `position: relative` in order for them to work. + * + * Additionally, you may use the standard `ng-mouseenter` and `ng-mouseleave` directives to + * open or close the speed dial. However, if you wish to allow users to hover over the empty + * space where the actions will appear, you must also add the `md-hover-full` class to the speed + * dial element. Without this, the hover effect will only occur on top of the trigger. + * + * See the demos for more information. + * + * ## Troubleshooting + * + * If your speed dial shows the closing animation upon launch, you may need to use `ng-cloak` on + * the parent container to ensure that it is only visible once ready. We have plans to remove this + * necessity in the future. + * + * @usage + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * @param {string} md-direction From which direction you would like the speed dial to appear + * relative to the trigger element. + * @param {expression=} md-open Programmatically control whether or not the speed-dial is visible. + */ + function MdFabSpeedDialDirective() { + return { + restrict: 'E', + + scope: { + direction: '@?mdDirection', + isOpen: '=?mdOpen' + }, + + bindToController: true, + controller: 'MdFabController', + controllerAs: 'vm', + + link: FabSpeedDialLink + }; + + function FabSpeedDialLink(scope, element) { + // Prepend an element to hold our CSS variables so we can use them in the animations below + element.prepend('
    '); + } + } + + function MdFabSpeedDialFlingAnimation($timeout) { + function delayDone(done) { $timeout(done, cssAnimationDuration, false); } + + function runAnimation(element) { + // Don't run if we are still waiting and we are not ready + if (element.hasClass('md-animations-waiting') && !element.hasClass('_md-animations-ready')) { + return; + } + + var el = element[0]; + var ctrl = element.controller('mdFabSpeedDial'); + var items = el.querySelectorAll('.md-fab-action-item'); + + // Grab our trigger element + var triggerElement = el.querySelector('md-fab-trigger'); + + // Grab our element which stores CSS variables + var variablesElement = el.querySelector('._md-css-variables'); + + // Setup JS variables based on our CSS variables + var startZIndex = parseInt(window.getComputedStyle(variablesElement).zIndex); + + // Always reset the items to their natural position/state + angular.forEach(items, function(item, index) { + var styles = item.style; + + styles.transform = styles.webkitTransform = ''; + styles.transitionDelay = ''; + styles.opacity = 1; + + // Make the items closest to the trigger have the highest z-index + styles.zIndex = (items.length - index) + startZIndex; + }); + + // Set the trigger to be above all of the actions so they disappear behind it. + triggerElement.style.zIndex = startZIndex + items.length + 1; + + // If the control is closed, hide the items behind the trigger + if (!ctrl.isOpen) { + angular.forEach(items, function(item, index) { + var newPosition, axis; + var styles = item.style; + + // Make sure to account for differences in the dimensions of the trigger verses the items + // so that we can properly center everything; this helps hide the item's shadows behind + // the trigger. + var triggerItemHeightOffset = (triggerElement.clientHeight - item.clientHeight) / 2; + var triggerItemWidthOffset = (triggerElement.clientWidth - item.clientWidth) / 2; + + switch (ctrl.direction) { + case 'up': + newPosition = (item.scrollHeight * (index + 1) + triggerItemHeightOffset); + axis = 'Y'; + break; + case 'down': + newPosition = -(item.scrollHeight * (index + 1) + triggerItemHeightOffset); + axis = 'Y'; + break; + case 'left': + newPosition = (item.scrollWidth * (index + 1) + triggerItemWidthOffset); + axis = 'X'; + break; + case 'right': + newPosition = -(item.scrollWidth * (index + 1) + triggerItemWidthOffset); + axis = 'X'; + break; + } + + var newTranslate = 'translate' + axis + '(' + newPosition + 'px)'; + + styles.transform = styles.webkitTransform = newTranslate; + }); + } + } + + return { + addClass: function(element, className, done) { + if (element.hasClass('md-fling')) { + runAnimation(element); + delayDone(done); + } else { + done(); + } + }, + removeClass: function(element, className, done) { + runAnimation(element); + delayDone(done); + } + }; + } + + function MdFabSpeedDialScaleAnimation($timeout) { + function delayDone(done) { $timeout(done, cssAnimationDuration, false); } + + var delay = 65; + + function runAnimation(element) { + var el = element[0]; + var ctrl = element.controller('mdFabSpeedDial'); + var items = el.querySelectorAll('.md-fab-action-item'); + + // Grab our element which stores CSS variables + var variablesElement = el.querySelector('._md-css-variables'); + + // Setup JS variables based on our CSS variables + var startZIndex = parseInt(window.getComputedStyle(variablesElement).zIndex); + + // Always reset the items to their natural position/state + angular.forEach(items, function(item, index) { + var styles = item.style, + offsetDelay = index * delay; + + styles.opacity = ctrl.isOpen ? 1 : 0; + styles.transform = styles.webkitTransform = ctrl.isOpen ? 'scale(1)' : 'scale(0)'; + styles.transitionDelay = (ctrl.isOpen ? offsetDelay : (items.length - offsetDelay)) + 'ms'; + + // Make the items closest to the trigger have the highest z-index + styles.zIndex = (items.length - index) + startZIndex; + }); + } + + return { + addClass: function(element, className, done) { + runAnimation(element); + delayDone(done); + }, + + removeClass: function(element, className, done) { + runAnimation(element); + delayDone(done); + } + }; + } +})(); + +})(); +(function(){ +"use strict"; + +(function() { + 'use strict'; + + /** + * @ngdoc module + * @name material.components.fabToolbar + */ + angular + // Declare our module + .module('material.components.fabToolbar', [ + 'material.core', + 'material.components.fabShared', + 'material.components.fabActions' + ]) + + // Register our directive + .directive('mdFabToolbar', MdFabToolbarDirective) + + // Register our custom animations + .animation('.md-fab-toolbar', MdFabToolbarAnimation) + + // Register a service for the animation so that we can easily inject it into unit tests + .service('mdFabToolbarAnimation', MdFabToolbarAnimation); + + /** + * @ngdoc directive + * @name mdFabToolbar + * @module material.components.fabToolbar + * + * @restrict E + * + * @description + * + * The `` directive is used to present a toolbar of elements (usually ``s) + * for quick access to common actions when a floating action button is activated (via click or + * keyboard navigation). + * + * You may also easily position the trigger by applying one one of the following classes to the + * `` element: + * - `md-fab-top-left` + * - `md-fab-top-right` + * - `md-fab-bottom-left` + * - `md-fab-bottom-right` + * + * These CSS classes use `position: absolute`, so you need to ensure that the container element + * also uses `position: absolute` or `position: relative` in order for them to work. + * + * @usage + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * @param {string} md-direction From which direction you would like the toolbar items to appear + * relative to the trigger element. Supports `left` and `right` directions. + * @param {expression=} md-open Programmatically control whether or not the toolbar is visible. + */ + function MdFabToolbarDirective() { + return { + restrict: 'E', + transclude: true, + template: '
    ' + + '
    ' + + '
    ', + + scope: { + direction: '@?mdDirection', + isOpen: '=?mdOpen' + }, + + bindToController: true, + controller: 'MdFabController', + controllerAs: 'vm', + + link: link + }; + + function link(scope, element, attributes) { + // Add the base class for animations + element.addClass('md-fab-toolbar'); + + // Prepend the background element to the trigger's button + element.find('md-fab-trigger').find('button') + .prepend('
    '); + } + } + + function MdFabToolbarAnimation() { + + function runAnimation(element, className, done) { + // If no className was specified, don't do anything + if (!className) { + return; + } + + var el = element[0]; + var ctrl = element.controller('mdFabToolbar'); + + // Grab the relevant child elements + var backgroundElement = el.querySelector('.md-fab-toolbar-background'); + var triggerElement = el.querySelector('md-fab-trigger button'); + var toolbarElement = el.querySelector('md-toolbar'); + var iconElement = el.querySelector('md-fab-trigger button md-icon'); + var actions = element.find('md-fab-actions').children(); + + // If we have both elements, use them to position the new background + if (triggerElement && backgroundElement) { + // Get our variables + var color = window.getComputedStyle(triggerElement).getPropertyValue('background-color'); + var width = el.offsetWidth; + var height = el.offsetHeight; + + // Make it twice as big as it should be since we scale from the center + var scale = 2 * (width / triggerElement.offsetWidth); + + // Set some basic styles no matter what animation we're doing + backgroundElement.style.backgroundColor = color; + backgroundElement.style.borderRadius = width + 'px'; + + // If we're open + if (ctrl.isOpen) { + // Turn on toolbar pointer events when closed + toolbarElement.style.pointerEvents = 'inherit'; + + backgroundElement.style.width = triggerElement.offsetWidth + 'px'; + backgroundElement.style.height = triggerElement.offsetHeight + 'px'; + backgroundElement.style.transform = 'scale(' + scale + ')'; + + // Set the next close animation to have the proper delays + backgroundElement.style.transitionDelay = '0ms'; + iconElement && (iconElement.style.transitionDelay = '.3s'); + + // Apply a transition delay to actions + angular.forEach(actions, function(action, index) { + action.style.transitionDelay = (actions.length - index) * 25 + 'ms'; + }); + } else { + // Turn off toolbar pointer events when closed + toolbarElement.style.pointerEvents = 'none'; + + // Scale it back down to the trigger's size + backgroundElement.style.transform = 'scale(1)'; + + // Reset the position + backgroundElement.style.top = '0'; + + if (element.hasClass('md-right')) { + backgroundElement.style.left = '0'; + backgroundElement.style.right = null; + } + + if (element.hasClass('md-left')) { + backgroundElement.style.right = '0'; + backgroundElement.style.left = null; + } + + // Set the next open animation to have the proper delays + backgroundElement.style.transitionDelay = '200ms'; + iconElement && (iconElement.style.transitionDelay = '0ms'); + + // Apply a transition delay to actions + angular.forEach(actions, function(action, index) { + action.style.transitionDelay = 200 + (index * 25) + 'ms'; + }); + } + } + } + + return { + addClass: function(element, className, done) { + runAnimation(element, className, done); + done(); + }, + + removeClass: function(element, className, done) { + runAnimation(element, className, done); + done(); + } + }; + } +})(); + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.gridList + */ +GridListController.$inject = ["$mdUtil"]; +GridLayoutFactory.$inject = ["$mdUtil"]; +GridListDirective.$inject = ["$interpolate", "$mdConstant", "$mdGridLayout", "$mdMedia"]; +GridTileDirective.$inject = ["$mdMedia"]; +angular.module('material.components.gridList', ['material.core']) + .directive('mdGridList', GridListDirective) + .directive('mdGridTile', GridTileDirective) + .directive('mdGridTileFooter', GridTileCaptionDirective) + .directive('mdGridTileHeader', GridTileCaptionDirective) + .factory('$mdGridLayout', GridLayoutFactory); + +/** + * @ngdoc directive + * @name mdGridList + * @module material.components.gridList + * @restrict E + * @description + * Grid lists are an alternative to standard list views. Grid lists are distinct + * from grids used for layouts and other visual presentations. + * + * A grid list is best suited to presenting a homogenous data type, typically + * images, and is optimized for visual comprehension and differentiating between + * like data types. + * + * A grid list is a continuous element consisting of tessellated, regular + * subdivisions called cells that contain tiles (`md-grid-tile`). + * + * Concept of grid explained visually + * Grid concepts legend + * + * Cells are arrayed vertically and horizontally within the grid. + * + * Tiles hold content and can span one or more cells vertically or horizontally. + * + * ### Responsive Attributes + * + * The `md-grid-list` directive supports "responsive" attributes, which allow + * different `md-cols`, `md-gutter` and `md-row-height` values depending on the + * currently matching media query. + * + * In order to set a responsive attribute, first define the fallback value with + * the standard attribute name, then add additional attributes with the + * following convention: `{base-attribute-name}-{media-query-name}="{value}"` + * (ie. `md-cols-lg="8"`) + * + * @param {number} md-cols Number of columns in the grid. + * @param {string} md-row-height One of + *
      + *
    • CSS length - Fixed height rows (eg. `8px` or `1rem`)
    • + *
    • `{width}:{height}` - Ratio of width to height (eg. + * `md-row-height="16:9"`)
    • + *
    • `"fit"` - Height will be determined by subdividing the available + * height by the number of rows
    • + *
    + * @param {string=} md-gutter The amount of space between tiles in CSS units + * (default 1px) + * @param {expression=} md-on-layout Expression to evaluate after layout. Event + * object is available as `$event`, and contains performance information. + * + * @usage + * Basic: + * + * + * + * + * + * + * Fixed-height rows: + * + * + * + * + * + * + * Fit rows: + * + * + * + * + * + * + * Using responsive attributes: + * + * + * + * + * + */ +function GridListDirective($interpolate, $mdConstant, $mdGridLayout, $mdMedia) { + return { + restrict: 'E', + controller: GridListController, + scope: { + mdOnLayout: '&' + }, + link: postLink + }; + + function postLink(scope, element, attrs, ctrl) { + element.addClass('_md'); // private md component indicator for styling + + // Apply semantics + element.attr('role', 'list'); + + // Provide the controller with a way to trigger layouts. + ctrl.layoutDelegate = layoutDelegate; + + var invalidateLayout = angular.bind(ctrl, ctrl.invalidateLayout), + unwatchAttrs = watchMedia(); + scope.$on('$destroy', unwatchMedia); + + /** + * Watches for changes in media, invalidating layout as necessary. + */ + function watchMedia() { + for (var mediaName in $mdConstant.MEDIA) { + $mdMedia(mediaName); // initialize + $mdMedia.getQuery($mdConstant.MEDIA[mediaName]) + .addListener(invalidateLayout); + } + return $mdMedia.watchResponsiveAttributes( + ['md-cols', 'md-row-height', 'md-gutter'], attrs, layoutIfMediaMatch); + } + + function unwatchMedia() { + ctrl.layoutDelegate = angular.noop; + + unwatchAttrs(); + for (var mediaName in $mdConstant.MEDIA) { + $mdMedia.getQuery($mdConstant.MEDIA[mediaName]) + .removeListener(invalidateLayout); + } + } + + /** + * Performs grid layout if the provided mediaName matches the currently + * active media type. + */ + function layoutIfMediaMatch(mediaName) { + if (mediaName == null) { + // TODO(shyndman): It would be nice to only layout if we have + // instances of attributes using this media type + ctrl.invalidateLayout(); + } else if ($mdMedia(mediaName)) { + ctrl.invalidateLayout(); + } + } + + var lastLayoutProps; + + /** + * Invokes the layout engine, and uses its results to lay out our + * tile elements. + * + * @param {boolean} tilesInvalidated Whether tiles have been + * added/removed/moved since the last layout. This is to avoid situations + * where tiles are replaced with properties identical to their removed + * counterparts. + */ + function layoutDelegate(tilesInvalidated) { + var tiles = getTileElements(); + var props = { + tileSpans: getTileSpans(tiles), + colCount: getColumnCount(), + rowMode: getRowMode(), + rowHeight: getRowHeight(), + gutter: getGutter() + }; + + if (!tilesInvalidated && angular.equals(props, lastLayoutProps)) { + return; + } + + var performance = + $mdGridLayout(props.colCount, props.tileSpans, tiles) + .map(function(tilePositions, rowCount) { + return { + grid: { + element: element, + style: getGridStyle(props.colCount, rowCount, + props.gutter, props.rowMode, props.rowHeight) + }, + tiles: tilePositions.map(function(ps, i) { + return { + element: angular.element(tiles[i]), + style: getTileStyle(ps.position, ps.spans, + props.colCount, rowCount, + props.gutter, props.rowMode, props.rowHeight) + }; + }) + }; + }) + .reflow() + .performance(); + + // Report layout + scope.mdOnLayout({ + $event: { + performance: performance + } + }); + + lastLayoutProps = props; + } + + // Use $interpolate to do some simple string interpolation as a convenience. + + var startSymbol = $interpolate.startSymbol(); + var endSymbol = $interpolate.endSymbol(); + + // Returns an expression wrapped in the interpolator's start and end symbols. + function expr(exprStr) { + return startSymbol + exprStr + endSymbol; + } + + // The amount of space a single 1x1 tile would take up (either width or height), used as + // a basis for other calculations. This consists of taking the base size percent (as would be + // if evenly dividing the size between cells), and then subtracting the size of one gutter. + // However, since there are no gutters on the edges, each tile only uses a fration + // (gutterShare = numGutters / numCells) of the gutter size. (Imagine having one gutter per + // tile, and then breaking up the extra gutter on the edge evenly among the cells). + var UNIT = $interpolate(expr('share') + '% - (' + expr('gutter') + ' * ' + expr('gutterShare') + ')'); + + // The horizontal or vertical position of a tile, e.g., the 'top' or 'left' property value. + // The position comes the size of a 1x1 tile plus gutter for each previous tile in the + // row/column (offset). + var POSITION = $interpolate('calc((' + expr('unit') + ' + ' + expr('gutter') + ') * ' + expr('offset') + ')'); + + // The actual size of a tile, e.g., width or height, taking rowSpan or colSpan into account. + // This is computed by multiplying the base unit by the rowSpan/colSpan, and then adding back + // in the space that the gutter would normally have used (which was already accounted for in + // the base unit calculation). + var DIMENSION = $interpolate('calc((' + expr('unit') + ') * ' + expr('span') + ' + (' + expr('span') + ' - 1) * ' + expr('gutter') + ')'); + + /** + * Gets the styles applied to a tile element described by the given parameters. + * @param {{row: number, col: number}} position The row and column indices of the tile. + * @param {{row: number, col: number}} spans The rowSpan and colSpan of the tile. + * @param {number} colCount The number of columns. + * @param {number} rowCount The number of rows. + * @param {string} gutter The amount of space between tiles. This will be something like + * '5px' or '2em'. + * @param {string} rowMode The row height mode. Can be one of: + * 'fixed': all rows have a fixed size, given by rowHeight, + * 'ratio': row height defined as a ratio to width, or + * 'fit': fit to the grid-list element height, divinding evenly among rows. + * @param {string|number} rowHeight The height of a row. This is only used for 'fixed' mode and + * for 'ratio' mode. For 'ratio' mode, this is the *ratio* of width-to-height (e.g., 0.75). + * @returns {Object} Map of CSS properties to be applied to the style element. Will define + * values for top, left, width, height, marginTop, and paddingTop. + */ + function getTileStyle(position, spans, colCount, rowCount, gutter, rowMode, rowHeight) { + // TODO(shyndman): There are style caching opportunities here. + + // Percent of the available horizontal space that one column takes up. + var hShare = (1 / colCount) * 100; + + // Fraction of the gutter size that each column takes up. + var hGutterShare = (colCount - 1) / colCount; + + // Base horizontal size of a column. + var hUnit = UNIT({share: hShare, gutterShare: hGutterShare, gutter: gutter}); + + // The width and horizontal position of each tile is always calculated the same way, but the + // height and vertical position depends on the rowMode. + var ltr = document.dir != 'rtl' && document.body.dir != 'rtl'; + var style = ltr ? { + left: POSITION({ unit: hUnit, offset: position.col, gutter: gutter }), + width: DIMENSION({ unit: hUnit, span: spans.col, gutter: gutter }), + // resets + paddingTop: '', + marginTop: '', + top: '', + height: '' + } : { + right: POSITION({ unit: hUnit, offset: position.col, gutter: gutter }), + width: DIMENSION({ unit: hUnit, span: spans.col, gutter: gutter }), + // resets + paddingTop: '', + marginTop: '', + top: '', + height: '' + }; + + switch (rowMode) { + case 'fixed': + // In fixed mode, simply use the given rowHeight. + style.top = POSITION({ unit: rowHeight, offset: position.row, gutter: gutter }); + style.height = DIMENSION({ unit: rowHeight, span: spans.row, gutter: gutter }); + break; + + case 'ratio': + // Percent of the available vertical space that one row takes up. Here, rowHeight holds + // the ratio value. For example, if the width:height ratio is 4:3, rowHeight = 1.333. + var vShare = hShare / rowHeight; + + // Base veritcal size of a row. + var vUnit = UNIT({ share: vShare, gutterShare: hGutterShare, gutter: gutter }); + + // padidngTop and marginTop are used to maintain the given aspect ratio, as + // a percentage-based value for these properties is applied to the *width* of the + // containing block. See http://www.w3.org/TR/CSS2/box.html#margin-properties + style.paddingTop = DIMENSION({ unit: vUnit, span: spans.row, gutter: gutter}); + style.marginTop = POSITION({ unit: vUnit, offset: position.row, gutter: gutter }); + break; + + case 'fit': + // Fraction of the gutter size that each column takes up. + var vGutterShare = (rowCount - 1) / rowCount; + + // Percent of the available vertical space that one row takes up. + vShare = (1 / rowCount) * 100; + + // Base vertical size of a row. + vUnit = UNIT({share: vShare, gutterShare: vGutterShare, gutter: gutter}); + + style.top = POSITION({unit: vUnit, offset: position.row, gutter: gutter}); + style.height = DIMENSION({unit: vUnit, span: spans.row, gutter: gutter}); + break; + } + + return style; + } + + function getGridStyle(colCount, rowCount, gutter, rowMode, rowHeight) { + var style = {}; + + switch (rowMode) { + case 'fixed': + style.height = DIMENSION({ unit: rowHeight, span: rowCount, gutter: gutter }); + style.paddingBottom = ''; + break; + + case 'ratio': + // rowHeight is width / height + var hGutterShare = colCount === 1 ? 0 : (colCount - 1) / colCount, + hShare = (1 / colCount) * 100, + vShare = hShare * (1 / rowHeight), + vUnit = UNIT({ share: vShare, gutterShare: hGutterShare, gutter: gutter }); + + style.height = ''; + style.paddingBottom = DIMENSION({ unit: vUnit, span: rowCount, gutter: gutter}); + break; + + case 'fit': + // noop, as the height is user set + break; + } + + return style; + } + + function getTileElements() { + return [].filter.call(element.children(), function(ele) { + return ele.tagName == 'MD-GRID-TILE' && !ele.$$mdDestroyed; + }); + } + + /** + * Gets an array of objects containing the rowspan and colspan for each tile. + * @returns {Array<{row: number, col: number}>} + */ + function getTileSpans(tileElements) { + return [].map.call(tileElements, function(ele) { + var ctrl = angular.element(ele).controller('mdGridTile'); + return { + row: parseInt( + $mdMedia.getResponsiveAttribute(ctrl.$attrs, 'md-rowspan'), 10) || 1, + col: parseInt( + $mdMedia.getResponsiveAttribute(ctrl.$attrs, 'md-colspan'), 10) || 1 + }; + }); + } + + function getColumnCount() { + var colCount = parseInt($mdMedia.getResponsiveAttribute(attrs, 'md-cols'), 10); + if (isNaN(colCount)) { + throw 'md-grid-list: md-cols attribute was not found, or contained a non-numeric value'; + } + return colCount; + } + + function getGutter() { + return applyDefaultUnit($mdMedia.getResponsiveAttribute(attrs, 'md-gutter') || 1); + } + + function getRowHeight() { + var rowHeight = $mdMedia.getResponsiveAttribute(attrs, 'md-row-height'); + if (!rowHeight) { + throw 'md-grid-list: md-row-height attribute was not found'; + } + + switch (getRowMode()) { + case 'fixed': + return applyDefaultUnit(rowHeight); + case 'ratio': + var whRatio = rowHeight.split(':'); + return parseFloat(whRatio[0]) / parseFloat(whRatio[1]); + case 'fit': + return 0; // N/A + } + } + + function getRowMode() { + var rowHeight = $mdMedia.getResponsiveAttribute(attrs, 'md-row-height'); + if (!rowHeight) { + throw 'md-grid-list: md-row-height attribute was not found'; + } + + if (rowHeight == 'fit') { + return 'fit'; + } else if (rowHeight.indexOf(':') !== -1) { + return 'ratio'; + } else { + return 'fixed'; + } + } + + function applyDefaultUnit(val) { + return /\D$/.test(val) ? val : val + 'px'; + } + } +} + +/* @ngInject */ +function GridListController($mdUtil) { + this.layoutInvalidated = false; + this.tilesInvalidated = false; + this.$timeout_ = $mdUtil.nextTick; + this.layoutDelegate = angular.noop; +} + +GridListController.prototype = { + invalidateTiles: function() { + this.tilesInvalidated = true; + this.invalidateLayout(); + }, + + invalidateLayout: function() { + if (this.layoutInvalidated) { + return; + } + this.layoutInvalidated = true; + this.$timeout_(angular.bind(this, this.layout)); + }, + + layout: function() { + try { + this.layoutDelegate(this.tilesInvalidated); + } finally { + this.layoutInvalidated = false; + this.tilesInvalidated = false; + } + } +}; + + +/* @ngInject */ +function GridLayoutFactory($mdUtil) { + var defaultAnimator = GridTileAnimator; + + /** + * Set the reflow animator callback + */ + GridLayout.animateWith = function(customAnimator) { + defaultAnimator = !angular.isFunction(customAnimator) ? GridTileAnimator : customAnimator; + }; + + return GridLayout; + + /** + * Publish layout function + */ + function GridLayout(colCount, tileSpans) { + var self, layoutInfo, gridStyles, layoutTime, mapTime, reflowTime; + + layoutTime = $mdUtil.time(function() { + layoutInfo = calculateGridFor(colCount, tileSpans); + }); + + return self = { + + /** + * An array of objects describing each tile's position in the grid. + */ + layoutInfo: function() { + return layoutInfo; + }, + + /** + * Maps grid positioning to an element and a set of styles using the + * provided updateFn. + */ + map: function(updateFn) { + mapTime = $mdUtil.time(function() { + var info = self.layoutInfo(); + gridStyles = updateFn(info.positioning, info.rowCount); + }); + return self; + }, + + /** + * Default animator simply sets the element.css( ). An alternate + * animator can be provided as an argument. The function has the following + * signature: + * + * function({grid: {element: JQLite, style: Object}, tiles: Array<{element: JQLite, style: Object}>) + */ + reflow: function(animatorFn) { + reflowTime = $mdUtil.time(function() { + var animator = animatorFn || defaultAnimator; + animator(gridStyles.grid, gridStyles.tiles); + }); + return self; + }, + + /** + * Timing for the most recent layout run. + */ + performance: function() { + return { + tileCount: tileSpans.length, + layoutTime: layoutTime, + mapTime: mapTime, + reflowTime: reflowTime, + totalTime: layoutTime + mapTime + reflowTime + }; + } + }; + } + + /** + * Default Gridlist animator simple sets the css for each element; + * NOTE: any transitions effects must be manually set in the CSS. + * e.g. + * + * md-grid-tile { + * transition: all 700ms ease-out 50ms; + * } + * + */ + function GridTileAnimator(grid, tiles) { + grid.element.css(grid.style); + tiles.forEach(function(t) { + t.element.css(t.style); + }); + } + + /** + * Calculates the positions of tiles. + * + * The algorithm works as follows: + * An Array with length colCount (spaceTracker) keeps track of + * available tiling positions, where elements of value 0 represents an + * empty position. Space for a tile is reserved by finding a sequence of + * 0s with length <= than the tile's colspan. When such a space has been + * found, the occupied tile positions are incremented by the tile's + * rowspan value, as these positions have become unavailable for that + * many rows. + * + * If the end of a row has been reached without finding space for the + * tile, spaceTracker's elements are each decremented by 1 to a minimum + * of 0. Rows are searched in this fashion until space is found. + */ + function calculateGridFor(colCount, tileSpans) { + var curCol = 0, + curRow = 0, + spaceTracker = newSpaceTracker(); + + return { + positioning: tileSpans.map(function(spans, i) { + return { + spans: spans, + position: reserveSpace(spans, i) + }; + }), + rowCount: curRow + Math.max.apply(Math, spaceTracker) + }; + + function reserveSpace(spans, i) { + if (spans.col > colCount) { + throw 'md-grid-list: Tile at position ' + i + ' has a colspan ' + + '(' + spans.col + ') that exceeds the column count ' + + '(' + colCount + ')'; + } + + var start = 0, + end = 0; + + // TODO(shyndman): This loop isn't strictly necessary if you can + // determine the minimum number of rows before a space opens up. To do + // this, recognize that you've iterated across an entire row looking for + // space, and if so fast-forward by the minimum rowSpan count. Repeat + // until the required space opens up. + while (end - start < spans.col) { + if (curCol >= colCount) { + nextRow(); + continue; + } + + start = spaceTracker.indexOf(0, curCol); + if (start === -1 || (end = findEnd(start + 1)) === -1) { + start = end = 0; + nextRow(); + continue; + } + + curCol = end + 1; + } + + adjustRow(start, spans.col, spans.row); + curCol = start + spans.col; + + return { + col: start, + row: curRow + }; + } + + function nextRow() { + curCol = 0; + curRow++; + adjustRow(0, colCount, -1); // Decrement row spans by one + } + + function adjustRow(from, cols, by) { + for (var i = from; i < from + cols; i++) { + spaceTracker[i] = Math.max(spaceTracker[i] + by, 0); + } + } + + function findEnd(start) { + var i; + for (i = start; i < spaceTracker.length; i++) { + if (spaceTracker[i] !== 0) { + return i; + } + } + + if (i === spaceTracker.length) { + return i; + } + } + + function newSpaceTracker() { + var tracker = []; + for (var i = 0; i < colCount; i++) { + tracker.push(0); + } + return tracker; + } + } +} + +/** + * @ngdoc directive + * @name mdGridTile + * @module material.components.gridList + * @restrict E + * @description + * Tiles contain the content of an `md-grid-list`. They span one or more grid + * cells vertically or horizontally, and use `md-grid-tile-{footer,header}` to + * display secondary content. + * + * ### Responsive Attributes + * + * The `md-grid-tile` directive supports "responsive" attributes, which allow + * different `md-rowspan` and `md-colspan` values depending on the currently + * matching media query. + * + * In order to set a responsive attribute, first define the fallback value with + * the standard attribute name, then add additional attributes with the + * following convention: `{base-attribute-name}-{media-query-name}="{value}"` + * (ie. `md-colspan-sm="4"`) + * + * @param {number=} md-colspan The number of columns to span (default 1). Cannot + * exceed the number of columns in the grid. Supports interpolation. + * @param {number=} md-rowspan The number of rows to span (default 1). Supports + * interpolation. + * + * @usage + * With header: + * + * + * + *

    This is a header

    + *
    + *
    + *
    + * + * With footer: + * + * + * + *

    This is a footer

    + *
    + *
    + *
    + * + * Spanning multiple rows/columns: + * + * + * + * + * + * Responsive attributes: + * + * + * + * + */ +function GridTileDirective($mdMedia) { + return { + restrict: 'E', + require: '^mdGridList', + template: '
    ', + transclude: true, + scope: {}, + // Simple controller that exposes attributes to the grid directive + controller: ["$attrs", function($attrs) { + this.$attrs = $attrs; + }], + link: postLink + }; + + function postLink(scope, element, attrs, gridCtrl) { + // Apply semantics + element.attr('role', 'listitem'); + + // If our colspan or rowspan changes, trigger a layout + var unwatchAttrs = $mdMedia.watchResponsiveAttributes(['md-colspan', 'md-rowspan'], + attrs, angular.bind(gridCtrl, gridCtrl.invalidateLayout)); + + // Tile registration/deregistration + gridCtrl.invalidateTiles(); + scope.$on('$destroy', function() { + // Mark the tile as destroyed so it is no longer considered in layout, + // even if the DOM element sticks around (like during a leave animation) + element[0].$$mdDestroyed = true; + unwatchAttrs(); + gridCtrl.invalidateLayout(); + }); + + if (angular.isDefined(scope.$parent.$index)) { + scope.$watch(function() { return scope.$parent.$index; }, + function indexChanged(newIdx, oldIdx) { + if (newIdx === oldIdx) { + return; + } + gridCtrl.invalidateTiles(); + }); + } + } +} + + +function GridTileCaptionDirective() { + return { + template: '
    ', + transclude: true + }; +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.icon + * @description + * Icon + */ +angular.module('material.components.icon', ['material.core']); + +})(); +(function(){ +"use strict"; + +angular + .module('material.components.icon') + .directive('mdIcon', ['$mdIcon', '$mdTheming', '$mdAria', '$sce', mdIconDirective]); + +/** + * @ngdoc directive + * @name mdIcon + * @module material.components.icon + * + * @restrict E + * + * @description + * The `md-icon` directive makes it easier to use vector-based icons in your app (as opposed to + * raster-based icons types like PNG). The directive supports both icon fonts and SVG icons. + * + * Icons should be considered view-only elements that should not be used directly as buttons; instead nest a `` + * inside a `md-button` to add hover and click features. + * + * ### Icon fonts + * Icon fonts are a technique in which you use a font where the glyphs in the font are + * your icons instead of text. Benefits include a straightforward way to bundle everything into a + * single HTTP request, simple scaling, easy color changing, and more. + * + * `md-icon` lets you consume an icon font by letting you reference specific icons in that font + * by name rather than character code. + * + * When using font-icons, developers must follow three (3) simple steps: + * + *
      + *
    1. Load the font library. e.g.
      + * `` + *
    2. + *
    3. + * Use either (a) font-icon class names or (b) a fontset and a font ligature to render the font glyph by + * using its textual name _or_ numerical character reference. Note that `material-icons` is the default fontset when + * none is specified. + *
    4. + *
    5. Use any of the following templates:
      + *
        + *
      • ``
      • + *
      • `textual_name`
      • + *
      • ` numerical_character_reference `
      • + *
      • ``
      • + *
      • ``
      • + *
      + *
    6. + *
    + * + * Full details for these steps can be found in the + * + * Material Design Icon font for the web docs. + * + * You can browse and search the Material Design icon style .material-icons + * in the Material Design Icons tool. + * + * ### SVG + * For SVGs, the problem with using `` or a CSS `background-image` is that you can't take + * advantage of some SVG features, such as styling specific parts of the icon with CSS or SVG + * animation. + * + * `md-icon` makes it easier to use SVG icons by *inlining* the SVG into an `` element in the + * document. The most straightforward way of referencing an SVG icon is via URL, just like a + * traditional ``. `$mdIconProvider`, as a convenience, lets you _name_ an icon so you can + * reference it by name instead of URL throughout your templates. + * + * Additionally, you may not want to make separate HTTP requests for every icon, so you can bundle + * your SVG icons together and pre-load them with `$mdIconProvider` as an icon set. An icon set can + * also be given a name, which acts as a namespace for individual icons, so you can reference them + * like `"social:cake"`. + * + * When using SVGs, both external SVGs (via URLs) or sets of SVGs (from icon sets) can be + * easily loaded and used. + * + * ### Localization + * + * Because an `md-icon` element's text content is not intended to be translated, it is recommended + * to declare the text content for an `md-icon` element in its start tag. Instead of using the HTML + * text content, consider using `ng-bind` with a scope variable or literal string. + * + * Examples: + * + *
      + *
    • ``
    • + *
    • `` + *
    + * + *

    Material Design Icons tool

    + * Using the Material Design Icons tool, developers can easily and quickly search for a specific + * open source Material Design icon. The search is in the top left. Below search, you can select + * from the new icon themes or filter by icon category. + * + * + * + * + * + *
    + * Click on the image above to open the + * Material Design Icons tool. + *
    + * + * Click on any icon, then click on the "Selected Icon" chevron to see the slide-up + * information panel with details regarding a SVG download and information on the font-icon's + * textual name. This panel also allows you to select a black on transparent or white on transparent + * icon and to change the icon size. These settings only affect the downloaded icons. + * + * @param {string} md-font-icon String name of CSS icon associated with the font-face will be used + * to render the icon. Requires the fonts and the named CSS styles to be preloaded. + * @param {string} md-font-set CSS style name associated with the font library; which will be assigned as + * the class for the font-icon ligature. This value may also be an alias that is used to lookup the classname; + * internally use `$mdIconProvider.fontSet()` to determine the style name. + * @param {string} md-svg-src String URL (or expression) used to load, cache, and display an + * external SVG. + * @param {string} md-svg-icon md-svg-icon String name used for lookup of the icon from the internal cache; + * interpolated strings or expressions may also be used. Specific set names can be used with + * the syntax `:`.

    + * To use icon sets, developers are required to pre-register the sets using the `$mdIconProvider` service. + * @param {string=} aria-label Labels icon for accessibility. If an empty string is provided, icon + * will be hidden from accessibility layer with `aria-hidden="true"`. If there's no aria-label on the icon + * nor a label on the parent element, a warning will be logged to the console. + * @param {string=} alt Labels icon for accessibility. If an empty string is provided, icon + * will be hidden from accessibility layer with `aria-hidden="true"`. If there's no alt on the icon + * nor a label on the parent element, a warning will be logged to the console. + * + * @usage + * When using SVGs: + * + * + * + * + * + * + * + * + * + * + * + * Use the $mdIconProvider to configure your application with + * SVG icon sets. + * + * + * angular.module('appSvgIconSets', ['ngMaterial']) + * .controller('DemoCtrl', function($scope) {}) + * .config(function($mdIconProvider) { + * $mdIconProvider + * .iconSet('social', 'img/icons/sets/social-icons.svg', 24) + * .defaultIconSet('img/icons/sets/core-icons.svg', 24); + * }); + * + * + * + * When using Font Icons with classnames: + * + * + * + * + * + * + * + * When using Material Font Icons with ligatures: + * + * + * face + * + * face + * + * + * + * face + * + * + * When using other Font-Icon libraries: + * + * + * // Specify a font-icon style alias + * angular.config(function($mdIconProvider) { + * $mdIconProvider.fontSet('md', 'material-icons'); + * }); + * + * + * + * favorite + * + * + */ +function mdIconDirective($mdIcon, $mdTheming, $mdAria, $sce) { + + return { + restrict: 'E', + link : postLink + }; + + + /** + * Directive postLink + * Supports embedded SVGs, font-icons, & external SVGs + */ + function postLink(scope, element, attr) { + $mdTheming(element); + var lastFontIcon = attr.mdFontIcon; + var lastFontSet = $mdIcon.fontSet(attr.mdFontSet); + + prepareForFontIcon(); + + attr.$observe('mdFontIcon', fontIconChanged); + attr.$observe('mdFontSet', fontIconChanged); + + // Keep track of the content of the svg src so we can compare against it later to see if the + // attribute is static (and thus safe). + var originalSvgSrc = element[0].getAttribute(attr.$attr.mdSvgSrc); + + // If using a font-icon, then the textual name of the icon itself + // provides the aria-label. + + var attrName = attr.$normalize(attr.$attr.mdSvgIcon || attr.$attr.mdSvgSrc || ''); + + /* Provide a default accessibility role of img */ + if (!attr.role) { + $mdAria.expect(element, 'role', 'img'); + /* manually update attr variable */ + attr.role = 'img'; + } + + /* Don't process ARIA if already valid */ + if (attr.role === "img" && !attr.ariaHidden && !$mdAria.hasAriaLabel(element)) { + var iconName; + if (attr.alt) { + /* Use alt text by default if available */ + $mdAria.expect(element, 'aria-label', attr.alt); + } else if ($mdAria.parentHasAriaLabel(element, 2)) { + /* Parent has ARIA so we will assume it will describe the image */ + $mdAria.expect(element, 'aria-hidden', 'true'); + } else if (iconName = (attr.mdFontIcon || attr.mdSvgIcon || element.text())) { + /* Use icon name as aria-label */ + $mdAria.expect(element, 'aria-label', iconName); + } else { + /* No label found */ + $mdAria.expect(element, 'aria-hidden', 'true'); + } + } + + if (attrName) { + // Use either pre-configured SVG or URL source, respectively. + attr.$observe(attrName, function(attrVal) { + element.empty(); + if (attrVal) { + $mdIcon(attrVal) + .then(function(svg) { + element.empty(); + element.append(svg); + }); + } + }); + } + + function prepareForFontIcon() { + if (!attr.mdSvgIcon && !attr.mdSvgSrc) { + if (attr.mdFontIcon) { + element.addClass('md-font ' + attr.mdFontIcon); + } + + element.addClass(lastFontSet); + } + } + + function fontIconChanged() { + if (!attr.mdSvgIcon && !attr.mdSvgSrc) { + if (attr.mdFontIcon) { + element.removeClass(lastFontIcon); + element.addClass(attr.mdFontIcon); + + lastFontIcon = attr.mdFontIcon; + } + + var fontSet = $mdIcon.fontSet(attr.mdFontSet); + + if (lastFontSet !== fontSet) { + element.removeClass(lastFontSet); + element.addClass(fontSet); + + lastFontSet = fontSet; + } + } + } + } +} + +})(); +(function(){ +"use strict"; + + +MdIconService.$inject = ["config", "$templateRequest", "$q", "$log", "$mdUtil", "$sce"];angular + .module('material.components.icon') + .constant('$$mdSvgRegistry', { + 'mdTabsArrow': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwb2x5Z29uIHBvaW50cz0iMTUuNCw3LjQgMTQsNiA4LDEyIDE0LDE4IDE1LjQsMTYuNiAxMC44LDEyICIvPjwvZz48L3N2Zz4=', + 'mdClose': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik0xOSA2LjQxbC0xLjQxLTEuNDEtNS41OSA1LjU5LTUuNTktNS41OS0xLjQxIDEuNDEgNS41OSA1LjU5LTUuNTkgNS41OSAxLjQxIDEuNDEgNS41OS01LjU5IDUuNTkgNS41OSAxLjQxLTEuNDEtNS41OS01LjU5eiIvPjwvZz48L3N2Zz4=', + 'mdCancel': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik0xMiAyYy01LjUzIDAtMTAgNC40Ny0xMCAxMHM0LjQ3IDEwIDEwIDEwIDEwLTQuNDcgMTAtMTAtNC40Ny0xMC0xMC0xMHptNSAxMy41OWwtMS40MSAxLjQxLTMuNTktMy41OS0zLjU5IDMuNTktMS40MS0xLjQxIDMuNTktMy41OS0zLjU5LTMuNTkgMS40MS0xLjQxIDMuNTkgMy41OSAzLjU5LTMuNTkgMS40MSAxLjQxLTMuNTkgMy41OSAzLjU5IDMuNTl6Ii8+PC9nPjwvc3ZnPg==', + 'mdMenu': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGQ9Ik0zLDZIMjFWOEgzVjZNMywxMUgyMVYxM0gzVjExTTMsMTZIMjFWMThIM1YxNloiIC8+PC9zdmc+', + 'mdToggleArrow': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgNDggNDgiPjxwYXRoIGQ9Ik0yNCAxNmwtMTIgMTIgMi44MyAyLjgzIDkuMTctOS4xNyA5LjE3IDkuMTcgMi44My0yLjgzeiIvPjxwYXRoIGQ9Ik0wIDBoNDh2NDhoLTQ4eiIgZmlsbD0ibm9uZSIvPjwvc3ZnPg==', + 'mdCalendar': 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTkgM2gtMVYxaC0ydjJIOFYxSDZ2Mkg1Yy0xLjExIDAtMS45OS45LTEuOTkgMkwzIDE5YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjVjMC0xLjEtLjktMi0yLTJ6bTAgMTZINVY4aDE0djExek03IDEwaDV2NUg3eiIvPjwvc3ZnPg==', + 'mdChecked': 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxnPjxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiLz48L2c+PC9zdmc+' + }) + .provider('$mdIcon', MdIconProvider); + +/** + * @ngdoc service + * @name $mdIconProvider + * @module material.components.icon + * + * @description + * `$mdIconProvider` is used only to register icon IDs with URLs. These configuration features allow + * icons and icon sets to be pre-registered and associated with source URLs **before** the `` + * directives are compiled. + * + * If using font-icons, the developer is responsible for loading the fonts. + * + * If using SVGs, loading of the actual svg files are deferred to on-demand requests and are loaded + * internally by the `$mdIcon` service using the `$templateRequest` service. When an SVG is + * requested by name/ID, the `$mdIcon` service searches its registry for the associated source URL; + * that URL is used to on-demand load and parse the SVG dynamically. + * + * The `$templateRequest` service expects the icons source to be loaded over trusted URLs.
    + * This means, when loading icons from an external URL, you have to trust the URL in the `$sceDelegateProvider`. + * + * + * app.config(function($sceDelegateProvider) { + * $sceDelegateProvider.resourceUrlWhitelist([ + * // Adding 'self' to the whitelist, will allow requests from the current origin. + * 'self', + * // Using double asterisks here, will allow all URLs to load. + * // We recommend to only specify the given domain you want to allow. + * '**' + * ]); + * }); + * + * + * Read more about the [$sceDelegateProvider](https://docs.angularjs.org/api/ng/provider/$sceDelegateProvider). + * + * **Notice:** Most font-icons libraries do not support ligatures (for example `fontawesome`).
    + * In such cases you are not able to use the icon's ligature name - Like so: + * + * + * fa-bell + * + * + * You should instead use the given unicode, instead of the ligature name. + * + *

    ##// Notice we can't use a hljs element here, because the characters will be escaped.

    + * ```html + * + * ``` + * + * All unicode ligatures are prefixed with the `&#x` string. + * + * @usage + * + * app.config(function($mdIconProvider) { + * + * // Configure URLs for icons specified by [set:]id. + * + * $mdIconProvider + * .defaultFontSet( 'fa' ) // This sets our default fontset className. + * .defaultIconSet('my/app/icons.svg') // Register a default set of SVG icons + * .iconSet('social', 'my/app/social.svg') // Register a named icon set of SVGs + * .icon('android', 'my/app/android.svg') // Register a specific icon (by name) + * .icon('work:chair', 'my/app/chair.svg'); // Register icon in a specific set + * }); + * + * + * SVG icons and icon sets can be easily pre-loaded and cached using either (a) a build process or (b) a runtime + * **startup** process (shown below): + * + * + * app.config(function($mdIconProvider) { + * + * // Register a default set of SVG icon definitions + * $mdIconProvider.defaultIconSet('my/app/icons.svg') + * + * }) + * .run(function($templateRequest){ + * + * // Pre-fetch icons sources by URL and cache in the $templateCache... + * // subsequent $templateRequest calls will look there first. + * + * var urls = [ 'imy/app/icons.svg', 'img/icons/android.svg']; + * + * angular.forEach(urls, function(url) { + * $templateRequest(url); + * }); + * + * }); + * + * + * + * > Note: The loaded SVG data is subsequently cached internally for future requests. + * + */ + +/** + * @ngdoc method + * @name $mdIconProvider#icon + * + * @description + * Register a source URL for a specific icon name; the name may include optional 'icon set' name prefix. + * These icons will later be retrieved from the cache using `$mdIcon( )` + * + * @param {string} id Icon name/id used to register the icon + * @param {string} url specifies the external location for the data file. Used internally by + * `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading + * was configured. + * @param {number=} viewBoxSize Sets the width and height the icon's viewBox. + * It is ignored for icons with an existing viewBox. Default size is 24. + * + * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API + * + * @usage + * + * app.config(function($mdIconProvider) { + * + * // Configure URLs for icons specified by [set:]id. + * + * $mdIconProvider + * .icon('android', 'my/app/android.svg') // Register a specific icon (by name) + * .icon('work:chair', 'my/app/chair.svg'); // Register icon in a specific set + * }); + * + * + */ +/** + * @ngdoc method + * @name $mdIconProvider#iconSet + * + * @description + * Register a source URL for a 'named' set of icons; group of SVG definitions where each definition + * has an icon id. Individual icons can be subsequently retrieved from this cached set using + * `$mdIcon(:)` + * + * @param {string} id Icon name/id used to register the iconset + * @param {string} url specifies the external location for the data file. Used internally by + * `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading + * was configured. + * @param {number=} viewBoxSize Sets the width and height of the viewBox of all icons in the set. + * It is ignored for icons with an existing viewBox. All icons in the icon set should be the same size. + * Default value is 24. + * + * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API + * + * + * @usage + * + * app.config(function($mdIconProvider) { + * + * // Configure URLs for icons specified by [set:]id. + * + * $mdIconProvider + * .iconSet('social', 'my/app/social.svg') // Register a named icon set + * }); + * + * + */ +/** + * @ngdoc method + * @name $mdIconProvider#defaultIconSet + * + * @description + * Register a source URL for the default 'named' set of icons. Unless explicitly registered, + * subsequent lookups of icons will failover to search this 'default' icon set. + * Icon can be retrieved from this cached, default set using `$mdIcon()` + * + * @param {string} url specifies the external location for the data file. Used internally by + * `$templateRequest` to load the data or as part of the lookup in `$templateCache` if pre-loading + * was configured. + * @param {number=} viewBoxSize Sets the width and height of the viewBox of all icons in the set. + * It is ignored for icons with an existing viewBox. All icons in the icon set should be the same size. + * Default value is 24. + * + * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API + * + * @usage + * + * app.config(function($mdIconProvider) { + * + * // Configure URLs for icons specified by [set:]id. + * + * $mdIconProvider + * .defaultIconSet( 'my/app/social.svg' ) // Register a default icon set + * }); + * + * + */ +/** + * @ngdoc method + * @name $mdIconProvider#defaultFontSet + * + * @description + * When using Font-Icons, AngularJS Material assumes the the Material Design icons will be used and automatically + * configures the default font-set == 'material-icons'. Note that the font-set references the font-icon library + * class style that should be applied to the ``. + * + * Configuring the default means that the attributes + * `md-font-set="material-icons"` or `class="material-icons"` do not need to be explicitly declared on the + * `` markup. For example: + * + * ` face ` + * will render as + * ` face `, and + * + * ` face ` + * will render as + * ` face ` + * + * @param {string} name of the font-library style that should be applied to the md-icon DOM element + * + * @usage + * + * app.config(function($mdIconProvider) { + * $mdIconProvider.defaultFontSet( 'fa' ); + * }); + * + * + */ + +/** + * @ngdoc method + * @name $mdIconProvider#fontSet + * + * @description + * When using a font set for `` you must specify the correct font classname in the `md-font-set` + * attribute. If the fonset className is really long, your markup may become cluttered... an easy + * solution is to define an `alias` for your fontset: + * + * @param {string} alias of the specified fontset. + * @param {string} className of the fontset. + * + * @usage + * + * app.config(function($mdIconProvider) { + * // In this case, we set an alias for the `material-icons` fontset. + * $mdIconProvider.fontSet('md', 'material-icons'); + * }); + * + * + */ + +/** + * @ngdoc method + * @name $mdIconProvider#defaultViewBoxSize + * + * @description + * While `` markup can also be style with sizing CSS, this method configures + * the default width **and** height used for all icons; unless overridden by specific CSS. + * The default sizing is (24px, 24px). + * @param {number=} viewBoxSize Sets the width and height of the viewBox for an icon or an icon set. + * All icons in a set should be the same size. The default value is 24. + * + * @returns {obj} an `$mdIconProvider` reference; used to support method call chains for the API + * + * @usage + * + * app.config(function($mdIconProvider) { + * + * // Configure URLs for icons specified by [set:]id. + * + * $mdIconProvider + * .defaultViewBoxSize(36) // Register a default icon size (width == height) + * }); + * + * + */ + +var config = { + defaultViewBoxSize: 24, + defaultFontSet: 'material-icons', + fontSets: [] +}; + +function MdIconProvider() { +} + +MdIconProvider.prototype = { + icon: function(id, url, viewBoxSize) { + if (id.indexOf(':') == -1) id = '$default:' + id; + + config[id] = new ConfigurationItem(url, viewBoxSize); + return this; + }, + + iconSet: function(id, url, viewBoxSize) { + config[id] = new ConfigurationItem(url, viewBoxSize); + return this; + }, + + defaultIconSet: function(url, viewBoxSize) { + var setName = '$default'; + + if (!config[setName]) { + config[setName] = new ConfigurationItem(url, viewBoxSize); + } + + config[setName].viewBoxSize = viewBoxSize || config.defaultViewBoxSize; + + return this; + }, + + defaultViewBoxSize: function(viewBoxSize) { + config.defaultViewBoxSize = viewBoxSize; + return this; + }, + + /** + * Register an alias name associated with a font-icon library style ; + */ + fontSet: function fontSet(alias, className) { + config.fontSets.push({ + alias: alias, + fontSet: className || alias + }); + return this; + }, + + /** + * Specify a default style name associated with a font-icon library + * fallback to Material Icons. + * + */ + defaultFontSet: function defaultFontSet(className) { + config.defaultFontSet = !className ? '' : className; + return this; + }, + + defaultIconSize: function defaultIconSize(iconSize) { + config.defaultIconSize = iconSize; + return this; + }, + + $get: ['$templateRequest', '$q', '$log', '$mdUtil', '$sce', function($templateRequest, $q, $log, $mdUtil, $sce) { + return MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce); + }] +}; + + /** + * Configuration item stored in the Icon registry; used for lookups + * to load if not already cached in the `loaded` cache + * @param {string} url + * @param {=number} viewBoxSize + * @constructor + */ + function ConfigurationItem(url, viewBoxSize) { + this.url = url; + this.viewBoxSize = viewBoxSize || config.defaultViewBoxSize; + } + +/** + * @ngdoc service + * @name $mdIcon + * @module material.components.icon + * + * @description + * The `$mdIcon` service is a function used to lookup SVG icons. + * + * @param {string} id Query value for a unique Id or URL. If the argument is a URL, then the service will retrieve the icon element + * from its internal cache or load the icon and cache it first. If the value is not a URL-type string, then an ID lookup is + * performed. The Id may be a unique icon ID or may include an iconSet ID prefix. + * + * For the **id** query to work properly, this means that all id-to-URL mappings must have been previously configured + * using the `$mdIconProvider`. + * + * @returns {angular.$q.Promise} A promise that gets resolved to a clone of the initial SVG DOM element; which was + * created from the SVG markup in the SVG data file. If an error occurs (e.g. the icon cannot be found) the promise + * will get rejected. + * + * @usage + * + * function SomeDirective($mdIcon) { + * + * // See if the icon has already been loaded, if not + * // then lookup the icon from the registry cache, load and cache + * // it for future requests. + * // NOTE: ID queries require configuration with $mdIconProvider + * + * $mdIcon('android').then(function(iconEl) { element.append(iconEl); }); + * $mdIcon('work:chair').then(function(iconEl) { element.append(iconEl); }); + * + * // Load and cache the external SVG using a URL + * + * $mdIcon('img/icons/android.svg').then(function(iconEl) { + * element.append(iconEl); + * }); + * }; + * + * + * > Note: The `` directive internally uses the `$mdIcon` service to query, load, + * and instantiate SVG DOM elements. + */ + +/* @ngInject */ +function MdIconService(config, $templateRequest, $q, $log, $mdUtil, $sce) { + var iconCache = {}; + var svgCache = {}; + var urlRegex = /[-\w@:%+.~#?&//=]{2,}\.[a-z]{2,4}\b(\/[-\w@:%+.~#?&//=]*)?/i; + var dataUrlRegex = /^data:image\/svg\+xml[\s*;\w\-=]*?(base64)?,(.*)$/i; + + Icon.prototype = {clone: cloneSVG, prepare: prepareAndStyle}; + getIcon.fontSet = findRegisteredFontSet; + + // Publish service... + return getIcon; + + /** + * Actual $mdIcon service is essentially a lookup function + * @param {*} id $sce trust wrapper over a URL string, URL, icon registry id, or icon set id + * @returns {angular.$q.Promise} + */ + function getIcon(id) { + id = id || ''; + + // If the "id" provided is not a string, the only other valid value is a $sce trust wrapper + // over a URL string. If the value is not trusted, this will intentionally throw an error + // because the user is attempted to use an unsafe URL, potentially opening themselves up + // to an XSS attack. + if (!angular.isString(id)) { + id = $sce.getTrustedUrl(id); + } + + // If already loaded and cached, use a clone of the cached icon. + // Otherwise either load by URL, or lookup in the registry and then load by URL, and cache. + + if (iconCache[id]) { + return $q.when(transformClone(iconCache[id])); + } + + if (urlRegex.test(id) || dataUrlRegex.test(id)) { + return loadByURL(id).then(cacheIcon(id)); + } + + if (id.indexOf(':') === -1) { + id = '$default:' + id; + } + + var load = config[id] ? loadByID : loadFromIconSet; + return load(id) + .then(cacheIcon(id)); + } + + /** + * Lookup a registered fontSet style using its alias. + * @param {string} alias used to lookup the alias in the array of fontSets + * @returns {*} matching fontSet or the defaultFontSet if that alias does not match + */ + function findRegisteredFontSet(alias) { + var useDefault = angular.isUndefined(alias) || !(alias && alias.length); + if (useDefault) { + return config.defaultFontSet; + } + + var result = alias; + angular.forEach(config.fontSets, function(fontSet) { + if (fontSet.alias === alias) { + result = fontSet.fontSet || result; + } + }); + + return result; + } + + /** + * @param {!Icon} cacheElement cached icon from the iconCache + * @returns {Icon} cloned Icon element with unique ids + */ + function transformClone(cacheElement) { + var clone = cacheElement.clone(); + var newUid = $mdUtil.nextUid(); + var cacheSuffix, svgUrlQuerySelector, i, xlinkHrefValue; + // These are SVG attributes that can reference element ids. + var svgUrlAttributes = [ + 'clip-path', 'color-profile', 'cursor', 'fill', 'filter', 'href', 'marker-start', + 'marker-mid', 'marker-end', 'mask', 'stroke', 'style', 'vector-effect' + ]; + var isIeSvg = clone.innerHTML === undefined; + + // Verify that the newUid only contains a number and not some XSS content. + if (!isFinite(Number(newUid))) { + throw new Error('Unsafe and unexpected non-number result from $mdUtil.nextUid().'); + } + cacheSuffix = '_cache' + newUid; + + // For each cached icon, we need to modify the id attributes and references. + // This is needed because SVG ids are treated as normal DOM ids and should not be duplicated on + // the page. + if (clone.id) { + clone.id += cacheSuffix; + } + + // Do as much as possible with querySelectorAll as it provides much greater performance + // than RegEx against serialized DOM. + angular.forEach(clone.querySelectorAll('[id]'), function(descendantElem) { + svgUrlQuerySelector = ''; + for (i = 0; i < svgUrlAttributes.length; i++) { + svgUrlQuerySelector += '[' + svgUrlAttributes[i] + '="url(#' + descendantElem.id + ')"]'; + if (i + 1 < svgUrlAttributes.length) { + svgUrlQuerySelector += ', '; + } + } + // Append the cacheSuffix to references of the element's id within url(#id) calls. + angular.forEach(clone.querySelectorAll(svgUrlQuerySelector), function(refItem) { + updateSvgIdReferences(descendantElem, refItem, isIeSvg, newUid); + }); + // Handle usages of url(#id) in the SVG's stylesheets + angular.forEach(clone.querySelectorAll('style'), function(refItem) { + updateSvgIdReferences(descendantElem, refItem, isIeSvg, newUid); + }); + + // Update ids referenced by the deprecated (in SVG v2) xlink:href XML attribute. The now + // preferred href attribute is handled above. However, this non-standard XML namespaced + // attribute cannot be handled in the same way. Explanation of this query selector here: + // https://stackoverflow.com/q/23034283/633107. + angular.forEach(clone.querySelectorAll('[*|href]:not([href])'), function(refItem) { + xlinkHrefValue = refItem.getAttribute('xlink:href'); + if (xlinkHrefValue) { + xlinkHrefValue = xlinkHrefValue.replace("#" + descendantElem.id, "#" + descendantElem.id + cacheSuffix); + refItem.setAttribute('xlink:href', xlinkHrefValue); + } + }); + + descendantElem.id += cacheSuffix; + }); + + return clone; + } + + /** + * @param {Element} referencedElement element w/ id that needs to be updated + * @param {Element} referencingElement element that references the original id + * @param {boolean} isIeSvg true if we're dealing with an SVG in IE11, false otherwise + * @param {string} newUid the cache id to add as part of the cache suffix + */ + function updateSvgIdReferences(referencedElement, referencingElement, isIeSvg, newUid) { + var svgElement, cacheSuffix; + + // Verify that the newUid only contains a number and not some XSS content. + if (!isFinite(Number(newUid))) { + throw new Error('Unsafe and unexpected non-number result for newUid.'); + } + cacheSuffix = '_cache' + newUid; + + // outerHTML of SVG elements is not supported by IE11 + if (isIeSvg) { + svgElement = $mdUtil.getOuterHTML(referencingElement); + svgElement = svgElement.replace("url(#" + referencedElement.id + ")", + "url(#" + referencedElement.id + cacheSuffix + ")"); + referencingElement.textContent = angular.element(svgElement)[0].innerHTML; + } else { + // This use of outerHTML should be safe from XSS attack since we are only injecting the + // cacheSuffix with content from $mdUtil.nextUid which we verify is a finite number above. + referencingElement.outerHTML = referencingElement.outerHTML.replace( + "url(#" + referencedElement.id + ")", + "url(#" + referencedElement.id + cacheSuffix + ")"); + } + } + + /** + * Prepare and cache the loaded icon for the specified `id`. + * @param {string} id icon cache id + * @returns {function(*=): *} + */ + function cacheIcon(id) { + + return function updateCache(icon) { + iconCache[id] = isIcon(icon) ? icon : new Icon(icon, config[id]); + + return transformClone(iconCache[id]); + }; + } + + /** + * Lookup the configuration in the registry, if !registered throw an error + * otherwise load the icon [on-demand] using the registered URL. + * @param {string} id icon registry id + * @returns {angular.$q.Promise} + */ + function loadByID(id) { + var iconConfig = config[id]; + return loadByURL(iconConfig.url).then(function(icon) { + return new Icon(icon, iconConfig); + }); + } + + /** + * Loads the file as XML and uses querySelector( ) to find the desired node... + * @param {string} id icon id in icon set + * @returns {angular.$q.Promise} + */ + function loadFromIconSet(id) { + var setName = id.substring(0, id.lastIndexOf(':')) || '$default'; + var iconSetConfig = config[setName]; + + return !iconSetConfig ? announceIdNotFound(id) : loadByURL(iconSetConfig.url).then(extractFromSet); + + function extractFromSet(set) { + var iconName = id.slice(id.lastIndexOf(':') + 1); + var icon = set.querySelector('#' + iconName); + return icon ? new Icon(icon, iconSetConfig) : announceIdNotFound(id); + } + + function announceIdNotFound(id) { + var msg = 'icon ' + id + ' not found'; + $log.warn(msg); + + return $q.reject(msg || id); + } + } + + /** + * Load the icon by URL (may use the $templateCache). + * Extract the data for later conversion to Icon + * @param {string} url icon URL + * @returns {angular.$q.Promise} + */ + function loadByURL(url) { + /* Load the icon from embedded data URL. */ + function loadByDataUrl(url) { + var results = dataUrlRegex.exec(url); + var isBase64 = /base64/i.test(url); + var data = isBase64 ? window.atob(results[2]) : results[2]; + + return $q.when(angular.element(data)[0]); + } + + /* Load the icon by URL using HTTP. */ + function loadByHttpUrl(url) { + return $q(function(resolve, reject) { + // Catch HTTP or generic errors not related to incorrect icon IDs. + var announceAndReject = function(err) { + var msg = angular.isString(err) ? err : (err.message || err.data || err.statusText); + $log.warn(msg); + reject(err); + }, + extractSvg = function(response) { + if (!svgCache[url]) { + svgCache[url] = angular.element('
    ').append(response)[0].querySelector('svg'); + } + resolve(svgCache[url]); + }; + + $templateRequest(url, true).then(extractSvg, announceAndReject); + }); + } + + return dataUrlRegex.test(url) + ? loadByDataUrl(url) + : loadByHttpUrl(url); + } + + /** + * Check target signature to see if it is an Icon instance. + * @param {Icon|Element} target + * @returns {boolean} true if the specified target is an Icon object, false otherwise. + */ + function isIcon(target) { + return angular.isDefined(target.element) && angular.isDefined(target.config); + } + + /** + * Define the Icon class + * @param {Element} el + * @param {=ConfigurationItem} config + * @constructor + */ + function Icon(el, config) { + // If the node is a , it won't be rendered so we have to convert it into . + if (el && el.tagName.toLowerCase() === 'symbol') { + var viewbox = el.getAttribute('viewBox'); + // // Check if innerHTML is supported as IE11 does not support innerHTML on SVG elements. + if (el.innerHTML) { + el = angular.element('') + .html(el.innerHTML)[0]; + } else { + el = angular.element('') + .append($mdUtil.getInnerHTML(el))[0]; + } + if (viewbox) el.setAttribute('viewBox', viewbox); + } + + if (el && el.tagName.toLowerCase() !== 'svg') { + el = angular.element( + '').append(el.cloneNode(true))[0]; + } + + // Inject the namespace if not available... + if (!el.getAttribute('xmlns')) { + el.setAttribute('xmlns', "http://www.w3.org/2000/svg"); + } + + this.element = el; + this.config = config; + this.prepare(); + } + + /** + * Prepare the DOM element that will be cached in the + * loaded iconCache store. + */ + function prepareAndStyle() { + var viewBoxSize = this.config ? this.config.viewBoxSize : config.defaultViewBoxSize; + angular.forEach({ + 'fit': '', + 'height': '100%', + 'width': '100%', + 'preserveAspectRatio': 'xMidYMid meet', + 'viewBox': this.element.getAttribute('viewBox') || ('0 0 ' + viewBoxSize + ' ' + viewBoxSize), + 'focusable': false // Disable IE11s default behavior to make SVGs focusable + }, function(val, attr) { + this.element.setAttribute(attr, val); + }, this); + } + + /** + * Clone the Icon DOM element. + */ + function cloneSVG() { + // If the element or any of its children have a style attribute, then a CSP policy without + // 'unsafe-inline' in the style-src directive, will result in a violation. + return this.element.cloneNode(true); + } + +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.input + */ +mdInputContainerDirective.$inject = ["$mdTheming", "$parse", "$$rAF"]; +inputTextareaDirective.$inject = ["$mdUtil", "$window", "$mdAria", "$timeout", "$mdGesture"]; +mdMaxlengthDirective.$inject = ["$animate", "$mdUtil"]; +placeholderDirective.$inject = ["$compile"]; +ngMessageDirective.$inject = ["$mdUtil"]; +mdSelectOnFocusDirective.$inject = ["$document", "$timeout"]; +mdInputInvalidMessagesAnimation.$inject = ["$$AnimateRunner", "$animateCss", "$mdUtil"]; +ngMessagesAnimation.$inject = ["$$AnimateRunner", "$animateCss", "$mdUtil"]; +ngMessageAnimation.$inject = ["$$AnimateRunner", "$animateCss", "$mdUtil", "$log"]; +var inputModule = angular.module('material.components.input', [ + 'material.core' + ]) + .directive('mdInputContainer', mdInputContainerDirective) + .directive('label', labelDirective) + .directive('input', inputTextareaDirective) + .directive('textarea', inputTextareaDirective) + .directive('mdMaxlength', mdMaxlengthDirective) + .directive('placeholder', placeholderDirective) + .directive('ngMessages', ngMessagesDirective) + .directive('ngMessage', ngMessageDirective) + .directive('ngMessageExp', ngMessageDirective) + .directive('mdSelectOnFocus', mdSelectOnFocusDirective) + + .animation('.md-input-invalid', mdInputInvalidMessagesAnimation) + .animation('.md-input-messages-animation', ngMessagesAnimation) + .animation('.md-input-message-animation', ngMessageAnimation); + +// If we are running inside of tests; expose some extra services so that we can test them +if (window._mdMocksIncluded) { + inputModule.service('$$mdInput', function() { + return { + // special accessor to internals... useful for testing + messages: { + getElement : getMessagesElement + } + }; + }) + + // Register a service for each animation so that we can easily inject them into unit tests + .service('mdInputInvalidAnimation', mdInputInvalidMessagesAnimation) + .service('mdInputMessagesAnimation', ngMessagesAnimation) + .service('mdInputMessageAnimation', ngMessageAnimation); +} + +/** + * @ngdoc directive + * @name mdInputContainer + * @module material.components.input + * + * @restrict E + * + * @description + * `` is the parent of any input or textarea element. It can also optionally + * wrap `` elements so that they will be formatted for use in a form. + * + * Input and textarea elements will not behave properly unless the md-input-container parent is + * provided. + * + * A single `` should contain only one `Exception: Hidden inputs (``) are ignored and will not throw an + * error, so you may combine these with other inputs. + * + * Note: When using `ngMessages` with your input element, make sure the message and container + * elements are *block* elements, otherwise animations applied to the messages will not look as + * intended. Either use a `div` and apply the `ng-message` and `ng-messages` classes respectively, + * or use the `md-block` class on your element. + * + * @param {expression=} md-is-error When the given expression evaluates to `true`, the input + * container will go into the error state. Defaults to erroring if the input has been touched and + * is invalid. + * @param {boolean=} md-no-float When present, `placeholder` attributes on the input will not be + * converted to floating labels. + * + * @usage + * + * + * + * + * + * + * + * + * + * + * + * + * + * {{ state }} + * + * + * + * + *

    When disabling floating labels

    + * + * + * + * + * + * + */ +function mdInputContainerDirective($mdTheming, $parse, $$rAF) { + + ContainerCtrl.$inject = ["$scope", "$element", "$attrs", "$animate"]; + var INPUT_TAGS = ['INPUT', 'TEXTAREA', 'SELECT', 'MD-SELECT']; + + var LEFT_SELECTORS = INPUT_TAGS.reduce(function(selectors, isel) { + return selectors.concat(['md-icon ~ ' + isel, '.md-icon ~ ' + isel]); + }, []).join(","); + + var RIGHT_SELECTORS = INPUT_TAGS.reduce(function(selectors, isel) { + return selectors.concat([isel + ' ~ md-icon', isel + ' ~ .md-icon']); + }, []).join(","); + + return { + restrict: 'E', + compile: compile, + controller: ContainerCtrl + }; + + function compile(tElement) { + // Check for both a left & right icon + var hasLeftIcon = tElement[0].querySelector(LEFT_SELECTORS); + var hasRightIcon = tElement[0].querySelector(RIGHT_SELECTORS); + + return function postLink(scope, element) { + $mdTheming(element); + + if (hasLeftIcon || hasRightIcon) { + // When accessing the element's contents synchronously, they may not be defined yet because + // of the use of ng-if. If we wait one frame, then the element should be there if the ng-if + // resolves to true. + $$rAF(function() { + // Handle the case where the md-icon element is initially hidden via ng-if from #9529. + // We don't want to preserve the space for the icon in the case of ng-if, like we do for + // ng-show. + // Note that we can't use the same selectors from above because the elements are no longer + // siblings for textareas at this point due to the insertion of the md-resize-wrapper. + var iconNotRemoved = element[0].querySelector('md-icon') || + element[0].querySelector('.md-icon'); + if (hasLeftIcon && iconNotRemoved) { + element.addClass('md-icon-left'); + } + if (hasRightIcon && iconNotRemoved) { + element.addClass('md-icon-right'); + } + }); + } + }; + } + + function ContainerCtrl($scope, $element, $attrs, $animate) { + var self = this; + + self.isErrorGetter = $attrs.mdIsError && $parse($attrs.mdIsError); + + self.delegateClick = function() { + self.input.focus(); + }; + self.element = $element; + self.setFocused = function(isFocused) { + $element.toggleClass('md-input-focused', !!isFocused); + }; + self.setHasValue = function(hasValue) { + $element.toggleClass('md-input-has-value', !!hasValue); + }; + self.setHasPlaceholder = function(hasPlaceholder) { + $element.toggleClass('md-input-has-placeholder', !!hasPlaceholder); + }; + self.setInvalid = function(isInvalid) { + if (isInvalid) { + $animate.addClass($element, 'md-input-invalid'); + } else { + $animate.removeClass($element, 'md-input-invalid'); + } + }; + $scope.$watch(function() { + return self.label && self.input; + }, function(hasLabelAndInput) { + if (hasLabelAndInput && !self.label.attr('for')) { + self.label.attr('for', self.input.attr('id')); + } + }); + } +} + +function labelDirective() { + return { + restrict: 'E', + require: '^?mdInputContainer', + link: function(scope, element, attr, containerCtrl) { + if (!containerCtrl || attr.mdNoFloat || element.hasClass('md-container-ignore')) return; + + containerCtrl.label = element; + scope.$on('$destroy', function() { + containerCtrl.label = null; + }); + } + }; +} + +/** + * @ngdoc directive + * @name mdInput + * @restrict E + * @module material.components.input + * + * @description + * You can use any `` or ` + *
    + *
    This is required!
    + *
    That's too long!
    + *
    + * + * + * + * + * + * + * + * + * + * + *

    Notes

    + * + * - Requires [ngMessages](https://docs.angularjs.org/api/ngMessages). + * - Behaves like the [AngularJS input directive](https://docs.angularjs.org/api/ng/directive/input). + * + * The `md-input` and `md-input-container` directives use very specific positioning to achieve the + * error animation effects. Therefore, it is *not* advised to use the Layout system inside of the + * `` tags. Instead, use relative or absolute positioning. + * + * + *

    Textarea directive

    + * The `textarea` element within a `md-input-container` has the following specific behavior: + * - By default the `textarea` grows as the user types. This can be disabled via the `md-no-autogrow` + * attribute. + * - If a `textarea` has the `rows` attribute, it will treat the `rows` as the minimum height and will + * continue growing as the user types. For example a textarea with `rows="3"` will be 3 lines of text + * high initially. If no rows are specified, the directive defaults to 1. + * - The textarea's height gets set on initialization, as well as while the user is typing. In certain situations + * (e.g. while animating) the directive might have been initialized, before the element got it's final height. In + * those cases, you can trigger a resize manually by broadcasting a `md-resize-textarea` event on the scope. + * - If you want a `textarea` to stop growing at a certain point, you can specify the `max-rows` attribute. + * - The textarea's bottom border acts as a handle which users can drag, in order to resize the element vertically. + * Once the user has resized a `textarea`, the autogrowing functionality becomes disabled. If you don't want a + * `textarea` to be resizeable by the user, you can add the `md-no-resize` attribute. + */ + +function inputTextareaDirective($mdUtil, $window, $mdAria, $timeout, $mdGesture) { + return { + restrict: 'E', + require: ['^?mdInputContainer', '?ngModel', '?^form'], + link: postLink + }; + + function postLink(scope, element, attr, ctrls) { + + var containerCtrl = ctrls[0]; + var hasNgModel = !!ctrls[1]; + var ngModelCtrl = ctrls[1] || $mdUtil.fakeNgModel(); + var parentForm = ctrls[2]; + var isReadonly = angular.isDefined(attr.readonly); + var mdNoAsterisk = $mdUtil.parseAttributeBoolean(attr.mdNoAsterisk); + var tagName = element[0].tagName.toLowerCase(); + + + if (!containerCtrl) return; + if (attr.type === 'hidden') { + element.attr('aria-hidden', 'true'); + return; + } else if (containerCtrl.input) { + if (containerCtrl.input[0].contains(element[0])) { + return; + } else { + throw new Error(" can only have *one* , + * + * + * + */ +function mdSelectOnFocusDirective($document, $timeout) { + + return { + restrict: 'A', + link: postLink + }; + + function postLink(scope, element, attr) { + if (element[0].nodeName !== 'INPUT' && element[0].nodeName !== "TEXTAREA") return; + + var preventMouseUp = false; + + element + .on('focus', onFocus) + .on('mouseup', onMouseUp); + + scope.$on('$destroy', function() { + element + .off('focus', onFocus) + .off('mouseup', onMouseUp); + }); + + function onFocus() { + preventMouseUp = true; + + $timeout(function() { + + // Use HTMLInputElement#select to fix firefox select issues. + // The debounce is here for Edge's sake, otherwise the selection doesn't work. + // Since focus may already have been lost on the input (and because `select()` + // will re-focus), make sure the element is still active before applying. + if ($document[0].activeElement === element[0]) { + element[0].select(); + } + + // This should be reset from inside the `focus`, because the event might + // have originated from something different than a click, e.g. a keyboard event. + preventMouseUp = false; + }, 1, false); + } + + // Prevents the default action of the first `mouseup` after a focus. + // This is necessary, because browsers fire a `mouseup` right after the element + // has been focused. In some browsers (Firefox in particular) this can clear the + // selection. There are examples of the problem in issue #7487. + function onMouseUp(event) { + if (preventMouseUp) { + event.preventDefault(); + } + } + } +} + +var visibilityDirectives = ['ngIf', 'ngShow', 'ngHide', 'ngSwitchWhen', 'ngSwitchDefault']; +function ngMessagesDirective() { + return { + restrict: 'EA', + link: postLink, + + // This is optional because we don't want target *all* ngMessage instances, just those inside of + // mdInputContainer. + require: '^^?mdInputContainer' + }; + + function postLink(scope, element, attrs, inputContainer) { + // If we are not a child of an input container, don't do anything + if (!inputContainer) return; + + // Add our animation class + element.toggleClass('md-input-messages-animation', true); + + // Add our md-auto-hide class to automatically hide/show messages when container is invalid + element.toggleClass('md-auto-hide', true); + + // If we see some known visibility directives, remove the md-auto-hide class + if (attrs.mdAutoHide == 'false' || hasVisibiltyDirective(attrs)) { + element.toggleClass('md-auto-hide', false); + } + } + + function hasVisibiltyDirective(attrs) { + return visibilityDirectives.some(function(attr) { + return attrs[attr]; + }); + } +} + +function ngMessageDirective($mdUtil) { + return { + restrict: 'EA', + compile: compile, + priority: 100 + }; + + function compile(tElement) { + if (!isInsideInputContainer(tElement)) { + + // When the current element is inside of a document fragment, then we need to check for an input-container + // in the postLink, because the element will be later added to the DOM and is currently just in a temporary + // fragment, which causes the input-container check to fail. + if (isInsideFragment()) { + return function (scope, element) { + if (isInsideInputContainer(element)) { + // Inside of the postLink function, a ngMessage directive will be a comment element, because it's + // currently hidden. To access the shown element, we need to use the element from the compile function. + initMessageElement(tElement); + } + }; + } + } else { + initMessageElement(tElement); + } + + function isInsideFragment() { + var nextNode = tElement[0]; + while (nextNode = nextNode.parentNode) { + if (nextNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { + return true; + } + } + return false; + } + + function isInsideInputContainer(element) { + return !!$mdUtil.getClosest(element, "md-input-container"); + } + + function initMessageElement(element) { + // Add our animation class + element.toggleClass('md-input-message-animation', true); + } + } +} + +var $$AnimateRunner, $animateCss, $mdUtil; + +function mdInputInvalidMessagesAnimation($$AnimateRunner, $animateCss, $mdUtil) { + saveSharedServices($$AnimateRunner, $animateCss, $mdUtil); + + return { + addClass: function(element, className, done) { + showInputMessages(element, done); + } + + // NOTE: We do not need the removeClass method, because the message ng-leave animation will fire + }; +} + +function ngMessagesAnimation($$AnimateRunner, $animateCss, $mdUtil) { + saveSharedServices($$AnimateRunner, $animateCss, $mdUtil); + + return { + enter: function(element, done) { + showInputMessages(element, done); + }, + + leave: function(element, done) { + hideInputMessages(element, done); + }, + + addClass: function(element, className, done) { + if (className == "ng-hide") { + hideInputMessages(element, done); + } else { + done(); + } + }, + + removeClass: function(element, className, done) { + if (className == "ng-hide") { + showInputMessages(element, done); + } else { + done(); + } + } + }; +} + +function ngMessageAnimation($$AnimateRunner, $animateCss, $mdUtil, $log) { + saveSharedServices($$AnimateRunner, $animateCss, $mdUtil, $log); + + return { + enter: function(element, done) { + var animator = showMessage(element); + + animator.start().done(done); + }, + + leave: function(element, done) { + var animator = hideMessage(element); + + animator.start().done(done); + } + }; +} + +function showInputMessages(element, done) { + var animators = [], animator; + var messages = getMessagesElement(element); + var children = messages.children(); + + if (messages.length == 0 || children.length == 0) { + done(); + return; + } + + angular.forEach(children, function(child) { + animator = showMessage(angular.element(child)); + + animators.push(animator.start()); + }); + + $$AnimateRunner.all(animators, done); +} + +function hideInputMessages(element, done) { + var animators = [], animator; + var messages = getMessagesElement(element); + var children = messages.children(); + + if (messages.length == 0 || children.length == 0) { + done(); + return; + } + + angular.forEach(children, function(child) { + animator = hideMessage(angular.element(child)); + + animators.push(animator.start()); + }); + + $$AnimateRunner.all(animators, done); +} + +function showMessage(element) { + var height = parseInt(window.getComputedStyle(element[0]).height); + var topMargin = parseInt(window.getComputedStyle(element[0]).marginTop); + + var messages = getMessagesElement(element); + var container = getInputElement(element); + + // Check to see if the message is already visible so we can skip + var alreadyVisible = (topMargin > -height); + + // If we have the md-auto-hide class, the md-input-invalid animation will fire, so we can skip + if (alreadyVisible || (messages.hasClass('md-auto-hide') && !container.hasClass('md-input-invalid'))) { + return $animateCss(element, {}); + } + + return $animateCss(element, { + event: 'enter', + structural: true, + from: {"opacity": 0, "margin-top": -height + "px"}, + to: {"opacity": 1, "margin-top": "0"}, + duration: 0.3 + }); +} + +function hideMessage(element) { + var height = element[0].offsetHeight; + var styles = window.getComputedStyle(element[0]); + + // If we are already hidden, just return an empty animation + if (parseInt(styles.opacity) === 0) { + return $animateCss(element, {}); + } + + // Otherwise, animate + return $animateCss(element, { + event: 'leave', + structural: true, + from: {"opacity": 1, "margin-top": 0}, + to: {"opacity": 0, "margin-top": -height + "px"}, + duration: 0.3 + }); +} + +function getInputElement(element) { + var inputContainer = element.controller('mdInputContainer'); + + return inputContainer.element; +} + +function getMessagesElement(element) { + // If we ARE the messages element, just return ourself + if (element.hasClass('md-input-messages-animation')) { + return element; + } + + // If we are a ng-message element, we need to traverse up the DOM tree + if (element.hasClass('md-input-message-animation')) { + return angular.element($mdUtil.getClosest(element, function(node) { + return node.classList.contains('md-input-messages-animation'); + })); + } + + // Otherwise, we can traverse down + return angular.element(element[0].querySelector('.md-input-messages-animation')); +} + +function saveSharedServices(_$$AnimateRunner_, _$animateCss_, _$mdUtil_) { + $$AnimateRunner = _$$AnimateRunner_; + $animateCss = _$animateCss_; + $mdUtil = _$mdUtil_; +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.list + * @description + * List module + */ +MdListController.$inject = ["$scope", "$element", "$mdListInkRipple"]; +mdListDirective.$inject = ["$mdTheming"]; +mdListItemDirective.$inject = ["$mdAria", "$mdConstant", "$mdUtil", "$timeout"]; +angular.module('material.components.list', [ + 'material.core' +]) + .controller('MdListController', MdListController) + .directive('mdList', mdListDirective) + .directive('mdListItem', mdListItemDirective); + +/** + * @ngdoc directive + * @name mdList + * @module material.components.list + * + * @restrict E + * + * @description + * The `` directive is a list container for 1..n `` tags. + * + * @usage + * + * + * + * + *
    + *

    {{item.title}}

    + *

    {{item.description}}

    + *
    + *
    + *
    + *
    + */ + +function mdListDirective($mdTheming) { + return { + restrict: 'E', + compile: function(tEl) { + tEl[0].setAttribute('role', 'list'); + return $mdTheming; + } + }; +} +/** + * @ngdoc directive + * @name mdListItem + * @module material.components.list + * + * @restrict E + * + * @description + * A `md-list-item` element can be used to represent some information in a row.
    + * + * @usage + * ### Single Row Item + * + * + * Single Row Item + * + * + * + * ### Multiple Lines + * By using the following markup, you will be able to have two lines inside of one `md-list-item`. + * + * + * + *
    + *

    First Line

    + *

    Second Line

    + *
    + *
    + *
    + * + * It is also possible to have three lines inside of one list item. + * + * + * + *
    + *

    First Line

    + *

    Second Line

    + *

    Third Line

    + *
    + *
    + *
    + * + * ### Secondary Items + * Secondary items are elements which will be aligned at the end of the `md-list-item`. + * + * + * + * Single Row Item + * + * Secondary Button + * + * + * + * + * It also possible to have multiple secondary items inside of one `md-list-item`. + * + * + * + * Single Row Item + * First Button + * Second Button + * + * + * + * ### Proxy Item + * Proxies are elements, which will execute their specific action on click
    + * Currently supported proxy items are + * - `md-checkbox` (Toggle) + * - `md-switch` (Toggle) + * - `md-menu` (Open) + * + * This means, when using a supported proxy item inside of `md-list-item`, the list item will + * automatically become clickable and executes the associated action of the proxy element on click. + * + * It is possible to disable this behavior by applying the `md-no-proxy` class to the list item. + * + * + * + * No Proxy List + * + * + * + * + * Here are a few examples of proxy elements inside of a list item. + * + * + * + * First Line + * + * + * + * + * The `md-checkbox` element will be automatically detected as a proxy element and will toggle on click. + * + * + * + * First Line + * + * + * + * + * The recognized `md-switch` will toggle its state, when the user clicks on the `md-list-item`. + * + * It is also possible to have a `md-menu` inside of a `md-list-item`. + * + * + *

    Click anywhere to fire the secondary action

    + * + * + * + * + * + * + * + * Redial + * + * + * + * + * Check voicemail + * + * + * + * + * + * Notifications + * + * + * + * + *
    + *
    + * + * The menu will automatically open, when the users clicks on the `md-list-item`.
    + * + * If the developer didn't specify any position mode on the menu, the `md-list-item` will automatically detect the + * position mode and applies it to the `md-menu`. + * + * ### Avatars + * Sometimes you may want to have some avatars inside of the `md-list-item `.
    + * You are able to create a optimized icon for the list item, by applying the `.md-avatar` class on the `` element. + * + * + * + * + * Alan Turing + * + * + * When using `` for an avatar, you have to use the `.md-avatar-icon` class. + * + * + * + * Timothy Kopra + * + * + * + * In cases, you have a `md-list-item`, which doesn't have any avatar, + * but you want to align it with the other avatar items, you have to use the `.md-offset` class. + * + * + * + * Jon Doe + * + * + * + * ### DOM modification + * The `md-list-item` component automatically detects if the list item should be clickable. + * + * --- + * If the `md-list-item` is clickable, we wrap all content inside of a `
    ` and create + * an overlaying button, which will will execute the given actions (like `ng-href`, `ng-click`) + * + * We create an overlaying button, instead of wrapping all content inside of the button, + * because otherwise some elements may not be clickable inside of the button. + * + * --- + * When using a secondary item inside of your list item, the `md-list-item` component will automatically create + * a secondary container at the end of the `md-list-item`, which contains all secondary items. + * + * The secondary item container is not static, because otherwise the overflow will not work properly on the + * list item. + * + */ +function mdListItemDirective($mdAria, $mdConstant, $mdUtil, $timeout) { + var proxiedTypes = ['md-checkbox', 'md-switch', 'md-menu']; + return { + restrict: 'E', + controller: 'MdListController', + compile: function(tEl, tAttrs) { + + // Check for proxy controls (no ng-click on parent, and a control inside) + var secondaryItems = tEl[0].querySelectorAll('.md-secondary'); + var hasProxiedElement; + var proxyElement; + var itemContainer = tEl; + + tEl[0].setAttribute('role', 'listitem'); + + if (tAttrs.ngClick || tAttrs.ngDblclick || tAttrs.ngHref || tAttrs.href || tAttrs.uiSref || tAttrs.ngAttrUiSref) { + wrapIn('button'); + } else if (!tEl.hasClass('md-no-proxy')) { + + for (var i = 0, type; type = proxiedTypes[i]; ++i) { + if (proxyElement = tEl[0].querySelector(type)) { + hasProxiedElement = true; + break; + } + } + + if (hasProxiedElement) { + wrapIn('div'); + } else { + tEl.addClass('md-no-proxy'); + } + + } + + wrapSecondaryItems(); + setupToggleAria(); + + if (hasProxiedElement && proxyElement.nodeName === "MD-MENU") { + setupProxiedMenu(); + } + + function setupToggleAria() { + var toggleTypes = ['md-switch', 'md-checkbox']; + var toggle; + + for (var i = 0, toggleType; toggleType = toggleTypes[i]; ++i) { + if (toggle = tEl.find(toggleType)[0]) { + if (!toggle.hasAttribute('aria-label')) { + var p = tEl.find('p')[0]; + if (!p) return; + toggle.setAttribute('aria-label', 'Toggle ' + p.textContent); + } + } + } + } + + function setupProxiedMenu() { + var menuEl = angular.element(proxyElement); + + var isEndAligned = menuEl.parent().hasClass('md-secondary-container') || + proxyElement.parentNode.firstElementChild !== proxyElement; + + var xAxisPosition = 'left'; + + if (isEndAligned) { + // When the proxy item is aligned at the end of the list, we have to set the origin to the end. + xAxisPosition = 'right'; + } + + // Set the position mode / origin of the proxied menu. + if (!menuEl.attr('md-position-mode')) { + menuEl.attr('md-position-mode', xAxisPosition + ' target'); + } + + // Apply menu open binding to menu button + var menuOpenButton = menuEl.children().eq(0); + if (!hasClickEvent(menuOpenButton[0])) { + menuOpenButton.attr('ng-click', '$mdMenu.open($event)'); + } + + if (!menuOpenButton.attr('aria-label')) { + menuOpenButton.attr('aria-label', 'Open List Menu'); + } + } + + function wrapIn(type) { + if (type == 'div') { + itemContainer = angular.element('
    '); + itemContainer.append(tEl.contents()); + tEl.addClass('md-proxy-focus'); + } else { + // Element which holds the default list-item content. + itemContainer = angular.element( + '
    '+ + '
    '+ + '
    ' + ); + + // Button which shows ripple and executes primary action. + var buttonWrap = angular.element( + '' + ); + + copyAttributes(tEl[0], buttonWrap[0]); + + // If there is no aria-label set on the button (previously copied over if present) + // we determine the label from the content and copy it to the button. + if (!buttonWrap.attr('aria-label')) { + buttonWrap.attr('aria-label', $mdAria.getText(tEl)); + } + + // We allow developers to specify the `md-no-focus` class, to disable the focus style + // on the button executor. Once more classes should be forwarded, we should probably make the + // class forward more generic. + if (tEl.hasClass('md-no-focus')) { + buttonWrap.addClass('md-no-focus'); + } + + // Append the button wrap before our list-item content, because it will overlay in relative. + itemContainer.prepend(buttonWrap); + itemContainer.children().eq(1).append(tEl.contents()); + + tEl.addClass('_md-button-wrap'); + } + + tEl[0].setAttribute('tabindex', '-1'); + tEl.append(itemContainer); + } + + function wrapSecondaryItems() { + var secondaryItemsWrapper = angular.element('
    '); + + angular.forEach(secondaryItems, function(secondaryItem) { + wrapSecondaryItem(secondaryItem, secondaryItemsWrapper); + }); + + itemContainer.append(secondaryItemsWrapper); + } + + function wrapSecondaryItem(secondaryItem, container) { + // If the current secondary item is not a button, but contains a ng-click attribute, + // the secondary item will be automatically wrapped inside of a button. + if (secondaryItem && !isButton(secondaryItem) && secondaryItem.hasAttribute('ng-click')) { + + $mdAria.expect(secondaryItem, 'aria-label'); + var buttonWrapper = angular.element(''); + + // Copy the attributes from the secondary item to the generated button. + // We also support some additional attributes from the secondary item, + // because some developers may use a ngIf, ngHide, ngShow on their item. + copyAttributes(secondaryItem, buttonWrapper[0], ['ng-if', 'ng-hide', 'ng-show']); + + secondaryItem.setAttribute('tabindex', '-1'); + buttonWrapper.append(secondaryItem); + + secondaryItem = buttonWrapper[0]; + } + + if (secondaryItem && (!hasClickEvent(secondaryItem) || (!tAttrs.ngClick && isProxiedElement(secondaryItem)))) { + // In this case we remove the secondary class, so we can identify it later, when we searching for the + // proxy items. + angular.element(secondaryItem).removeClass('md-secondary'); + } + + tEl.addClass('md-with-secondary'); + container.append(secondaryItem); + } + + /** + * Copies attributes from a source element to the destination element + * By default the function will copy the most necessary attributes, supported + * by the button executor for clickable list items. + * @param source Element with the specified attributes + * @param destination Element which will retrieve the attributes + * @param extraAttrs Additional attributes, which will be copied over. + */ + function copyAttributes(source, destination, extraAttrs) { + var copiedAttrs = $mdUtil.prefixer([ + 'ng-if', 'ng-click', 'ng-dblclick', 'aria-label', 'ng-disabled', 'ui-sref', + 'href', 'ng-href', 'rel', 'target', 'ng-attr-ui-sref', 'ui-sref-opts', 'download' + ]); + + if (extraAttrs) { + copiedAttrs = copiedAttrs.concat($mdUtil.prefixer(extraAttrs)); + } + + angular.forEach(copiedAttrs, function(attr) { + if (source.hasAttribute(attr)) { + destination.setAttribute(attr, source.getAttribute(attr)); + source.removeAttribute(attr); + } + }); + } + + function isProxiedElement(el) { + return proxiedTypes.indexOf(el.nodeName.toLowerCase()) != -1; + } + + function isButton(el) { + var nodeName = el.nodeName.toUpperCase(); + + return nodeName == "MD-BUTTON" || nodeName == "BUTTON"; + } + + function hasClickEvent (element) { + var attr = element.attributes; + for (var i = 0; i < attr.length; i++) { + if (tAttrs.$normalize(attr[i].name) === 'ngClick') return true; + } + return false; + } + + return postLink; + + function postLink($scope, $element, $attr, ctrl) { + $element.addClass('_md'); // private md component indicator for styling + + var proxies = [], + firstElement = $element[0].firstElementChild, + isButtonWrap = $element.hasClass('_md-button-wrap'), + clickChild = isButtonWrap ? firstElement.firstElementChild : firstElement, + hasClick = clickChild && hasClickEvent(clickChild), + noProxies = $element.hasClass('md-no-proxy'); + + computeProxies(); + computeClickable(); + + if (proxies.length) { + angular.forEach(proxies, function(proxy) { + proxy = angular.element(proxy); + + $scope.mouseActive = false; + proxy.on('mousedown', function() { + $scope.mouseActive = true; + $timeout(function(){ + $scope.mouseActive = false; + }, 100); + }) + .on('focus', function() { + if ($scope.mouseActive === false) { $element.addClass('md-focused'); } + proxy.on('blur', function proxyOnBlur() { + $element.removeClass('md-focused'); + proxy.off('blur', proxyOnBlur); + }); + }); + }); + } + + + function computeProxies() { + + if (firstElement && firstElement.children && !hasClick && !noProxies) { + + angular.forEach(proxiedTypes, function(type) { + + // All elements which are not capable for being used a proxy have the .md-secondary class + // applied. These items had been sorted out in the secondary wrap function. + angular.forEach(firstElement.querySelectorAll(type + ':not(.md-secondary)'), function(child) { + proxies.push(child); + }); + }); + + } + } + + function computeClickable() { + if (proxies.length == 1 || hasClick) { + $element.addClass('md-clickable'); + + if (!hasClick) { + ctrl.attachRipple($scope, angular.element($element[0].querySelector('.md-no-style'))); + } + } + } + + function isEventFromControl(event) { + var forbiddenControls = ['md-slider']; + + // If there is no path property in the event, then we can assume that the event was not bubbled. + if (!event.path) { + return forbiddenControls.indexOf(event.target.tagName.toLowerCase()) !== -1; + } + + // We iterate the event path up and check for a possible component. + // Our maximum index to search, is the list item root. + var maxPath = event.path.indexOf($element.children()[0]); + + for (var i = 0; i < maxPath; i++) { + if (forbiddenControls.indexOf(event.path[i].tagName.toLowerCase()) !== -1) { + return true; + } + } + } + + var clickChildKeypressListener = function(e) { + if (e.target.nodeName != 'INPUT' && e.target.nodeName != 'TEXTAREA' && !e.target.isContentEditable) { + var keyCode = e.which || e.keyCode; + if (keyCode == $mdConstant.KEY_CODE.SPACE) { + if (clickChild) { + clickChild.click(); + e.preventDefault(); + e.stopPropagation(); + } + } + } + }; + + if (!hasClick && !proxies.length) { + clickChild && clickChild.addEventListener('keypress', clickChildKeypressListener); + } + + $element.off('click'); + $element.off('keypress'); + + if (proxies.length == 1 && clickChild) { + $element.children().eq(0).on('click', function(e) { + // When the event is coming from an control and it should not trigger the proxied element + // then we are skipping. + if (isEventFromControl(e)) return; + + var parentButton = $mdUtil.getClosest(e.target, 'BUTTON'); + if (!parentButton && clickChild.contains(e.target)) { + angular.forEach(proxies, function(proxy) { + if (e.target !== proxy && !proxy.contains(e.target)) { + if (proxy.nodeName === 'MD-MENU') { + proxy = proxy.children[0]; + } + angular.element(proxy).triggerHandler('click'); + } + }); + } + }); + } + + $scope.$on('$destroy', function () { + clickChild && clickChild.removeEventListener('keypress', clickChildKeypressListener); + }); + } + } + }; +} + +/* + * @private + * @ngdoc controller + * @name MdListController + * @module material.components.list + * + */ +function MdListController($scope, $element, $mdListInkRipple) { + var ctrl = this; + ctrl.attachRipple = attachRipple; + + function attachRipple (scope, element) { + var options = {}; + $mdListInkRipple.attach(scope, element, options); + } +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.menu + */ + +angular.module('material.components.menu', [ + 'material.core', + 'material.components.backdrop' +]); + +})(); +(function(){ +"use strict"; + + + +MenuController.$inject = ["$mdMenu", "$attrs", "$element", "$scope", "$mdUtil", "$timeout", "$rootScope", "$q", "$log"]; +angular + .module('material.components.menu') + .controller('mdMenuCtrl', MenuController); + +/** + * @ngInject + */ +function MenuController($mdMenu, $attrs, $element, $scope, $mdUtil, $timeout, $rootScope, $q, $log) { + + var prefixer = $mdUtil.prefixer(); + var menuContainer; + var self = this; + var triggerElement; + + this.nestLevel = parseInt($attrs.mdNestLevel, 10) || 0; + + /** + * Called by our linking fn to provide access to the menu-content + * element removed during link + */ + this.init = function init(setMenuContainer, opts) { + opts = opts || {}; + menuContainer = setMenuContainer; + + // Default element for ARIA attributes has the ngClick or ngMouseenter expression + triggerElement = $element[0].querySelector(prefixer.buildSelector(['ng-click', 'ng-mouseenter'])); + triggerElement.setAttribute('aria-expanded', 'false'); + + this.isInMenuBar = opts.isInMenuBar; + this.nestedMenus = $mdUtil.nodesToArray(menuContainer[0].querySelectorAll('.md-nested-menu')); + + menuContainer.on('$mdInterimElementRemove', function() { + self.isOpen = false; + $mdUtil.nextTick(function(){ self.onIsOpenChanged(self.isOpen);}); + }); + $mdUtil.nextTick(function(){ self.onIsOpenChanged(self.isOpen);}); + + var menuContainerId = 'menu_container_' + $mdUtil.nextUid(); + menuContainer.attr('id', menuContainerId); + angular.element(triggerElement).attr({ + 'aria-owns': menuContainerId, + 'aria-haspopup': 'true' + }); + + $scope.$on('$destroy', angular.bind(this, function() { + this.disableHoverListener(); + $mdMenu.destroy(); + })); + + menuContainer.on('$destroy', function() { + $mdMenu.destroy(); + }); + }; + + var openMenuTimeout, menuItems, deregisterScopeListeners = []; + this.enableHoverListener = function() { + deregisterScopeListeners.push($rootScope.$on('$mdMenuOpen', function(event, el) { + if (menuContainer[0].contains(el[0])) { + self.currentlyOpenMenu = el.controller('mdMenu'); + self.isAlreadyOpening = false; + self.currentlyOpenMenu.registerContainerProxy(self.triggerContainerProxy.bind(self)); + } + })); + deregisterScopeListeners.push($rootScope.$on('$mdMenuClose', function(event, el) { + if (menuContainer[0].contains(el[0])) { + self.currentlyOpenMenu = undefined; + } + })); + menuItems = angular.element($mdUtil.nodesToArray(menuContainer[0].children[0].children)); + menuItems.on('mouseenter', self.handleMenuItemHover); + menuItems.on('mouseleave', self.handleMenuItemMouseLeave); + }; + + this.disableHoverListener = function() { + while (deregisterScopeListeners.length) { + deregisterScopeListeners.shift()(); + } + menuItems && menuItems.off('mouseenter', self.handleMenuItemHover); + menuItems && menuItems.off('mouseleave', self.handleMenuItemMouseLeave); + }; + + this.handleMenuItemHover = function(event) { + if (self.isAlreadyOpening) return; + var nestedMenu = ( + event.target.querySelector('md-menu') + || $mdUtil.getClosest(event.target, 'MD-MENU') + ); + openMenuTimeout = $timeout(function() { + if (nestedMenu) { + nestedMenu = angular.element(nestedMenu).controller('mdMenu'); + } + + if (self.currentlyOpenMenu && self.currentlyOpenMenu != nestedMenu) { + var closeTo = self.nestLevel + 1; + self.currentlyOpenMenu.close(true, { closeTo: closeTo }); + self.isAlreadyOpening = !!nestedMenu; + nestedMenu && nestedMenu.open(); + } else if (nestedMenu && !nestedMenu.isOpen && nestedMenu.open) { + self.isAlreadyOpening = !!nestedMenu; + nestedMenu && nestedMenu.open(); + } + }, nestedMenu ? 100 : 250); + var focusableTarget = event.currentTarget.querySelector('.md-button:not([disabled])'); + focusableTarget && focusableTarget.focus(); + }; + + this.handleMenuItemMouseLeave = function() { + if (openMenuTimeout) { + $timeout.cancel(openMenuTimeout); + openMenuTimeout = undefined; + } + }; + + + /** + * Uses the $mdMenu interim element service to open the menu contents + */ + this.open = function openMenu(ev) { + ev && ev.stopPropagation(); + ev && ev.preventDefault(); + if (self.isOpen) return; + self.enableHoverListener(); + self.isOpen = true; + $mdUtil.nextTick(function(){ self.onIsOpenChanged(self.isOpen);}); + triggerElement = triggerElement || (ev ? ev.target : $element[0]); + triggerElement.setAttribute('aria-expanded', 'true'); + $scope.$emit('$mdMenuOpen', $element); + $mdMenu.show({ + scope: $scope, + mdMenuCtrl: self, + nestLevel: self.nestLevel, + element: menuContainer, + target: triggerElement, + preserveElement: true, + parent: 'body' + }).finally(function() { + triggerElement.setAttribute('aria-expanded', 'false'); + self.disableHoverListener(); + }); + }; + + this.onIsOpenChanged = function(isOpen) { + if (isOpen) { + menuContainer.attr('aria-hidden', 'false'); + $element[0].classList.add('md-open'); + angular.forEach(self.nestedMenus, function(el) { + el.classList.remove('md-open'); + }); + } else { + menuContainer.attr('aria-hidden', 'true'); + $element[0].classList.remove('md-open'); + } + $scope.$mdMenuIsOpen = self.isOpen; + }; + + this.focusMenuContainer = function focusMenuContainer() { + var focusTarget = menuContainer[0] + .querySelector(prefixer.buildSelector(['md-menu-focus-target', 'md-autofocus'])); + + if (!focusTarget) focusTarget = menuContainer[0].querySelector('.md-button:not([disabled])'); + focusTarget.focus(); + }; + + this.registerContainerProxy = function registerContainerProxy(handler) { + this.containerProxy = handler; + }; + + this.triggerContainerProxy = function triggerContainerProxy(ev) { + this.containerProxy && this.containerProxy(ev); + }; + + this.destroy = function() { + return self.isOpen ? $mdMenu.destroy() : $q.when(false); + }; + + // Use the $mdMenu interim element service to close the menu contents + this.close = function closeMenu(skipFocus, closeOpts) { + if (!self.isOpen) return; + self.isOpen = false; + $mdUtil.nextTick(function(){ self.onIsOpenChanged(self.isOpen);}); + + var eventDetails = angular.extend({}, closeOpts, { skipFocus: skipFocus }); + $scope.$emit('$mdMenuClose', $element, eventDetails); + $mdMenu.hide(null, closeOpts); + + if (!skipFocus) { + var el = self.restoreFocusTo || $element.find('button')[0]; + if (el instanceof angular.element) el = el[0]; + if (el) el.focus(); + } + }; + + /** + * Build a nice object out of our string attribute which specifies the + * target mode for left and top positioning + */ + this.positionMode = function positionMode() { + var attachment = ($attrs.mdPositionMode || 'target').split(' '); + + // If attachment is a single item, duplicate it for our second value. + // ie. 'target' -> 'target target' + if (attachment.length === 1) { + attachment.push(attachment[0]); + } + + return { + left: attachment[0], + top: attachment[1] + }; + }; + + /** + * Build a nice object out of our string attribute which specifies + * the offset of top and left in pixels. + */ + this.offsets = function offsets() { + var position = ($attrs.mdOffset || '0 0').split(' ').map(parseFloat); + if (position.length === 2) { + return { + left: position[0], + top: position[1] + }; + } else if (position.length === 1) { + return { + top: position[0], + left: position[0] + }; + } else { + throw Error('Invalid offsets specified. Please follow format or '); + } + }; + + // Functionality that is exposed in the view. + $scope.$mdMenu = { + open: this.open, + close: this.close + }; + + // Deprecated APIs + $scope.$mdOpenMenu = angular.bind(this, function() { + $log.warn('mdMenu: The $mdOpenMenu method is deprecated. Please use `$mdMenu.open`.'); + return this.open.apply(this, arguments); + }); +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc directive + * @name mdMenu + * @module material.components.menu + * @restrict E + * @description + * + * Menus are elements that open when clicked. They are useful for displaying + * additional options within the context of an action. + * + * Every `md-menu` must specify exactly two child elements. The first element is what is + * left in the DOM and is used to open the menu. This element is called the trigger element. + * The trigger element's scope has access to `$mdMenu.open($event)` + * which it may call to open the menu. By passing $event as argument, the + * corresponding event is stopped from propagating up the DOM-tree. Similarly, `$mdMenu.close()` + * can be used to close the menu. + * + * The second element is the `md-menu-content` element which represents the + * contents of the menu when it is open. Typically this will contain `md-menu-item`s, + * but you can do custom content as well. + * + * + * + * + * + * + * + * + * Do Something + * + * + * + + * ## Sizing Menus + * + * The width of the menu when it is open may be specified by specifying a `width` + * attribute on the `md-menu-content` element. + * See the [Material Design Spec](https://material.io/archive/guidelines/components/menus.html#menus-simple-menus) + * for more information. + * + * ## Menu Density + * + * You can use dense menus by adding the `md-dense` class to the `md-menu-content` element. + * This reduces the height of menu items, their top and bottom padding, and default font size. + * Without the `md-dense` class, we use the "mobile" height of `48px`. With the `md-dense` class, + * we use the "desktop" height of `32px`. We do not support the "dense desktop" option in the spec, + * which uses a height of `24px`, at this time. + * See the [Menu Specs](https://material.io/archive/guidelines/components/menus.html#menus-specs) + * section of the Material Design Spec for more information. + * + * ## Aligning Menus + * + * When a menu opens, it is important that the content aligns with the trigger element. + * Failure to align menus can result in jarring experiences for users as content + * suddenly shifts. To help with this, `md-menu` provides several APIs to help + * with alignment. + * + * ### Target Mode + * + * By default, `md-menu` will attempt to align the `md-menu-content` by aligning + * designated child elements in both the trigger and the menu content. + * + * To specify the alignment element in the `trigger` you can use the `md-menu-origin` + * attribute on a child element. If no `md-menu-origin` is specified, the `md-menu` + * will be used as the origin element. + * + * Similarly, the `md-menu-content` may specify a `md-menu-align-target` for a + * `md-menu-item` to specify the node that it should try and align with. + * + * In this example code, we specify an icon to be our origin element, and an + * icon in our menu content to be our alignment target. This ensures that both + * icons are aligned when the menu opens. + * + * + * + * + * + * + * + * + * + * + * Do Something + * + * + * + * + * + * + * ### Position Mode + * + * We can specify the origin of the menu by using the `md-position-mode` attribute. + * This attribute allows specifying the positioning by the `x` and `y` axes. + * + * The default mode is `target target`. This mode uses the left and top edges of the origin element + * to position the menu in LTR layouts. The `x` axis modes will adjust when in RTL layouts. + * + * Sometimes you want to specify alignment from the right side of a origin element. For example, + * if we have a menu on the right side a toolbar, we may want to right align our menu content. + * We can use `target-right target` to specify a right-oriented alignment target. + * There is a working example of this in the Menu Position Modes demo. + * + * #### Horizontal Positioning Options + * - `target` + * - `target-left` + * - `target-right` + * - `cascade` + * - `right` + * - `left` + * + * #### Vertical Positioning Options + * - `target` + * - `cascade` + * - `bottom` + * + * ### Menu Offsets + * + * It is sometimes unavoidable to need to have a deeper level of control for + * the positioning of a menu to ensure perfect alignment. `md-menu` provides + * the `md-offset` attribute to allow pixel-level specificity when adjusting + * menu positioning. + * + * This offset is provided in the format of `x y` or `n` where `n` will be used + * in both the `x` and `y` axis. + * For example, to move a menu by `2px` down from the top, we can use: + * + * + * + * + * + * + * + * Specifying `md-offset="2 2"` would shift the menu two pixels down and two pixels to the right. + * + * ### Auto Focus + * By default, when a menu opens, `md-menu` focuses the first button in the menu content. + * + * Sometimes you would like to focus another menu item instead of the first.
    + * This can be done by applying the `md-autofocus` directive on the given element. + * + * + * + * + * Auto Focus + * + * + * + * + * + * ### Preventing close + * + * Sometimes you would like to be able to click on a menu item without having the menu + * close. To do this, AngularJS Material exposes the `md-prevent-menu-close` attribute which + * can be added to a button inside a menu to stop the menu from automatically closing. + * You can then close the menu either by using `$mdMenu.close()` in the template, + * or programmatically by injecting `$mdMenu` and calling `$mdMenu.hide()`. + * + * + * + * + * + * + * Do Something + * + * + * + * + * + * @usage + * + * + * + * + * + * + * Do Something + * + * + * + * + * @param {string=} md-position-mode Specify pre-defined position modes for the `x` and `y` axes. + * The default modes are `target target`. This positions the origin of the menu using the left and top edges + * of the origin element in LTR layouts.
    + * #### Valid modes for horizontal positioning + * - `target` + * - `target-left` + * - `target-right` + * - `cascade` + * - `right` + * - `left`
    + * #### Valid modes for vertical positioning + * - `target` + * - `cascade` + * - `bottom` + * @param {string=} md-offset An offset to apply to the dropdown on opening, after positioning. + * Defined as `x` and `y` pixel offset values in the form of `x y`.
    + * The default value is `0 0`. + */ +MenuDirective.$inject = ["$mdUtil"]; +angular + .module('material.components.menu') + .directive('mdMenu', MenuDirective); + +/** + * @ngInject + */ +function MenuDirective($mdUtil) { + var INVALID_PREFIX = 'Invalid HTML for md-menu: '; + return { + restrict: 'E', + require: ['mdMenu', '?^mdMenuBar'], + controller: 'mdMenuCtrl', // empty function to be built by link + scope: true, + compile: compile + }; + + function compile(templateElement) { + templateElement.addClass('md-menu'); + + var triggerEl = templateElement.children()[0]; + var prefixer = $mdUtil.prefixer(); + + if (!prefixer.hasAttribute(triggerEl, 'ng-click')) { + triggerEl = triggerEl + .querySelector(prefixer.buildSelector(['ng-click', 'ng-mouseenter'])) || triggerEl; + } + + var isButtonTrigger = triggerEl.nodeName === 'MD-BUTTON' || triggerEl.nodeName === 'BUTTON'; + + if (triggerEl && isButtonTrigger && !triggerEl.hasAttribute('type')) { + triggerEl.setAttribute('type', 'button'); + } + + if (!triggerEl) { + throw Error(INVALID_PREFIX + 'Expected the menu to have a trigger element.'); + } + + if (templateElement.children().length !== 2) { + throw Error(INVALID_PREFIX + 'Expected two children elements. The second element must have a `md-menu-content` element.'); + } + + // Default element for ARIA attributes has the ngClick or ngMouseenter expression + triggerEl && triggerEl.setAttribute('aria-haspopup', 'true'); + + var nestedMenus = templateElement[0].querySelectorAll('md-menu'); + var nestingDepth = parseInt(templateElement[0].getAttribute('md-nest-level'), 10) || 0; + if (nestedMenus) { + angular.forEach($mdUtil.nodesToArray(nestedMenus), function(menuEl) { + if (!menuEl.hasAttribute('md-position-mode')) { + menuEl.setAttribute('md-position-mode', 'cascade'); + } + menuEl.classList.add('_md-nested-menu'); + menuEl.setAttribute('md-nest-level', nestingDepth + 1); + }); + } + return link; + } + + function link(scope, element, attr, ctrls) { + var mdMenuCtrl = ctrls[0]; + var isInMenuBar = !!ctrls[1]; + // Move everything into a md-menu-container and pass it to the controller + var menuContainer = angular.element('
    '); + var menuContents = element.children()[1]; + + element.addClass('_md'); // private md component indicator for styling + + if (!menuContents.hasAttribute('role')) { + menuContents.setAttribute('role', 'menu'); + } + menuContainer.append(menuContents); + + element.on('$destroy', function() { + menuContainer.remove(); + }); + + element.append(menuContainer); + menuContainer[0].style.display = 'none'; + mdMenuCtrl.init(menuContainer, { isInMenuBar: isInMenuBar }); + + } +} + +})(); +(function(){ +"use strict"; + + +MenuProvider.$inject = ["$$interimElementProvider"];angular + .module('material.components.menu') + .provider('$mdMenu', MenuProvider); + +/** + * Interim element provider for the menu. + * Handles behavior for a menu while it is open, including: + * - handling animating the menu opening/closing + * - handling key/mouse events on the menu element + * - handling enabling/disabling scroll while the menu is open + * - handling redrawing during resizes and orientation changes + * + */ + +function MenuProvider($$interimElementProvider) { + menuDefaultOptions.$inject = ["$mdUtil", "$mdTheming", "$mdConstant", "$document", "$window", "$q", "$$rAF", "$animateCss", "$animate", "$log"]; + var MENU_EDGE_MARGIN = 8; + + return $$interimElementProvider('$mdMenu') + .setDefaults({ + methods: ['target'], + options: menuDefaultOptions + }); + + /* @ngInject */ + function menuDefaultOptions($mdUtil, $mdTheming, $mdConstant, $document, $window, $q, $$rAF, + $animateCss, $animate, $log) { + + var prefixer = $mdUtil.prefixer(); + var animator = $mdUtil.dom.animator; + + return { + parent: 'body', + onShow: onShow, + onRemove: onRemove, + hasBackdrop: true, + disableParentScroll: true, + skipCompile: true, + preserveScope: true, + multiple: true, + themable: true + }; + + /** + * Show modal backdrop element... + * @returns {function(): void} A function that removes this backdrop + */ + function showBackdrop(scope, element, options) { + if (options.nestLevel) return angular.noop; + + // If we are not within a dialog... + if (options.disableParentScroll && !$mdUtil.getClosest(options.target, 'MD-DIALOG')) { + // !! DO this before creating the backdrop; since disableScrollAround() + // configures the scroll offset; which is used by mdBackDrop postLink() + options.restoreScroll = $mdUtil.disableScrollAround(options.element, options.parent); + } else { + options.disableParentScroll = false; + } + + if (options.hasBackdrop) { + options.backdrop = $mdUtil.createBackdrop(scope, "md-menu-backdrop md-click-catcher"); + + $animate.enter(options.backdrop, $document[0].body); + } + + /** + * Hide and destroys the backdrop created by showBackdrop() + */ + return function hideBackdrop() { + if (options.backdrop) options.backdrop.remove(); + if (options.disableParentScroll) options.restoreScroll(); + }; + } + + /** + * Removing the menu element from the DOM and remove all associated event listeners + * and backdrop + */ + function onRemove(scope, element, opts) { + opts.cleanupInteraction(); + opts.cleanupBackdrop(); + opts.cleanupResizing(); + opts.hideBackdrop(); + + // Before the menu is closing remove the clickable class. + element.removeClass('md-clickable'); + + // For navigation $destroy events, do a quick, non-animated removal, + // but for normal closes (from clicks, etc) animate the removal + + return (opts.$destroy === true) ? detachAndClean() : animateRemoval().then(detachAndClean); + + /** + * For normal closes, animate the removal. + * For forced closes (like $destroy events), skip the animations + */ + function animateRemoval() { + return $animateCss(element, {addClass: 'md-leave'}).start(); + } + + /** + * Detach the element + */ + function detachAndClean() { + element.removeClass('md-active'); + detachElement(element, opts); + opts.alreadyOpen = false; + } + + } + + /** + * Inserts and configures the staged Menu element into the DOM, positioning it, + * and wiring up various interaction events + */ + function onShow(scope, element, opts) { + sanitizeAndConfigure(opts); + + if (opts.menuContentEl[0]) { + // Inherit the theme from the target element. + $mdTheming.inherit(opts.menuContentEl, opts.target); + } else { + $log.warn( + '$mdMenu: Menu elements should always contain a `md-menu-content` element,' + + 'otherwise interactivity features will not work properly.', + element + ); + } + + // Register various listeners to move menu on resize/orientation change + opts.cleanupResizing = startRepositioningOnResize(); + opts.hideBackdrop = showBackdrop(scope, element, opts); + + // Return the promise for when our menu is done animating in + return showMenu() + .then(function(response) { + opts.alreadyOpen = true; + opts.cleanupInteraction = activateInteraction(); + opts.cleanupBackdrop = setupBackdrop(); + + // Since the menu finished its animation, mark the menu as clickable. + element.addClass('md-clickable'); + + return response; + }); + + /** + * Place the menu into the DOM and call positioning related functions + */ + function showMenu() { + opts.parent.append(element); + element[0].style.display = ''; + + return $q(function(resolve) { + var position = calculateMenuPosition(element, opts); + + element.removeClass('md-leave'); + + // Animate the menu scaling, and opacity [from its position origin (default == top-left)] + // to normal scale. + $animateCss(element, { + addClass: 'md-active', + from: animator.toCss(position), + to: animator.toCss({transform: ''}) + }) + .start() + .then(resolve); + + }); + } + + /** + * Check for valid opts and set some sane defaults + */ + function sanitizeAndConfigure() { + if (!opts.target) { + throw Error( + '$mdMenu.show() expected a target to animate from in options.target' + ); + } + angular.extend(opts, { + alreadyOpen: false, + isRemoved: false, + target: angular.element(opts.target), // make sure it's not a naked DOM node + parent: angular.element(opts.parent), + menuContentEl: angular.element(element[0].querySelector('md-menu-content')) + }); + } + + /** + * Configure various resize listeners for screen changes + */ + function startRepositioningOnResize() { + + var repositionMenu = (function(target, options) { + return $$rAF.throttle(function() { + if (opts.isRemoved) return; + var position = calculateMenuPosition(target, options); + + target.css(animator.toCss(position)); + }); + })(element, opts); + + $window.addEventListener('resize', repositionMenu); + $window.addEventListener('orientationchange', repositionMenu); + + return function stopRepositioningOnResize() { + + // Disable resizing handlers + $window.removeEventListener('resize', repositionMenu); + $window.removeEventListener('orientationchange', repositionMenu); + + }; + } + + /** + * Sets up the backdrop and listens for click elements. + * Once the backdrop will be clicked, the menu will automatically close. + * @returns {!Function} Function to remove the backdrop. + */ + function setupBackdrop() { + if (!opts.backdrop) return angular.noop; + + opts.backdrop.on('click', onBackdropClick); + + return function() { + opts.backdrop.off('click', onBackdropClick); + }; + } + + /** + * Function to be called whenever the backdrop is clicked. + * @param {!MouseEvent} event + */ + function onBackdropClick(event) { + event.preventDefault(); + event.stopPropagation(); + + scope.$apply(function() { + opts.mdMenuCtrl.close(true, { closeAll: true }); + }); + } + + /** + * Activate interaction on the menu. Resolves the focus target and closes the menu on + * escape or option click. + * @returns {!Function} Function to deactivate the interaction listeners. + */ + function activateInteraction() { + if (!opts.menuContentEl[0]) return angular.noop; + + // Wire up keyboard listeners. + // - Close on escape, + // - focus next item on down arrow, + // - focus prev item on up + opts.menuContentEl.on('keydown', onMenuKeyDown); + opts.menuContentEl[0].addEventListener('click', captureClickListener, true); + + // kick off initial focus in the menu on the first enabled element + var focusTarget = opts.menuContentEl[0] + .querySelector(prefixer.buildSelector(['md-menu-focus-target', 'md-autofocus'])); + + if (!focusTarget) { + var childrenLen = opts.menuContentEl[0].children.length; + for (var childIndex = 0; childIndex < childrenLen; childIndex++) { + var child = opts.menuContentEl[0].children[childIndex]; + focusTarget = child.querySelector('.md-button:not([disabled])'); + if (focusTarget) { + break; + } + if (child.firstElementChild && !child.firstElementChild.disabled) { + focusTarget = child.firstElementChild; + break; + } + } + } + + focusTarget && focusTarget.focus(); + + return function cleanupInteraction() { + opts.menuContentEl.off('keydown', onMenuKeyDown); + opts.menuContentEl[0].removeEventListener('click', captureClickListener, true); + }; + + // ************************************ + // internal functions + // ************************************ + + function onMenuKeyDown(ev) { + var handled; + switch (ev.keyCode) { + case $mdConstant.KEY_CODE.ESCAPE: + opts.mdMenuCtrl.close(false, { closeAll: true }); + handled = true; + break; + case $mdConstant.KEY_CODE.TAB: + opts.mdMenuCtrl.close(false, { closeAll: true }); + // Don't prevent default or stop propagation on this event as we want tab + // to move the focus to the next focusable element on the page. + handled = false; + break; + case $mdConstant.KEY_CODE.UP_ARROW: + if (!focusMenuItem(ev, opts.menuContentEl, opts, -1) && !opts.nestLevel) { + opts.mdMenuCtrl.triggerContainerProxy(ev); + } + handled = true; + break; + case $mdConstant.KEY_CODE.DOWN_ARROW: + if (!focusMenuItem(ev, opts.menuContentEl, opts, 1) && !opts.nestLevel) { + opts.mdMenuCtrl.triggerContainerProxy(ev); + } + handled = true; + break; + case $mdConstant.KEY_CODE.LEFT_ARROW: + if (opts.nestLevel) { + opts.mdMenuCtrl.close(); + } else { + opts.mdMenuCtrl.triggerContainerProxy(ev); + } + handled = true; + break; + case $mdConstant.KEY_CODE.RIGHT_ARROW: + var parentMenu = $mdUtil.getClosest(ev.target, 'MD-MENU'); + if (parentMenu && parentMenu != opts.parent[0]) { + ev.target.click(); + } else { + opts.mdMenuCtrl.triggerContainerProxy(ev); + } + handled = true; + break; + } + if (handled) { + ev.preventDefault(); + ev.stopImmediatePropagation(); + } + } + + function onBackdropClick(e) { + e.preventDefault(); + e.stopPropagation(); + scope.$apply(function() { + opts.mdMenuCtrl.close(true, { closeAll: true }); + }); + } + + // Close menu on menu item click, if said menu-item is not disabled + function captureClickListener(e) { + var target = e.target; + // Traverse up the event until we get to the menuContentEl to see if + // there is an ng-click and that the ng-click is not disabled + do { + if (target == opts.menuContentEl[0]) return; + if ((hasAnyAttribute(target, ['ng-click', 'ng-href', 'ui-sref']) || + target.nodeName == 'BUTTON' || target.nodeName == 'MD-BUTTON') && !hasAnyAttribute(target, ['md-prevent-menu-close'])) { + var closestMenu = $mdUtil.getClosest(target, 'MD-MENU'); + if (!target.hasAttribute('disabled') && (!closestMenu || closestMenu == opts.parent[0])) { + close(); + } + break; + } + } while (target = target.parentNode); + + function close() { + scope.$apply(function() { + opts.mdMenuCtrl.close(true, { closeAll: true }); + }); + } + + function hasAnyAttribute(target, attrs) { + if (!target) return false; + + for (var i = 0, attr; attr = attrs[i]; ++i) { + if (prefixer.hasAttribute(target, attr)) { + return true; + } + } + + return false; + } + } + + } + } + + /** + * Takes a keypress event and focuses the next/previous menu + * item from the emitting element + * @param {event} e - The origin keypress event + * @param {angular.element} menuEl - The menu element + * @param {object} opts - The interim element options for the mdMenu + * @param {number} direction - The direction to move in (+1 = next, -1 = prev) + */ + function focusMenuItem(e, menuEl, opts, direction) { + var currentItem = $mdUtil.getClosest(e.target, 'MD-MENU-ITEM'); + + var items = $mdUtil.nodesToArray(menuEl[0].children); + var currentIndex = items.indexOf(currentItem); + + // Traverse through our elements in the specified direction (+/-1) and try to + // focus them until we find one that accepts focus + var didFocus; + for (var i = currentIndex + direction; i >= 0 && i < items.length; i = i + direction) { + var focusTarget = items[i].querySelector('.md-button'); + didFocus = attemptFocus(focusTarget); + if (didFocus) { + break; + } + } + return didFocus; + } + + /** + * Attempts to focus an element. Checks whether that element is the currently + * focused element after attempting. + * @param {HTMLElement} el - the element to attempt focus on + * @returns {boolean} - whether the element was successfully focused + */ + function attemptFocus(el) { + if (el && el.getAttribute('tabindex') != -1) { + el.focus(); + return ($document[0].activeElement == el); + } + } + + /** + * Use browser to remove this element without triggering a $destroy event + */ + function detachElement(element, opts) { + if (!opts.preserveElement) { + if (toNode(element).parentNode === toNode(opts.parent)) { + toNode(opts.parent).removeChild(toNode(element)); + } + } else { + toNode(element).style.display = 'none'; + } + } + + /** + * Computes menu position and sets the style on the menu container + * @param {HTMLElement} el - the menu container element + * @param {object} opts - the interim element options object + */ + function calculateMenuPosition(el, opts) { + + var containerNode = el[0], + openMenuNode = el[0].firstElementChild, + openMenuNodeRect = openMenuNode.getBoundingClientRect(), + boundryNode = $document[0].body, + boundryNodeRect = boundryNode.getBoundingClientRect(); + + var menuStyle = $window.getComputedStyle(openMenuNode); + + var originNode = opts.target[0].querySelector(prefixer.buildSelector('md-menu-origin')) || opts.target[0], + originNodeRect = originNode.getBoundingClientRect(); + + var bounds = { + left: boundryNodeRect.left + MENU_EDGE_MARGIN, + top: Math.max(boundryNodeRect.top, 0) + MENU_EDGE_MARGIN, + bottom: Math.max(boundryNodeRect.bottom, Math.max(boundryNodeRect.top, 0) + boundryNodeRect.height) - MENU_EDGE_MARGIN, + right: boundryNodeRect.right - MENU_EDGE_MARGIN + }; + + var alignTarget, alignTargetRect = { top:0, left : 0, right:0, bottom:0 }, existingOffsets = { top:0, left : 0, right:0, bottom:0 }; + var positionMode = opts.mdMenuCtrl.positionMode(); + + if (positionMode.top === 'target' || positionMode.left === 'target' || positionMode.left === 'target-right') { + alignTarget = firstVisibleChild(); + if (alignTarget) { + // TODO: Allow centering on an arbitrary node, for now center on first menu-item's child + alignTarget = alignTarget.firstElementChild || alignTarget; + alignTarget = alignTarget.querySelector(prefixer.buildSelector('md-menu-align-target')) || alignTarget; + alignTargetRect = alignTarget.getBoundingClientRect(); + + existingOffsets = { + top: parseFloat(containerNode.style.top || 0), + left: parseFloat(containerNode.style.left || 0) + }; + } + } + + var position = {}; + var transformOrigin = 'top '; + + switch (positionMode.top) { + case 'target': + position.top = existingOffsets.top + originNodeRect.top - alignTargetRect.top; + break; + case 'cascade': + position.top = originNodeRect.top - parseFloat(menuStyle.paddingTop) - originNode.style.top; + break; + case 'bottom': + position.top = originNodeRect.top + originNodeRect.height; + break; + default: + throw new Error('Invalid target mode "' + positionMode.top + '" specified for md-menu on Y axis.'); + } + + var rtl = ($mdUtil.bidi() === 'rtl'); + + switch (positionMode.left) { + case 'target': + position.left = existingOffsets.left + originNodeRect.left - alignTargetRect.left; + transformOrigin += rtl ? 'right' : 'left'; + break; + case 'target-left': + position.left = originNodeRect.left; + transformOrigin += 'left'; + break; + case 'target-right': + position.left = originNodeRect.right - openMenuNodeRect.width + (openMenuNodeRect.right - alignTargetRect.right); + transformOrigin += 'right'; + break; + case 'cascade': + var willFitRight = rtl ? (originNodeRect.left - openMenuNodeRect.width) < bounds.left : (originNodeRect.right + openMenuNodeRect.width) < bounds.right; + position.left = willFitRight ? originNodeRect.right - originNode.style.left : originNodeRect.left - originNode.style.left - openMenuNodeRect.width; + transformOrigin += willFitRight ? 'left' : 'right'; + break; + case 'right': + if (rtl) { + position.left = originNodeRect.right - originNodeRect.width; + transformOrigin += 'left'; + } else { + position.left = originNodeRect.right - openMenuNodeRect.width; + transformOrigin += 'right'; + } + break; + case 'left': + if (rtl) { + position.left = originNodeRect.right - openMenuNodeRect.width; + transformOrigin += 'right'; + } else { + position.left = originNodeRect.left; + transformOrigin += 'left'; + } + break; + default: + throw new Error('Invalid target mode "' + positionMode.left + '" specified for md-menu on X axis.'); + } + + var offsets = opts.mdMenuCtrl.offsets(); + position.top += offsets.top; + position.left += offsets.left; + + clamp(position); + + var scaleX = Math.round(100 * Math.min(originNodeRect.width / containerNode.offsetWidth, 1.0)) / 100; + var scaleY = Math.round(100 * Math.min(originNodeRect.height / containerNode.offsetHeight, 1.0)) / 100; + + return { + top: Math.round(position.top), + left: Math.round(position.left), + // Animate a scale out if we aren't just repositioning + transform: !opts.alreadyOpen ? $mdUtil.supplant('scale({0},{1})', [scaleX, scaleY]) : undefined, + transformOrigin: transformOrigin + }; + + /** + * Clamps the repositioning of the menu within the confines of + * bounding element (often the screen/body) + */ + function clamp(pos) { + pos.top = Math.max(Math.min(pos.top, bounds.bottom - containerNode.offsetHeight), bounds.top); + pos.left = Math.max(Math.min(pos.left, bounds.right - containerNode.offsetWidth), bounds.left); + } + + /** + * Gets the first visible child in the openMenuNode + * Necessary incase menu nodes are being dynamically hidden + */ + function firstVisibleChild() { + for (var i = 0; i < openMenuNode.children.length; ++i) { + if ($window.getComputedStyle(openMenuNode.children[i]).display != 'none') { + return openMenuNode.children[i]; + } + } + } + } + } + function toNode(el) { + if (el instanceof angular.element) { + el = el[0]; + } + return el; + } +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.menuBar + */ + +angular.module('material.components.menuBar', [ + 'material.core', + 'material.components.icon', + 'material.components.menu' +]); + +})(); +(function(){ +"use strict"; + + +MenuBarController.$inject = ["$scope", "$rootScope", "$element", "$attrs", "$mdConstant", "$document", "$mdUtil", "$timeout"]; +angular + .module('material.components.menuBar') + .controller('MenuBarController', MenuBarController); + +var BOUND_MENU_METHODS = ['handleKeyDown', 'handleMenuHover', 'scheduleOpenHoveredMenu', 'cancelScheduledOpen']; + +/** + * @ngInject + */ +function MenuBarController($scope, $rootScope, $element, $attrs, $mdConstant, $document, $mdUtil, $timeout) { + this.$element = $element; + this.$attrs = $attrs; + this.$mdConstant = $mdConstant; + this.$mdUtil = $mdUtil; + this.$document = $document; + this.$scope = $scope; + this.$rootScope = $rootScope; + this.$timeout = $timeout; + + var self = this; + angular.forEach(BOUND_MENU_METHODS, function(methodName) { + self[methodName] = angular.bind(self, self[methodName]); + }); +} + +MenuBarController.prototype.init = function() { + var $element = this.$element; + var $mdUtil = this.$mdUtil; + var $scope = this.$scope; + + var self = this; + var deregisterFns = []; + $element.on('keydown', this.handleKeyDown); + this.parentToolbar = $mdUtil.getClosest($element, 'MD-TOOLBAR'); + + deregisterFns.push(this.$rootScope.$on('$mdMenuOpen', function(event, el) { + if (self.getMenus().indexOf(el[0]) != -1) { + $element[0].classList.add('md-open'); + el[0].classList.add('md-open'); + self.currentlyOpenMenu = el.controller('mdMenu'); + self.currentlyOpenMenu.registerContainerProxy(self.handleKeyDown); + self.enableOpenOnHover(); + } + })); + + deregisterFns.push(this.$rootScope.$on('$mdMenuClose', function(event, el, opts) { + var rootMenus = self.getMenus(); + if (rootMenus.indexOf(el[0]) != -1) { + $element[0].classList.remove('md-open'); + el[0].classList.remove('md-open'); + } + + if ($element[0].contains(el[0])) { + var parentMenu = el[0]; + while (parentMenu && rootMenus.indexOf(parentMenu) == -1) { + parentMenu = $mdUtil.getClosest(parentMenu, 'MD-MENU', true); + } + if (parentMenu) { + if (!opts.skipFocus) parentMenu.querySelector('button:not([disabled])').focus(); + self.currentlyOpenMenu = undefined; + self.disableOpenOnHover(); + self.setKeyboardMode(true); + } + } + })); + + $scope.$on('$destroy', function() { + self.disableOpenOnHover(); + while (deregisterFns.length) { + deregisterFns.shift()(); + } + }); + + + this.setKeyboardMode(true); +}; + +MenuBarController.prototype.setKeyboardMode = function(enabled) { + if (enabled) this.$element[0].classList.add('md-keyboard-mode'); + else this.$element[0].classList.remove('md-keyboard-mode'); +}; + +MenuBarController.prototype.enableOpenOnHover = function() { + if (this.openOnHoverEnabled) return; + + var self = this; + + self.openOnHoverEnabled = true; + + if (self.parentToolbar) { + self.parentToolbar.classList.add('md-has-open-menu'); + + // Needs to be on the next tick so it doesn't close immediately. + self.$mdUtil.nextTick(function() { + angular.element(self.parentToolbar).on('click', self.handleParentClick); + }, false); + } + + angular + .element(self.getMenus()) + .on('mouseenter', self.handleMenuHover); +}; + +MenuBarController.prototype.handleMenuHover = function(e) { + this.setKeyboardMode(false); + if (this.openOnHoverEnabled) { + this.scheduleOpenHoveredMenu(e); + } +}; + +MenuBarController.prototype.disableOpenOnHover = function() { + if (!this.openOnHoverEnabled) return; + + this.openOnHoverEnabled = false; + + if (this.parentToolbar) { + this.parentToolbar.classList.remove('md-has-open-menu'); + angular.element(this.parentToolbar).off('click', this.handleParentClick); + } + + angular + .element(this.getMenus()) + .off('mouseenter', this.handleMenuHover); +}; + +MenuBarController.prototype.scheduleOpenHoveredMenu = function(e) { + var menuEl = angular.element(e.currentTarget); + var menuCtrl = menuEl.controller('mdMenu'); + this.setKeyboardMode(false); + this.scheduleOpenMenu(menuCtrl); +}; + +MenuBarController.prototype.scheduleOpenMenu = function(menuCtrl) { + var self = this; + var $timeout = this.$timeout; + if (menuCtrl != self.currentlyOpenMenu) { + $timeout.cancel(self.pendingMenuOpen); + self.pendingMenuOpen = $timeout(function() { + self.pendingMenuOpen = undefined; + if (self.currentlyOpenMenu) { + self.currentlyOpenMenu.close(true, { closeAll: true }); + } + menuCtrl.open(); + }, 200, false); + } +}; + +MenuBarController.prototype.handleKeyDown = function(e) { + var keyCodes = this.$mdConstant.KEY_CODE; + var currentMenu = this.currentlyOpenMenu; + var wasOpen = currentMenu && currentMenu.isOpen; + this.setKeyboardMode(true); + var handled, newMenu, newMenuCtrl; + switch (e.keyCode) { + case keyCodes.DOWN_ARROW: + if (currentMenu) { + currentMenu.focusMenuContainer(); + } else { + this.openFocusedMenu(); + } + handled = true; + break; + case keyCodes.UP_ARROW: + currentMenu && currentMenu.close(); + handled = true; + break; + case keyCodes.LEFT_ARROW: + newMenu = this.focusMenu(-1); + if (wasOpen) { + newMenuCtrl = angular.element(newMenu).controller('mdMenu'); + this.scheduleOpenMenu(newMenuCtrl); + } + handled = true; + break; + case keyCodes.RIGHT_ARROW: + newMenu = this.focusMenu(+1); + if (wasOpen) { + newMenuCtrl = angular.element(newMenu).controller('mdMenu'); + this.scheduleOpenMenu(newMenuCtrl); + } + handled = true; + break; + } + if (handled) { + e && e.preventDefault && e.preventDefault(); + e && e.stopImmediatePropagation && e.stopImmediatePropagation(); + } +}; + +MenuBarController.prototype.focusMenu = function(direction) { + var menus = this.getMenus(); + var focusedIndex = this.getFocusedMenuIndex(); + + if (focusedIndex == -1) { focusedIndex = this.getOpenMenuIndex(); } + + var changed = false; + + if (focusedIndex == -1) { focusedIndex = 0; changed = true; } + else if ( + direction < 0 && focusedIndex > 0 || + direction > 0 && focusedIndex < menus.length - direction + ) { + focusedIndex += direction; + changed = true; + } + if (changed) { + menus[focusedIndex].querySelector('button').focus(); + return menus[focusedIndex]; + } +}; + +MenuBarController.prototype.openFocusedMenu = function() { + var menu = this.getFocusedMenu(); + menu && angular.element(menu).controller('mdMenu').open(); +}; + +MenuBarController.prototype.getMenus = function() { + var $element = this.$element; + return this.$mdUtil.nodesToArray($element[0].children) + .filter(function(el) { return el.nodeName == 'MD-MENU'; }); +}; + +MenuBarController.prototype.getFocusedMenu = function() { + return this.getMenus()[this.getFocusedMenuIndex()]; +}; + +MenuBarController.prototype.getFocusedMenuIndex = function() { + var $mdUtil = this.$mdUtil; + var focusedEl = $mdUtil.getClosest( + this.$document[0].activeElement, + 'MD-MENU' + ); + if (!focusedEl) return -1; + + var focusedIndex = this.getMenus().indexOf(focusedEl); + return focusedIndex; +}; + +MenuBarController.prototype.getOpenMenuIndex = function() { + var menus = this.getMenus(); + for (var i = 0; i < menus.length; ++i) { + if (menus[i].classList.contains('md-open')) return i; + } + return -1; +}; + +MenuBarController.prototype.handleParentClick = function(event) { + var openMenu = this.querySelector('md-menu.md-open'); + + if (openMenu && !openMenu.contains(event.target)) { + angular.element(openMenu).controller('mdMenu').close(true, { + closeAll: true + }); + } +}; + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc directive + * @name mdMenuBar + * @module material.components.menuBar + * @restrict E + * @description + * + * Menu bars are containers that hold multiple menus. They change the behavior and appearance + * of the `md-menu` directive to behave similar to an operating system provided menu. + * + * @usage + * + * + * + * + * + * + * + * Share... + * + * + * + * + * + * + * New + * + * Document + * Spreadsheet + * Presentation + * Form + * Drawing + * + * + * + * + * + * + * + * + * ## Menu Bar Controls + * + * You may place `md-menu-item`s that function as controls within menu bars. + * There are two modes that are exposed via the `type` attribute of the `md-menu-item`. + * `type="checkbox"` will function as a boolean control for the `ng-model` attribute of the + * `md-menu-item`. `type="radio"` will function like a radio button, setting the `ngModel` + * to the `string` value of the `value` attribute. If you need non-string values, you can use + * `ng-value` to provide an expression (this is similar to how angular's native `input[type=radio]` + * works. + * + * If you want either to disable closing the opened menu when clicked, you can add the + * `md-prevent-menu-close` attribute to the `md-menu-item`. The attribute will be forwarded to the + * `button` element that is generated. + * + * + * + * + * + * + * + * Allow changes + * + * + * Mode 1 + * Mode 2 + * Mode 3 + * + * + * + * + * + * + * ### Nesting Menus + * + * Menus may be nested within menu bars. This is commonly called cascading menus. + * To nest a menu place the nested menu inside the content of the `md-menu-item`. + * + * + * + * ' + + * '
    ' + + * ' ' + + * ' ' + + * '
    ' + + * '
    ', + * panelClass: 'menu-panel-container', + * focusOnOpen: false, + * zIndex: 100, + * propagateContainerEvents: true, + * groupName: 'menus' + * }); + * } + * + * function PanelProviderCtrl($mdPanel) { + * this.navigation = { + * name: 'navigation', + * items: [ + * 'Home', + * 'About', + * 'Contact' + * ] + * }; + * this.favorites = { + * name: 'favorites', + * items: [ + * 'Add to Favorites' + * ] + * }; + * this.more = { + * name: 'more', + * items: [ + * 'Account', + * 'Sign Out' + * ] + * }; + * + * $mdPanel.newPanelGroup('menus', { + * maxOpen: 2 + * }); + * + * this.showMenu = function($event, menu) { + * $mdPanel.open('demoPreset', { + * id: 'menu_' + menu.name, + * position: $mdPanel.newPanelPosition() + * .relativeTo($event.target) + * .addPanelPosition( + * $mdPanel.xPosition.ALIGN_START, + * $mdPanel.yPosition.BELOW + * ), + * locals: { + * items: menu.items + * }, + * openFrom: $event + * }); + * }; + * } + * + * function PanelMenuCtrl(mdPanelRef) { + * // 'mdPanelRef' is injected in the controller. + * this.closeMenu = function() { + * if (mdPanelRef) { + * mdPanelRef.close(); + * } + * }; + * } + * })(angular); + * + */ + +/** + * @ngdoc method + * @name $mdPanelProvider#definePreset + * @description + * Takes the passed in preset name and preset configuration object and adds it + * to the `_presets` object of the provider. This `_presets` object is then + * passed along to the `$mdPanel` service. + * + * @param {string} name Preset name. + * @param {!Object} preset Specific configuration object that can contain any + * and all of the parameters avaialble within the `$mdPanel.create` method. + * However, parameters that pertain to id, position, animation, and user + * interaction are not allowed and will be removed from the preset + * configuration. + */ + + +/***************************************************************************** + * MdPanel Service * + *****************************************************************************/ + + +/** + * @ngdoc service + * @name $mdPanel + * @module material.components.panel + * + * @description + * `$mdPanel` is a robust, low-level service for creating floating panels on + * the screen. It can be used to implement tooltips, dialogs, pop-ups, etc. + * + * The following types, referenced below, have separate documentation: + * - MdPanelAnimation from `$mdPanel.newPanelAnimation()` + * - MdPanelPosition from `$mdPanel.newPanelPosition()` + * - MdPanelRef from the `$mdPanel.open()` Promise or + * injected in the panel's controller + * + * @usage + * + * (function(angular, undefined) { + * 'use strict'; + * + * angular + * .module('demoApp', ['ngMaterial']) + * .controller('DemoDialogController', DialogController) + * .controller('DemoCtrl', function($mdPanel) { + * + * var panelRef; + * + * function showPanel($event) { + * var panelPosition = $mdPanel.newPanelPosition() + * .absolute() + * .top('50%') + * .left('50%'); + * + * var panelAnimation = $mdPanel.newPanelAnimation() + * .openFrom($event) + * .duration(200) + * .closeTo('.show-button') + * .withAnimation($mdPanel.animation.SCALE); + * + * var config = { + * attachTo: angular.element(document.body), + * controller: DialogController, + * controllerAs: 'ctrl', + * position: panelPosition, + * animation: panelAnimation, + * targetEvent: $event, + * templateUrl: 'dialog-template.html', + * clickOutsideToClose: true, + * escapeToClose: true, + * focusOnOpen: true + * }; + * + * $mdPanel.open(config) + * .then(function(result) { + * panelRef = result; + * }); + * } + * } + * + * function DialogController(MdPanelRef) { + * function closeDialog() { + * if (MdPanelRef) MdPanelRef.close(); + * } + * } + * })(angular); + * + */ + +/** + * @ngdoc method + * @name $mdPanel#create + * @description + * Creates a panel with the specified options. + * + * @param config {!Object=} Specific configuration object that may contain the + * following properties: + * + * - `id` - `{string=}`: An ID to track the panel by. When an ID is provided, + * the created panel is added to a tracked panels object. Any subsequent + * requests made to create a panel with that ID are ignored. This is useful + * in having the panel service not open multiple panels from the same user + * interaction when there is no backdrop and events are propagated. Defaults + * to an arbitrary string that is not tracked. + * - `template` - `{string=}`: HTML template to show in the panel. This + * **must** be trusted HTML with respect to AngularJS’s + * [$sce service](https://docs.angularjs.org/api/ng/service/$sce). + * - `templateUrl` - `{string=}`: The URL that will be used as the content of + * the panel. + * - `contentElement` - `{(string|!angular.JQLite|!Element)=}`: Pre-compiled + * element to be used as the panel's content. + * - `controller` - `{(function|string)=}`: The controller to associate with + * the panel. The controller can inject a reference to the returned + * panelRef, which allows the panel to be closed, hidden, and shown. Any + * fields passed in through locals or resolve will be bound to the + * controller. + * - `controllerAs` - `{string=}`: An alias to assign the controller to on + * the scope. + * - `bindToController` - `{boolean=}`: Binds locals to the controller + * instead of passing them in. Defaults to true, as this is a best + * practice. + * - `locals` - `{Object=}`: An object containing key/value pairs. The keys + * will be used as names of values to inject into the controller. For + * example, `locals: {three: 3}` would inject `three` into the controller, + * with the value 3. 'mdPanelRef' is a reserved key, and will always + * be set to the created MdPanelRef instance. + * - `resolve` - `{Object=}`: Similar to locals, except it takes promises as + * values. The panel will not open until all of the promises resolve. + * - `attachTo` - `{(string|!angular.JQLite|!Element)=}`: The element to + * attach the panel to. Defaults to appending to the root element of the + * application. + * - `propagateContainerEvents` - `{boolean=}`: Whether pointer or touch + * events should be allowed to propagate 'go through' the container, aka the + * wrapper, of the panel. Defaults to false. + * - `panelClass` - `{string=}`: A css class to apply to the panel element. + * This class should define any borders, box-shadow, etc. for the panel. + * - `zIndex` - `{number=}`: The z-index to place the panel at. + * Defaults to 80. + * - `position` - `{MdPanelPosition=}`: An MdPanelPosition object that + * specifies the alignment of the panel. For more information, see + * `MdPanelPosition`. + * - `clickOutsideToClose` - `{boolean=}`: Whether the user can click + * outside the panel to close it. Defaults to false. + * - `escapeToClose` - `{boolean=}`: Whether the user can press escape to + * close the panel. Defaults to false. + * - `onCloseSuccess` - `{function(!panelRef, string)=}`: Function that is + * called after the close successfully finishes. The first parameter passed + * into this function is the current panelRef and the 2nd is an optional + * string explaining the close reason. The currently supported closeReasons + * can be found in the MdPanelRef.closeReasons enum. These are by default + * passed along by the panel. + * - `trapFocus` - `{boolean=}`: Whether focus should be trapped within the + * panel. If `trapFocus` is true, the user will not be able to interact + * with the rest of the page until the panel is dismissed. Defaults to + * false. + * - `focusOnOpen` - `{boolean=}`: An option to override focus behavior on + * open. Only disable if focusing some other way, as focus management is + * required for panels to be accessible. Defaults to true. + * - `fullscreen` - `{boolean=}`: Whether the panel should be full screen. + * Applies the class `._md-panel-fullscreen` to the panel on open. Defaults + * to false. + * - `animation` - `{MdPanelAnimation=}`: An MdPanelAnimation object that + * specifies the animation of the panel. For more information, see + * `MdPanelAnimation`. + * - `hasBackdrop` - `{boolean=}`: Whether there should be an opaque backdrop + * behind the panel. Defaults to false. + * - `disableParentScroll` - `{boolean=}`: Whether the user can scroll the + * page behind the panel. Defaults to false. + * - `onDomAdded` - `{function=}`: Callback function used to announce when + * the panel is added to the DOM. + * - `onOpenComplete` - `{function=}`: Callback function used to announce + * when the open() action is finished. + * - `onRemoving` - `{function=}`: Callback function used to announce the + * close/hide() action is starting. + * - `onDomRemoved` - `{function=}`: Callback function used to announce when + * the panel is removed from the DOM. + * - `origin` - `{(string|!angular.JQLite|!Element)=}`: The element to focus + * on when the panel closes. This is commonly the element which triggered + * the opening of the panel. If you do not use `origin`, you need to control + * the focus manually. + * - `groupName` - `{(string|!Array)=}`: A group name or an array of + * group names. The group name is used for creating a group of panels. The + * group is used for configuring the number of open panels and identifying + * specific behaviors for groups. For instance, all tooltips could be + * identified using the same groupName. + * + * @returns {!MdPanelRef} panelRef + */ + +/** + * @ngdoc method + * @name $mdPanel#open + * @description + * Calls the create method above, then opens the panel. This is a shortcut for + * creating and then calling open manually. If custom methods need to be + * called when the panel is added to the DOM or opened, do not use this method. + * Instead create the panel, chain promises on the domAdded and openComplete + * methods, and call open from the returned panelRef. + * + * @param {!Object=} config Specific configuration object that may contain + * the properties defined in `$mdPanel.create`. + * @returns {!angular.$q.Promise} panelRef A promise that resolves + * to an instance of the panel. + */ + +/** + * @ngdoc method + * @name $mdPanel#newPanelPosition + * @description + * Returns a new instance of the MdPanelPosition object. Use this to create + * the position config object. + * + * @returns {!MdPanelPosition} panelPosition + */ + +/** + * @ngdoc method + * @name $mdPanel#newPanelAnimation + * @description + * Returns a new instance of the MdPanelAnimation object. Use this to create + * the animation config object. + * + * @returns {!MdPanelAnimation} panelAnimation + */ + +/** + * @ngdoc method + * @name $mdPanel#newPanelGroup + * @description + * Creates a panel group and adds it to a tracked list of panel groups. + * + * @param {string} groupName Name of the group to create. + * @param {!Object=} config Specific configuration object that may contain the + * following properties: + * + * - `maxOpen` - `{number=}`: The maximum number of panels that are allowed to + * be open within a defined panel group. + * + * @returns {!Object, + * openPanels: !Array, + * maxOpen: number}>} panelGroup + */ + +/** + * @ngdoc method + * @name $mdPanel#setGroupMaxOpen + * @description + * Sets the maximum number of panels in a group that can be opened at a given + * time. + * + * @param {string} groupName The name of the group to configure. + * @param {number} maxOpen The maximum number of panels that can be + * opened. Infinity can be passed in to remove the maxOpen limit. + */ + + +/***************************************************************************** + * MdPanelRef * + *****************************************************************************/ + + +/** + * @ngdoc type + * @name MdPanelRef + * @module material.components.panel + * @description + * A reference to a created panel. This reference contains a unique id for the + * panel, along with the following properties: + * + * - `id` - `{string}`: The unique id for the panel. This id is used to track + * when a panel was interacted with. + * - `config` - `{!Object=}`: The entire config object that was used in + * create. + * - `isAttached` - `{boolean}`: Whether the panel is attached to the DOM. + * Visibility to the user does not factor into isAttached. + * - `panelContainer` - `{angular.JQLite}`: The wrapper element containing the + * panel. This property is added in order to have access to the `addClass`, + * `removeClass`, `toggleClass`, etc methods. + * - `panelEl` - `{angular.JQLite}`: The panel element. This property is added + * in order to have access to the `addClass`, `removeClass`, `toggleClass`, + * etc methods. + */ + +/** + * @ngdoc method + * @name MdPanelRef#open + * @description + * Attaches and shows the panel. + * + * @returns {!angular.$q.Promise} A promise that is resolved when the panel is + * opened. + */ + +/** + * @ngdoc method + * @name MdPanelRef#close + * @description + * Hides and detaches the panel. Note that this will **not** destroy the panel. + * If you don't intend on using the panel again, call the {@link #destroy + * destroy} method afterwards. + * + * @returns {!angular.$q.Promise} A promise that is resolved when the panel is + * closed. + */ + +/** + * @ngdoc method + * @name MdPanelRef#attach + * @description + * Create the panel elements and attach them to the DOM. The panel will be + * hidden by default. + * + * @returns {!angular.$q.Promise} A promise that is resolved when the panel is + * attached. + */ + +/** + * @ngdoc method + * @name MdPanelRef#detach + * @description + * Removes the panel from the DOM. This will NOT hide the panel before removing + * it. + * + * @returns {!angular.$q.Promise} A promise that is resolved when the panel is + * detached. + */ + +/** + * @ngdoc method + * @name MdPanelRef#show + * @description + * Shows the panel. + * + * @returns {!angular.$q.Promise} A promise that is resolved when the panel has + * shown and animations are completed. + */ + +/** + * @ngdoc method + * @name MdPanelRef#hide + * @description + * Hides the panel. + * + * @returns {!angular.$q.Promise} A promise that is resolved when the panel has + * hidden and animations are completed. + */ + +/** + * @ngdoc method + * @name MdPanelRef#destroy + * @description + * Destroys the panel. The panel cannot be opened again after this is called. + */ + +/** + * @ngdoc method + * @name MdPanelRef#addClass + * @deprecated + * This method is in the process of being deprecated in favor of using the panel + * and container JQLite elements that are referenced in the MdPanelRef object. + * Full deprecation is scheduled for material 1.2. + * @description + * Adds a class to the panel. DO NOT use this hide/show the panel. + * + * @param {string} newClass class to be added. + * @param {boolean} toElement Whether or not to add the class to the panel + * element instead of the container. + */ + +/** + * @ngdoc method + * @name MdPanelRef#removeClass + * @deprecated + * This method is in the process of being deprecated in favor of using the panel + * and container JQLite elements that are referenced in the MdPanelRef object. + * Full deprecation is scheduled for material 1.2. + * @description + * Removes a class from the panel. DO NOT use this to hide/show the panel. + * + * @param {string} oldClass Class to be removed. + * @param {boolean} fromElement Whether or not to remove the class from the + * panel element instead of the container. + */ + +/** + * @ngdoc method + * @name MdPanelRef#toggleClass + * @deprecated + * This method is in the process of being deprecated in favor of using the panel + * and container JQLite elements that are referenced in the MdPanelRef object. + * Full deprecation is scheduled for material 1.2. + * @description + * Toggles a class on the panel. DO NOT use this to hide/show the panel. + * + * @param {string} toggleClass Class to be toggled. + * @param {boolean} onElement Whether or not to remove the class from the panel + * element instead of the container. + */ + +/** + * @ngdoc method + * @name MdPanelRef#updatePosition + * @description + * Updates the position configuration of a panel. Use this to update the + * position of a panel that is open, without having to close and re-open the + * panel. + * + * @param {!MdPanelPosition} position + */ + +/** + * @ngdoc method + * @name MdPanelRef#addToGroup + * @description + * Adds a panel to a group if the panel does not exist within the group already. + * A panel can only exist within a single group. + * + * @param {string} groupName The name of the group to add the panel to. + */ + +/** + * @ngdoc method + * @name MdPanelRef#removeFromGroup + * @description + * Removes a panel from a group if the panel exists within that group. The group + * must be created ahead of time. + * + * @param {string} groupName The name of the group. + */ + +/** + * @ngdoc method + * @name MdPanelRef#registerInterceptor + * @description + * Registers an interceptor with the panel. The callback should return a promise, + * which will allow the action to continue when it gets resolved, or will + * prevent an action if it is rejected. The interceptors are called sequentially + * and it reverse order. `type` must be one of the following + * values available on `$mdPanel.interceptorTypes`: + * * `CLOSE` - Gets called before the panel begins closing. + * + * @param {string} type Type of interceptor. + * @param {!angular.$q.Promise} callback Callback to be registered. + * @returns {!MdPanelRef} + */ + +/** + * @ngdoc method + * @name MdPanelRef#removeInterceptor + * @description + * Removes a registered interceptor. + * + * @param {string} type Type of interceptor to be removed. + * @param {function(): !angular.$q.Promise} callback Interceptor to be removed. + * @returns {!MdPanelRef} + */ + +/** + * @ngdoc method + * @name MdPanelRef#removeAllInterceptors + * @description + * Removes all interceptors. If a type is supplied, only the + * interceptors of that type will be cleared. + * + * @param {string=} type Type of interceptors to be removed. + * @returns {!MdPanelRef} + */ + +/** + * @ngdoc method + * @name MdPanelRef#updateAnimation + * @description + * Updates the animation configuration for a panel. You can use this to change + * the panel's animation without having to re-create it. + * + * @param {!MdPanelAnimation} animation + */ + + +/***************************************************************************** + * MdPanelPosition * + *****************************************************************************/ + + +/** + * @ngdoc type + * @name MdPanelPosition + * @module material.components.panel + * @description + * + * Object for configuring the position of the panel. + * + * @usage + * + * #### Centering the panel + * + * + * new MdPanelPosition().absolute().center(); + * + * + * #### Overlapping the panel with an element + * + * + * new MdPanelPosition() + * .relativeTo(someElement) + * .addPanelPosition( + * $mdPanel.xPosition.ALIGN_START, + * $mdPanel.yPosition.ALIGN_TOPS + * ); + * + * + * #### Aligning the panel with the bottom of an element + * + * + * new MdPanelPosition() + * .relativeTo(someElement) + * .addPanelPosition($mdPanel.xPosition.CENTER, $mdPanel.yPosition.BELOW); + * + */ + +/** + * @ngdoc method + * @name MdPanelPosition#absolute + * @description + * Positions the panel absolutely relative to the parent element. If the parent + * is document.body, this is equivalent to positioning the panel absolutely + * within the viewport. + * + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#relativeTo + * @description + * Positions the panel relative to a specific element. + * + * @param {string|!Element|!angular.JQLite} element Query selector, DOM element, + * or angular element to position the panel with respect to. + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#top + * @description + * Sets the value of `top` for the panel. Clears any previously set vertical + * position. + * + * @param {string=} top Value of `top`. Defaults to '0'. + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#bottom + * @description + * Sets the value of `bottom` for the panel. Clears any previously set vertical + * position. + * + * @param {string=} bottom Value of `bottom`. Defaults to '0'. + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#start + * @description + * Sets the panel to the start of the page - `left` if `ltr` or `right` for + * `rtl`. Clears any previously set horizontal position. + * + * @param {string=} start Value of position. Defaults to '0'. + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#end + * @description + * Sets the panel to the end of the page - `right` if `ltr` or `left` for `rtl`. + * Clears any previously set horizontal position. + * + * @param {string=} end Value of position. Defaults to '0'. + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#left + * @description + * Sets the value of `left` for the panel. Clears any previously set + * horizontal position. + * + * @param {string=} left Value of `left`. Defaults to '0'. + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#right + * @description + * Sets the value of `right` for the panel. Clears any previously set + * horizontal position. + * + * @param {string=} right Value of `right`. Defaults to '0'. + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#centerHorizontally + * @description + * Centers the panel horizontally in the viewport. Clears any previously set + * horizontal position. + * + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#centerVertically + * @description + * Centers the panel vertically in the viewport. Clears any previously set + * vertical position. + * + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#center + * @description + * Centers the panel horizontally and vertically in the viewport. This is + * equivalent to calling both `centerHorizontally` and `centerVertically`. + * Clears any previously set horizontal and vertical positions. + * + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#addPanelPosition + * @description + * Sets the x and y position for the panel relative to another element. Can be + * called multiple times to specify an ordered list of panel positions. The + * first position which allows the panel to be completely on-screen will be + * chosen; the last position will be chose whether it is on-screen or not. + * + * xPosition must be one of the following values available on + * $mdPanel.xPosition: + * + * + * CENTER | ALIGN_START | ALIGN_END | OFFSET_START | OFFSET_END + * + *
    + *    *************
    + *    *           *
    + *    *   PANEL   *
    + *    *           *
    + *    *************
    + *   A B    C    D E
    + *
    + * A: OFFSET_START (for LTR displays)
    + * B: ALIGN_START (for LTR displays)
    + * C: CENTER
    + * D: ALIGN_END (for LTR displays)
    + * E: OFFSET_END (for LTR displays)
    + * 
    + * + * yPosition must be one of the following values available on + * $mdPanel.yPosition: + * + * CENTER | ALIGN_TOPS | ALIGN_BOTTOMS | ABOVE | BELOW + * + *
    + *   F
    + *   G *************
    + *     *           *
    + *   H *   PANEL   *
    + *     *           *
    + *   I *************
    + *   J
    + *
    + * F: BELOW
    + * G: ALIGN_TOPS
    + * H: CENTER
    + * I: ALIGN_BOTTOMS
    + * J: ABOVE
    + * 
    + * + * @param {string} xPosition + * @param {string} yPosition + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#withOffsetX + * @description + * Sets the value of the offset in the x-direction. + * + * @param {string|number} offsetX + * @returns {!MdPanelPosition} + */ + +/** + * @ngdoc method + * @name MdPanelPosition#withOffsetY + * @description + * Sets the value of the offset in the y-direction. + * + * @param {string|number} offsetY + * @returns {!MdPanelPosition} + */ + + +/***************************************************************************** + * MdPanelAnimation * + *****************************************************************************/ + + +/** + * @ngdoc type + * @name MdPanelAnimation + * @module material.components.panel + * @description + * Animation configuration object. To use, create an MdPanelAnimation with the + * desired properties, then pass the object as part of $mdPanel creation. + * + * @usage + * + * + * var panelAnimation = new MdPanelAnimation() + * .openFrom(myButtonEl) + * .duration(1337) + * .closeTo('.my-button') + * .withAnimation($mdPanel.animation.SCALE); + * + * $mdPanel.create({ + * animation: panelAnimation + * }); + * + */ + +/** + * @ngdoc method + * @name MdPanelAnimation#openFrom + * @description + * Specifies where to start the open animation. `openFrom` accepts a + * click event object, query selector, DOM element, or a Rect object that + * is used to determine the bounds. When passed a click event, the location + * of the click will be used as the position to start the animation. + * + * @param {string|!Element|!Event|{top: number, left: number}} + * @returns {!MdPanelAnimation} + */ + +/** + * @ngdoc method + * @name MdPanelAnimation#closeTo + * @description + * Specifies where to animate the panel close. `closeTo` accepts a + * query selector, DOM element, or a Rect object that is used to determine + * the bounds. + * + * @param {string|!Element|{top: number, left: number}} + * @returns {!MdPanelAnimation} + */ + +/** + * @ngdoc method + * @name MdPanelAnimation#withAnimation + * @description + * Specifies the animation class. + * + * There are several default animations that can be used: `$mdPanel.animation.` + * - `SLIDE`: The panel slides in and out from the specified + * elements. It will not fade in or out. + * - `SCALE`: The panel scales in and out. Slide and fade are + * included in this animation. + * - `FADE`: The panel fades in and out. + * + * Custom classes will by default fade in and out unless + * `transition: opacity 1ms` is added to the to custom class. + * + * @param {string|{open: string, close: string}} cssClass + * @returns {!MdPanelAnimation} + */ + +/** + * @ngdoc method + * @name MdPanelAnimation#duration + * @description + * Specifies the duration of the animation in milliseconds. The `duration` + * method accepts either a number or an object with separate open and close + * durations. + * + * @param {number|{open: number, close: number}} duration + * @returns {!MdPanelAnimation} + */ + + +/***************************************************************************** + * PUBLIC DOCUMENTATION * + *****************************************************************************/ + + +var MD_PANEL_Z_INDEX = 80; +var MD_PANEL_HIDDEN = '_md-panel-hidden'; +var FOCUS_TRAP_TEMPLATE = angular.element( + '
    '); + +var _presets = {}; + + +/** + * A provider that is used for creating presets for the panel API. + * @final @constructor @ngInject + */ +function MdPanelProvider() { + return { + 'definePreset': definePreset, + 'getAllPresets': getAllPresets, + 'clearPresets': clearPresets, + '$get': $getProvider() + }; +} + + +/** + * Takes the passed in panel configuration object and adds it to the `_presets` + * object at the specified name. + * @param {string} name Name of the preset to set. + * @param {!Object} preset Specific configuration object that can contain any + * and all of the parameters available within the `$mdPanel.create` method. + * However, parameters that pertain to id, position, animation, and user + * interaction are not allowed and will be removed from the preset + * configuration. + */ +function definePreset(name, preset) { + if (!name || !preset) { + throw new Error('mdPanelProvider: The panel preset definition is ' + + 'malformed. The name and preset object are required.'); + } else if (_presets.hasOwnProperty(name)) { + throw new Error('mdPanelProvider: The panel preset you have requested ' + + 'has already been defined.'); + } + + // Delete any property on the preset that is not allowed. + delete preset.id; + delete preset.position; + delete preset.animation; + + _presets[name] = preset; +} + + +/** + * Gets a clone of the `_presets`. + * @return {!Object} + */ +function getAllPresets() { + return angular.copy(_presets); +} + + +/** + * Clears all of the stored presets. + */ +function clearPresets() { + _presets = {}; +} + + +/** + * Represents the `$get` method of the AngularJS provider. From here, a new + * reference to the MdPanelService is returned where the needed arguments are + * passed in including the MdPanelProvider `_presets`. + * @param {!Object} _presets + * @param {!angular.JQLite} $rootElement + * @param {!angular.Scope} $rootScope + * @param {!angular.$injector} $injector + * @param {!angular.$window} $window + */ +function $getProvider() { + return [ + '$rootElement', '$rootScope', '$injector', '$window', + function($rootElement, $rootScope, $injector, $window) { + return new MdPanelService(_presets, $rootElement, $rootScope, + $injector, $window); + } + ]; +} + + +/***************************************************************************** + * MdPanel Service * + *****************************************************************************/ + + +/** + * A service that is used for controlling/displaying panels on the screen. + * @param {!Object} presets + * @param {!angular.JQLite} $rootElement + * @param {!angular.Scope} $rootScope + * @param {!angular.$injector} $injector + * @param {!angular.$window} $window + * @final @constructor @ngInject + */ +function MdPanelService(presets, $rootElement, $rootScope, $injector, $window) { + /** + * Default config options for the panel. + * Anything angular related needs to be done later. Therefore + * scope: $rootScope.$new(true), + * attachTo: $rootElement, + * are added later. + * @private {!Object} + */ + this._defaultConfigOptions = { + bindToController: true, + clickOutsideToClose: false, + disableParentScroll: false, + escapeToClose: false, + focusOnOpen: true, + fullscreen: false, + hasBackdrop: false, + propagateContainerEvents: false, + transformTemplate: angular.bind(this, this._wrapTemplate), + trapFocus: false, + zIndex: MD_PANEL_Z_INDEX + }; + + /** @private {!Object} */ + this._config = {}; + + /** @private {!Object} */ + this._presets = presets; + + /** @private @const */ + this._$rootElement = $rootElement; + + /** @private @const */ + this._$rootScope = $rootScope; + + /** @private @const */ + this._$injector = $injector; + + /** @private @const */ + this._$window = $window; + + /** @private @const */ + this._$mdUtil = this._$injector.get('$mdUtil'); + + /** @private {!Object} */ + this._trackedPanels = {}; + + /** + * @private {!Object, + * openPanels: !Array, + * maxOpen: number}>} + */ + this._groups = Object.create(null); + + /** + * Default animations that can be used within the panel. + * @type {enum} + */ + this.animation = MdPanelAnimation.animation; + + /** + * Possible values of xPosition for positioning the panel relative to + * another element. + * @type {enum} + */ + this.xPosition = MdPanelPosition.xPosition; + + /** + * Possible values of yPosition for positioning the panel relative to + * another element. + * @type {enum} + */ + this.yPosition = MdPanelPosition.yPosition; + + /** + * Possible values for the interceptors that can be registered on a panel. + * @type {enum} + */ + this.interceptorTypes = MdPanelRef.interceptorTypes; + + /** + * Possible values for closing of a panel. + * @type {enum} + */ + this.closeReasons = MdPanelRef.closeReasons; + + /** + * Possible values of absolute position. + * @type {enum} + */ + this.absPosition = MdPanelPosition.absPosition; +} + + +/** + * Creates a panel with the specified options. + * @param {string=} preset Name of a preset configuration that can be used to + * extend the panel configuration. + * @param {!Object=} config Configuration object for the panel. + * @returns {!MdPanelRef} + */ +MdPanelService.prototype.create = function(preset, config) { + if (typeof preset === 'string') { + preset = this._getPresetByName(preset); + } else if (typeof preset === 'object' && + (angular.isUndefined(config) || !config)) { + config = preset; + preset = {}; + } + + preset = preset || {}; + config = config || {}; + + // If the passed-in config contains an ID and the ID is within _trackedPanels, + // return the tracked panel after updating its config with the passed-in + // config. + if (angular.isDefined(config.id) && this._trackedPanels[config.id]) { + var trackedPanel = this._trackedPanels[config.id]; + angular.extend(trackedPanel.config, config); + return trackedPanel; + } + + // Combine the passed-in config, the _defaultConfigOptions, and the preset + // configuration into the `_config`. + this._config = angular.extend({ + // If no ID is set within the passed-in config, then create an arbitrary ID. + id: config.id || 'panel_' + this._$mdUtil.nextUid(), + scope: this._$rootScope.$new(true), + attachTo: this._$rootElement + }, this._defaultConfigOptions, config, preset); + + // Create the panelRef and add it to the `_trackedPanels` object. + var panelRef = new MdPanelRef(this._config, this._$injector); + this._trackedPanels[this._config.id] = panelRef; + + // Add the panel to each of its requested groups. + if (this._config.groupName) { + if (angular.isString(this._config.groupName)) { + this._config.groupName = [this._config.groupName]; + } + angular.forEach(this._config.groupName, function(group) { + panelRef.addToGroup(group); + }); + } + + this._config.scope.$on('$destroy', angular.bind(panelRef, panelRef.detach)); + + return panelRef; +}; + + +/** + * Creates and opens a panel with the specified options. + * @param {string=} preset Name of a preset configuration that can be used to + * extend the panel configuration. + * @param {!Object=} config Configuration object for the panel. + * @returns {!angular.$q.Promise} The panel created from create. + */ +MdPanelService.prototype.open = function(preset, config) { + var panelRef = this.create(preset, config); + return panelRef.open().then(function() { + return panelRef; + }); +}; + + +/** + * Gets a specific preset configuration object saved within `_presets`. + * @param {string} preset Name of the preset to search for. + * @returns {!Object} The preset configuration object. + */ +MdPanelService.prototype._getPresetByName = function(preset) { + if (!this._presets[preset]) { + throw new Error('mdPanel: The panel preset configuration that you ' + + 'requested does not exist. Use the $mdPanelProvider to create a ' + + 'preset before requesting one.'); + } + return this._presets[preset]; +}; + + +/** + * Returns a new instance of the MdPanelPosition. Use this to create the + * positioning object. + * @returns {!MdPanelPosition} + */ +MdPanelService.prototype.newPanelPosition = function() { + return new MdPanelPosition(this._$injector); +}; + + +/** + * Returns a new instance of the MdPanelAnimation. Use this to create the + * animation object. + * @returns {!MdPanelAnimation} + */ +MdPanelService.prototype.newPanelAnimation = function() { + return new MdPanelAnimation(this._$injector); +}; + + +/** + * Creates a panel group and adds it to a tracked list of panel groups. + * @param groupName {string} Name of the group to create. + * @param config {!Object=} Specific configuration object that may contain the + * following properties: + * + * - `maxOpen` - `{number=}`: The maximum number of panels that are allowed + * open within a defined panel group. + * + * @returns {!Object, + * openPanels: !Array, + * maxOpen: number}>} panelGroup + */ +MdPanelService.prototype.newPanelGroup = function(groupName, config) { + if (!this._groups[groupName]) { + config = config || {}; + var group = { + panels: [], + openPanels: [], + maxOpen: config.maxOpen > 0 ? config.maxOpen : Infinity + }; + this._groups[groupName] = group; + } + return this._groups[groupName]; +}; + + +/** + * Sets the maximum number of panels in a group that can be opened at a given + * time. + * @param {string} groupName The name of the group to configure. + * @param {number} maxOpen The maximum number of panels that can be + * opened. Infinity can be passed in to remove the maxOpen limit. + */ +MdPanelService.prototype.setGroupMaxOpen = function(groupName, maxOpen) { + if (this._groups[groupName]) { + this._groups[groupName].maxOpen = maxOpen; + } else { + throw new Error('mdPanel: Group does not exist yet. Call newPanelGroup().'); + } +}; + + +/** + * Determines if the current number of open panels within a group exceeds the + * limit of allowed open panels. + * @param {string} groupName The name of the group to check. + * @returns {boolean} true if open count does exceed maxOpen and false if not. + * @private + */ +MdPanelService.prototype._openCountExceedsMaxOpen = function(groupName) { + if (this._groups[groupName]) { + var group = this._groups[groupName]; + return group.maxOpen > 0 && group.openPanels.length > group.maxOpen; + } + return false; +}; + + +/** + * Closes the first open panel within a specific group. + * @param {string} groupName The name of the group. + * @private + */ +MdPanelService.prototype._closeFirstOpenedPanel = function(groupName) { + this._groups[groupName].openPanels[0].close(); +}; + + +/** + * Wraps the users template in two elements, md-panel-outer-wrapper, which + * covers the entire attachTo element, and md-panel, which contains only the + * template. This allows the panel control over positioning, animations, + * and similar properties. + * @param {string} origTemplate The original template. + * @returns {string} The wrapped template. + * @private + */ +MdPanelService.prototype._wrapTemplate = function(origTemplate) { + var template = origTemplate || ''; + + // The panel should be initially rendered offscreen so we can calculate + // height and width for positioning. + return '' + + '
    ' + + '
    ' + template + '
    ' + + '
    '; +}; + + +/** + * Wraps a content element in a md-panel-outer wrapper and + * positions it off-screen. Allows for proper control over positoning + * and animations. + * @param {!angular.JQLite} contentElement Element to be wrapped. + * @return {!angular.JQLite} Wrapper element. + * @private + */ +MdPanelService.prototype._wrapContentElement = function(contentElement) { + var wrapper = angular.element('
    '); + + contentElement.addClass('md-panel _md-panel-offscreen'); + wrapper.append(contentElement); + + return wrapper; +}; + + +/***************************************************************************** + * MdPanelRef * + *****************************************************************************/ + + +/** + * A reference to a created panel. This reference contains a unique id for the + * panel, along with properties/functions used to control the panel. + * @param {!Object} config + * @param {!angular.$injector} $injector + * @final @constructor + */ +function MdPanelRef(config, $injector) { + // Injected variables. + /** @private @const {!angular.$q} */ + this._$q = $injector.get('$q'); + + /** @private @const {!angular.$mdCompiler} */ + this._$mdCompiler = $injector.get('$mdCompiler'); + + /** @private @const {!angular.$mdConstant} */ + this._$mdConstant = $injector.get('$mdConstant'); + + /** @private @const {!angular.$mdUtil} */ + this._$mdUtil = $injector.get('$mdUtil'); + + /** @private @const {!angular.$mdTheming} */ + this._$mdTheming = $injector.get('$mdTheming'); + + /** @private @const {!angular.Scope} */ + this._$rootScope = $injector.get('$rootScope'); + + /** @private @const {!angular.$animate} */ + this._$animate = $injector.get('$animate'); + + /** @private @const {!MdPanelRef} */ + this._$mdPanel = $injector.get('$mdPanel'); + + /** @private @const {!angular.$log} */ + this._$log = $injector.get('$log'); + + /** @private @const {!angular.$window} */ + this._$window = $injector.get('$window'); + + /** @private @const {!Function} */ + this._$$rAF = $injector.get('$$rAF'); + + // Public variables. + /** + * Unique id for the panelRef. + * @type {string} + */ + this.id = config.id; + + /** @type {!Object} */ + this.config = config; + + /** @type {!angular.JQLite|undefined} */ + this.panelContainer; + + /** @type {!angular.JQLite|undefined} */ + this.panelEl; + + /** + * Whether the panel is attached. This is synchronous. When attach is called, + * isAttached is set to true. When detach is called, isAttached is set to + * false. + * @type {boolean} + */ + this.isAttached = false; + + // Private variables. + /** @private {Array} */ + this._removeListeners = []; + + /** @private {!angular.JQLite|undefined} */ + this._topFocusTrap; + + /** @private {!angular.JQLite|undefined} */ + this._bottomFocusTrap; + + /** @private {!$mdPanel|undefined} */ + this._backdropRef; + + /** @private {Function?} */ + this._restoreScroll = null; + + /** + * Keeps track of all the panel interceptors. + * @private {!Object} + */ + this._interceptors = Object.create(null); + + /** + * Cleanup function, provided by `$mdCompiler` and assigned after the element + * has been compiled. When `contentElement` is used, the function is used to + * restore the element to it's proper place in the DOM. + * @private {!Function} + */ + this._compilerCleanup = null; + + /** + * Cache for saving and restoring element inline styles, CSS classes etc. + * @type {{styles: string, classes: string}} + */ + this._restoreCache = { + styles: '', + classes: '' + }; +} + + +MdPanelRef.interceptorTypes = { + CLOSE: 'onClose' +}; + + +/** + * Opens an already created and configured panel. If the panel is already + * visible, does nothing. + * @returns {!angular.$q.Promise} A promise that is resolved when + * the panel is opened and animations finish. + */ +MdPanelRef.prototype.open = function() { + var self = this; + return this._$q(function(resolve, reject) { + var done = self._done(resolve, self); + var show = self._simpleBind(self.show, self); + var checkGroupMaxOpen = function() { + if (self.config.groupName) { + angular.forEach(self.config.groupName, function(group) { + if (self._$mdPanel._openCountExceedsMaxOpen(group)) { + self._$mdPanel._closeFirstOpenedPanel(group); + } + }); + } + }; + + self.attach() + .then(show) + .then(checkGroupMaxOpen) + .then(done) + .catch(reject); + }); +}; + + +/** + * Closes the panel. + * @param {string} closeReason The event type that triggered the close. + * @returns {!angular.$q.Promise} A promise that is resolved when + * the panel is closed and animations finish. + */ +MdPanelRef.prototype.close = function(closeReason) { + var self = this; + + return this._$q(function(resolve, reject) { + self._callInterceptors(MdPanelRef.interceptorTypes.CLOSE).then(function() { + var done = self._done(resolve, self); + var detach = self._simpleBind(self.detach, self); + var onCloseSuccess = self.config['onCloseSuccess'] || angular.noop; + onCloseSuccess = angular.bind(self, onCloseSuccess, self, closeReason); + + self.hide() + .then(detach) + .then(done) + .then(onCloseSuccess) + .catch(reject); + }, reject); + }); +}; + + +/** + * Attaches the panel. The panel will be hidden afterwards. + * @returns {!angular.$q.Promise} A promise that is resolved when + * the panel is attached. + */ +MdPanelRef.prototype.attach = function() { + if (this.isAttached && this.panelEl) { + return this._$q.when(this); + } + + var self = this; + return this._$q(function(resolve, reject) { + var done = self._done(resolve, self); + var onDomAdded = self.config['onDomAdded'] || angular.noop; + var addListeners = function(response) { + self.isAttached = true; + self._addEventListeners(); + return response; + }; + + self._$q.all([ + self._createBackdrop(), + self._createPanel() + .then(addListeners) + .catch(reject) + ]).then(onDomAdded) + .then(done) + .catch(reject); + }); +}; + + +/** + * Only detaches the panel. Will NOT hide the panel first. + * @returns {!angular.$q.Promise} A promise that is resolved when + * the panel is detached. + */ +MdPanelRef.prototype.detach = function() { + if (!this.isAttached) { + return this._$q.when(this); + } + + var self = this; + var onDomRemoved = self.config['onDomRemoved'] || angular.noop; + + var detachFn = function() { + self._removeEventListeners(); + + // Remove the focus traps that we added earlier for keeping focus within + // the panel. + if (self._topFocusTrap && self._topFocusTrap.parentNode) { + self._topFocusTrap.parentNode.removeChild(self._topFocusTrap); + } + + if (self._bottomFocusTrap && self._bottomFocusTrap.parentNode) { + self._bottomFocusTrap.parentNode.removeChild(self._bottomFocusTrap); + } + + if (self._restoreCache.classes) { + self.panelEl[0].className = self._restoreCache.classes; + } + + // Either restore the saved styles or clear the ones set by mdPanel. + self.panelEl[0].style.cssText = self._restoreCache.styles || ''; + + self._compilerCleanup(); + self.panelContainer.remove(); + self.isAttached = false; + return self._$q.when(self); + }; + + if (this._restoreScroll) { + this._restoreScroll(); + this._restoreScroll = null; + } + + return this._$q(function(resolve, reject) { + var done = self._done(resolve, self); + + self._$q.all([ + detachFn(), + self._backdropRef ? self._backdropRef.detach() : true + ]).then(onDomRemoved) + .then(done) + .catch(reject); + }); +}; + + +/** + * Destroys the panel. The Panel cannot be opened again after this. + */ +MdPanelRef.prototype.destroy = function() { + var self = this; + if (this.config.groupName) { + angular.forEach(this.config.groupName, function(group) { + self.removeFromGroup(group); + }); + } + this.config.scope.$destroy(); + this.config.locals = null; + this.config.onDomAdded = null; + this.config.onDomRemoved = null; + this.config.onRemoving = null; + this.config.onOpenComplete = null; + this._interceptors = null; +}; + + +/** + * Shows the panel. + * @returns {!angular.$q.Promise} A promise that is resolved when + * the panel has shown and animations finish. + */ +MdPanelRef.prototype.show = function() { + if (!this.panelContainer) { + return this._$q(function(resolve, reject) { + reject('mdPanel: Panel does not exist yet. Call open() or attach().'); + }); + } + + if (!this.panelContainer.hasClass(MD_PANEL_HIDDEN)) { + return this._$q.when(this); + } + + var self = this; + var animatePromise = function() { + self.panelContainer.removeClass(MD_PANEL_HIDDEN); + return self._animateOpen(); + }; + + return this._$q(function(resolve, reject) { + var done = self._done(resolve, self); + var onOpenComplete = self.config['onOpenComplete'] || angular.noop; + var addToGroupOpen = function() { + if (self.config.groupName) { + angular.forEach(self.config.groupName, function(group) { + self._$mdPanel._groups[group].openPanels.push(self); + }); + } + }; + + self._$q.all([ + self._backdropRef ? self._backdropRef.show() : self, + animatePromise().then(function() { self._focusOnOpen(); }, reject) + ]).then(onOpenComplete) + .then(addToGroupOpen) + .then(done) + .catch(reject); + }); +}; + + +/** + * Hides the panel. + * @returns {!angular.$q.Promise} A promise that is resolved when + * the panel has hidden and animations finish. + */ +MdPanelRef.prototype.hide = function() { + if (!this.panelContainer) { + return this._$q(function(resolve, reject) { + reject('mdPanel: Panel does not exist yet. Call open() or attach().'); + }); + } + + if (this.panelContainer.hasClass(MD_PANEL_HIDDEN)) { + return this._$q.when(this); + } + + var self = this; + + return this._$q(function(resolve, reject) { + var done = self._done(resolve, self); + var onRemoving = self.config['onRemoving'] || angular.noop; + var hidePanel = function() { + self.panelContainer.addClass(MD_PANEL_HIDDEN); + }; + var removeFromGroupOpen = function() { + if (self.config.groupName) { + var group, index; + angular.forEach(self.config.groupName, function(group) { + group = self._$mdPanel._groups[group]; + index = group.openPanels.indexOf(self); + if (index > -1) { + group.openPanels.splice(index, 1); + } + }); + } + }; + var focusOnOrigin = function() { + var origin = self.config['origin']; + if (origin) { + getElement(origin).focus(); + } + }; + + self._$q.all([ + self._backdropRef ? self._backdropRef.hide() : self, + self._animateClose() + .then(onRemoving) + .then(hidePanel) + .then(removeFromGroupOpen) + .then(focusOnOrigin) + .catch(reject) + ]).then(done, reject); + }); +}; + + +/** + * Add a class to the panel. DO NOT use this to hide/show the panel. + * @deprecated + * This method is in the process of being deprecated in favor of using the panel + * and container JQLite elements that are referenced in the MdPanelRef object. + * Full deprecation is scheduled for material 1.2. + * + * @param {string} newClass Class to be added. + * @param {boolean} toElement Whether or not to add the class to the panel + * element instead of the container. + */ +MdPanelRef.prototype.addClass = function(newClass, toElement) { + this._$log.warn( + 'mdPanel: The addClass method is in the process of being deprecated. ' + + 'Full deprecation is scheduled for the AngularJS Material 1.2 release. ' + + 'To achieve the same results, use the panelContainer or panelEl ' + + 'JQLite elements that are referenced in MdPanelRef.'); + + if (!this.panelContainer) { + throw new Error( + 'mdPanel: Panel does not exist yet. Call open() or attach().'); + } + + if (!toElement && !this.panelContainer.hasClass(newClass)) { + this.panelContainer.addClass(newClass); + } else if (toElement && !this.panelEl.hasClass(newClass)) { + this.panelEl.addClass(newClass); + } +}; + + +/** + * Remove a class from the panel. DO NOT use this to hide/show the panel. + * @deprecated + * This method is in the process of being deprecated in favor of using the panel + * and container JQLite elements that are referenced in the MdPanelRef object. + * Full deprecation is scheduled for material 1.2. + * + * @param {string} oldClass Class to be removed. + * @param {boolean} fromElement Whether or not to remove the class from the + * panel element instead of the container. + */ +MdPanelRef.prototype.removeClass = function(oldClass, fromElement) { + this._$log.warn( + 'mdPanel: The removeClass method is in the process of being deprecated. ' + + 'Full deprecation is scheduled for the AngularJS Material 1.2 release. ' + + 'To achieve the same results, use the panelContainer or panelEl ' + + 'JQLite elements that are referenced in MdPanelRef.'); + + if (!this.panelContainer) { + throw new Error( + 'mdPanel: Panel does not exist yet. Call open() or attach().'); + } + + if (!fromElement && this.panelContainer.hasClass(oldClass)) { + this.panelContainer.removeClass(oldClass); + } else if (fromElement && this.panelEl.hasClass(oldClass)) { + this.panelEl.removeClass(oldClass); + } +}; + + +/** + * Toggle a class on the panel. DO NOT use this to hide/show the panel. + * @deprecated + * This method is in the process of being deprecated in favor of using the panel + * and container JQLite elements that are referenced in the MdPanelRef object. + * Full deprecation is scheduled for material 1.2. + * + * @param {string} toggleClass The class to toggle. + * @param {boolean} onElement Whether or not to toggle the class on the panel + * element instead of the container. + */ +MdPanelRef.prototype.toggleClass = function(toggleClass, onElement) { + this._$log.warn( + 'mdPanel: The toggleClass method is in the process of being deprecated. ' + + 'Full deprecation is scheduled for the AngularJS Material 1.2 release. ' + + 'To achieve the same results, use the panelContainer or panelEl ' + + 'JQLite elements that are referenced in MdPanelRef.'); + + if (!this.panelContainer) { + throw new Error( + 'mdPanel: Panel does not exist yet. Call open() or attach().'); + } + + if (!onElement) { + this.panelContainer.toggleClass(toggleClass); + } else { + this.panelEl.toggleClass(toggleClass); + } +}; + + +/** + * Compiles the panel, according to the passed in config and appends it to + * the DOM. Helps normalize differences in the compilation process between + * using a string template and a content element. + * @returns {!angular.$q.Promise} Promise that is resolved when + * the element has been compiled and added to the DOM. + * @private + */ +MdPanelRef.prototype._compile = function() { + var self = this; + + // Compile the element via $mdCompiler. Note that when using a + // contentElement, the element isn't actually being compiled, rather the + // compiler saves it's place in the DOM and provides a way of restoring it. + return self._$mdCompiler.compile(self.config).then(function(compileData) { + var config = self.config; + + if (config.contentElement) { + var panelEl = compileData.element; + + // Since mdPanel modifies the inline styles and CSS classes, we need + // to save them in order to be able to restore on close. + self._restoreCache.styles = panelEl[0].style.cssText; + self._restoreCache.classes = panelEl[0].className; + + self.panelContainer = self._$mdPanel._wrapContentElement(panelEl); + self.panelEl = panelEl; + } else { + self.panelContainer = compileData.link(config['scope']); + self.panelEl = angular.element( + self.panelContainer[0].querySelector('.md-panel') + ); + } + + // Save a reference to the cleanup function from the compiler. + self._compilerCleanup = compileData.cleanup; + + // Attach the panel to the proper place in the DOM. + getElement(self.config['attachTo']).append(self.panelContainer); + + return self; + }); +}; + + +/** + * Creates a panel and adds it to the dom. + * @returns {!angular.$q.Promise} A promise that is resolved when the panel is + * created. + * @private + */ +MdPanelRef.prototype._createPanel = function() { + var self = this; + + return this._$q(function(resolve, reject) { + if (!self.config.locals) { + self.config.locals = {}; + } + + self.config.locals.mdPanelRef = self; + + self._compile().then(function() { + if (self.config['disableParentScroll']) { + self._restoreScroll = self._$mdUtil.disableScrollAround( + null, + self.panelContainer, + { disableScrollMask: true } + ); + } + + // Add a custom CSS class to the panel element. + if (self.config['panelClass']) { + self.panelEl.addClass(self.config['panelClass']); + } + + // Handle click and touch events for the panel container. + if (self.config['propagateContainerEvents']) { + self.panelContainer.css('pointer-events', 'none'); + self.panelEl.css('pointer-events', 'all'); + } + + // Panel may be outside the $rootElement, tell ngAnimate to animate + // regardless. + if (self._$animate.pin) { + self._$animate.pin( + self.panelContainer, + getElement(self.config['attachTo']) + ); + } + + self._configureTrapFocus(); + self._addStyles().then(function() { + resolve(self); + }, reject); + }, reject); + + }); +}; + + +/** + * Adds the styles for the panel, such as positioning and z-index. Also, + * themes the panel element and panel container using `$mdTheming`. + * @returns {!angular.$q.Promise} + * @private + */ +MdPanelRef.prototype._addStyles = function() { + var self = this; + return this._$q(function(resolve) { + self.panelContainer.css('z-index', self.config['zIndex']); + self.panelEl.css('z-index', self.config['zIndex'] + 1); + + var hideAndResolve = function() { + // Theme the element and container. + self._setTheming(); + + // Remove offscreen class and add hidden class. + self.panelEl.removeClass('_md-panel-offscreen'); + self.panelContainer.addClass(MD_PANEL_HIDDEN); + + resolve(self); + }; + + if (self.config['fullscreen']) { + self.panelEl.addClass('_md-panel-fullscreen'); + hideAndResolve(); + return; // Don't setup positioning. + } + + var positionConfig = self.config['position']; + if (!positionConfig) { + hideAndResolve(); + return; // Don't setup positioning. + } + + // Wait for angular to finish processing the template + self._$rootScope['$$postDigest'](function() { + // Position it correctly. This is necessary so that the panel will have a + // defined height and width. + self._updatePosition(true); + + // Theme the element and container. + self._setTheming(); + + resolve(self); + }); + }); +}; + + +/** + * Sets the `$mdTheming` classes on the `panelContainer` and `panelEl`. + * @private + */ +MdPanelRef.prototype._setTheming = function() { + this._$mdTheming(this.panelEl); + this._$mdTheming(this.panelContainer); +}; + + +/** + * Updates the position configuration of a panel + * @param {!MdPanelPosition} position + */ +MdPanelRef.prototype.updatePosition = function(position) { + if (!this.panelContainer) { + throw new Error( + 'mdPanel: Panel does not exist yet. Call open() or attach().'); + } + + this.config['position'] = position; + this._updatePosition(); +}; + + +/** + * Calculates and updates the position of the panel. + * @param {boolean=} init + * @private + */ +MdPanelRef.prototype._updatePosition = function(init) { + var positionConfig = this.config['position']; + + if (positionConfig) { + positionConfig._setPanelPosition(this.panelEl); + + // Hide the panel now that position is known. + if (init) { + this.panelEl.removeClass('_md-panel-offscreen'); + this.panelContainer.addClass(MD_PANEL_HIDDEN); + } + + this.panelEl.css( + MdPanelPosition.absPosition.TOP, + positionConfig.getTop() + ); + this.panelEl.css( + MdPanelPosition.absPosition.BOTTOM, + positionConfig.getBottom() + ); + this.panelEl.css( + MdPanelPosition.absPosition.LEFT, + positionConfig.getLeft() + ); + this.panelEl.css( + MdPanelPosition.absPosition.RIGHT, + positionConfig.getRight() + ); + } +}; + + +/** + * Focuses on the panel or the first focus target. + * @private + */ +MdPanelRef.prototype._focusOnOpen = function() { + if (this.config['focusOnOpen']) { + // Wait for the template to finish rendering to guarantee md-autofocus has + // finished adding the class md-autofocus, otherwise the focusable element + // isn't available to focus. + var self = this; + this._$rootScope['$$postDigest'](function() { + var target = self._$mdUtil.findFocusTarget(self.panelEl) || + self.panelEl; + target.focus(); + }); + } +}; + + +/** + * Shows the backdrop. + * @returns {!angular.$q.Promise} A promise that is resolved when the backdrop + * is created and attached. + * @private + */ +MdPanelRef.prototype._createBackdrop = function() { + if (this.config.hasBackdrop) { + if (!this._backdropRef) { + var backdropAnimation = this._$mdPanel.newPanelAnimation() + .openFrom(this.config.attachTo) + .withAnimation({ + open: '_md-opaque-enter', + close: '_md-opaque-leave' + }); + + if (this.config.animation) { + backdropAnimation.duration(this.config.animation._rawDuration); + } + + var backdropConfig = { + animation: backdropAnimation, + attachTo: this.config.attachTo, + focusOnOpen: false, + panelClass: '_md-panel-backdrop', + zIndex: this.config.zIndex - 1 + }; + + this._backdropRef = this._$mdPanel.create(backdropConfig); + } + if (!this._backdropRef.isAttached) { + return this._backdropRef.attach(); + } + } +}; + + +/** + * Listen for escape keys and outside clicks to auto close. + * @private + */ +MdPanelRef.prototype._addEventListeners = function() { + this._configureEscapeToClose(); + this._configureClickOutsideToClose(); + this._configureScrollListener(); +}; + + +/** + * Remove event listeners added in _addEventListeners. + * @private + */ +MdPanelRef.prototype._removeEventListeners = function() { + this._removeListeners && this._removeListeners.forEach(function(removeFn) { + removeFn(); + }); + this._removeListeners = []; +}; + + +/** + * Setup the escapeToClose event listeners. + * @private + */ +MdPanelRef.prototype._configureEscapeToClose = function() { + if (this.config['escapeToClose']) { + var parentTarget = getElement(this.config['attachTo']); + var self = this; + + var keyHandlerFn = function(ev) { + if (ev.keyCode === self._$mdConstant.KEY_CODE.ESCAPE) { + ev.stopPropagation(); + ev.preventDefault(); + + self.close(MdPanelRef.closeReasons.ESCAPE); + } + }; + + // Add keydown listeners + this.panelContainer.on('keydown', keyHandlerFn); + parentTarget.on('keydown', keyHandlerFn); + + // Queue remove listeners function + this._removeListeners.push(function() { + self.panelContainer.off('keydown', keyHandlerFn); + parentTarget.off('keydown', keyHandlerFn); + }); + } +}; + + +/** + * Setup the clickOutsideToClose event listeners. + * @private + */ +MdPanelRef.prototype._configureClickOutsideToClose = function() { + if (this.config['clickOutsideToClose']) { + var target = this.config['propagateContainerEvents'] ? + angular.element(document.body) : + this.panelContainer; + var sourceEl; + + // Keep track of the element on which the mouse originally went down + // so that we can only close the backdrop when the 'click' started on it. + // A simple 'click' handler does not work, it sets the target object as the + // element the mouse went down on. + var mousedownHandler = function(ev) { + sourceEl = ev.target; + }; + + // We check if our original element and the target is the backdrop + // because if the original was the backdrop and the target was inside the + // panel we don't want to panel to close. + var self = this; + var mouseupHandler = function(ev) { + if (self.config['propagateContainerEvents']) { + + // We check if the sourceEl of the event is the panel element or one + // of it's children. If it is not, then close the panel. + if (sourceEl !== self.panelEl[0] && !self.panelEl[0].contains(sourceEl)) { + self.close(); + } + + } else if (sourceEl === target[0] && ev.target === target[0]) { + ev.stopPropagation(); + ev.preventDefault(); + + self.close(MdPanelRef.closeReasons.CLICK_OUTSIDE); + } + }; + + // Add listeners + target.on('mousedown', mousedownHandler); + target.on('mouseup', mouseupHandler); + + // Queue remove listeners function + this._removeListeners.push(function() { + target.off('mousedown', mousedownHandler); + target.off('mouseup', mouseupHandler); + }); + } +}; + + +/** + * Configures the listeners for updating the panel position on scroll. + * @private +*/ +MdPanelRef.prototype._configureScrollListener = function() { + // No need to bind the event if scrolling is disabled. + if (!this.config['disableParentScroll']) { + var updatePosition = angular.bind(this, this._updatePosition); + var debouncedUpdatePosition = this._$$rAF.throttle(updatePosition); + var self = this; + + var onScroll = function() { + debouncedUpdatePosition(); + }; + + // Add listeners. + this._$window.addEventListener('scroll', onScroll, true); + + // Queue remove listeners function. + this._removeListeners.push(function() { + self._$window.removeEventListener('scroll', onScroll, true); + }); + } +}; + + +/** + * Setup the focus traps. These traps will wrap focus when tabbing past the + * panel. When shift-tabbing, the focus will stick in place. + * @private + */ +MdPanelRef.prototype._configureTrapFocus = function() { + // Focus doesn't remain inside of the panel without this. + this.panelEl.attr('tabIndex', '-1'); + if (this.config['trapFocus']) { + var element = this.panelEl; + // Set up elements before and after the panel to capture focus and + // redirect back into the panel. + this._topFocusTrap = FOCUS_TRAP_TEMPLATE.clone()[0]; + this._bottomFocusTrap = FOCUS_TRAP_TEMPLATE.clone()[0]; + + // When focus is about to move out of the panel, we want to intercept it + // and redirect it back to the panel element. + var focusHandler = function() { + element.focus(); + }; + this._topFocusTrap.addEventListener('focus', focusHandler); + this._bottomFocusTrap.addEventListener('focus', focusHandler); + + // Queue remove listeners function + this._removeListeners.push(this._simpleBind(function() { + this._topFocusTrap.removeEventListener('focus', focusHandler); + this._bottomFocusTrap.removeEventListener('focus', focusHandler); + }, this)); + + // The top focus trap inserted immediately before the md-panel element (as + // a sibling). The bottom focus trap inserted immediately after the + // md-panel element (as a sibling). + element[0].parentNode.insertBefore(this._topFocusTrap, element[0]); + element.after(this._bottomFocusTrap); + } +}; + + +/** + * Updates the animation of a panel. + * @param {!MdPanelAnimation} animation + */ +MdPanelRef.prototype.updateAnimation = function(animation) { + this.config['animation'] = animation; + + if (this._backdropRef) { + this._backdropRef.config.animation.duration(animation._rawDuration); + } +}; + + +/** + * Animate the panel opening. + * @returns {!angular.$q.Promise} A promise that is resolved when the panel has + * animated open. + * @private + */ +MdPanelRef.prototype._animateOpen = function() { + this.panelContainer.addClass('md-panel-is-showing'); + var animationConfig = this.config['animation']; + if (!animationConfig) { + // Promise is in progress, return it. + this.panelContainer.addClass('_md-panel-shown'); + return this._$q.when(this); + } + + var self = this; + return this._$q(function(resolve) { + var done = self._done(resolve, self); + var warnAndOpen = function() { + self._$log.warn( + 'mdPanel: MdPanel Animations failed. ' + + 'Showing panel without animating.'); + done(); + }; + + animationConfig.animateOpen(self.panelEl) + .then(done, warnAndOpen); + }); +}; + + +/** + * Animate the panel closing. + * @returns {!angular.$q.Promise} A promise that is resolved when the panel has + * animated closed. + * @private + */ +MdPanelRef.prototype._animateClose = function() { + var animationConfig = this.config['animation']; + if (!animationConfig) { + this.panelContainer.removeClass('md-panel-is-showing'); + this.panelContainer.removeClass('_md-panel-shown'); + return this._$q.when(this); + } + + var self = this; + return this._$q(function(resolve) { + var done = function() { + self.panelContainer.removeClass('md-panel-is-showing'); + resolve(self); + }; + var warnAndClose = function() { + self._$log.warn( + 'mdPanel: MdPanel Animations failed. ' + + 'Hiding panel without animating.'); + done(); + }; + + animationConfig.animateClose(self.panelEl) + .then(done, warnAndClose); + }); +}; + + +/** + * Registers a interceptor with the panel. The callback should return a promise, + * which will allow the action to continue when it gets resolved, or will + * prevent an action if it is rejected. + * @param {string} type Type of interceptor. + * @param {!angular.$q.Promise} callback Callback to be registered. + * @returns {!MdPanelRef} + */ +MdPanelRef.prototype.registerInterceptor = function(type, callback) { + var error = null; + + if (!angular.isString(type)) { + error = 'Interceptor type must be a string, instead got ' + typeof type; + } else if (!angular.isFunction(callback)) { + error = 'Interceptor callback must be a function, instead got ' + typeof callback; + } + + if (error) { + throw new Error('MdPanel: ' + error); + } + + var interceptors = this._interceptors[type] = this._interceptors[type] || []; + + if (interceptors.indexOf(callback) === -1) { + interceptors.push(callback); + } + + return this; +}; + + +/** + * Removes a registered interceptor. + * @param {string} type Type of interceptor to be removed. + * @param {Function} callback Interceptor to be removed. + * @returns {!MdPanelRef} + */ +MdPanelRef.prototype.removeInterceptor = function(type, callback) { + var index = this._interceptors[type] ? + this._interceptors[type].indexOf(callback) : -1; + + if (index > -1) { + this._interceptors[type].splice(index, 1); + } + + return this; +}; + + +/** + * Removes all interceptors. + * @param {string=} type Type of interceptors to be removed. + * If ommited, all interceptors types will be removed. + * @returns {!MdPanelRef} + */ +MdPanelRef.prototype.removeAllInterceptors = function(type) { + if (type) { + this._interceptors[type] = []; + } else { + this._interceptors = Object.create(null); + } + + return this; +}; + + +/** + * Invokes all the interceptors of a certain type sequantially in + * reverse order. Works in a similar way to `$q.all`, except it + * respects the order of the functions. + * @param {string} type Type of interceptors to be invoked. + * @returns {!angular.$q.Promise} + * @private + */ +MdPanelRef.prototype._callInterceptors = function(type) { + var self = this; + var $q = self._$q; + var interceptors = self._interceptors && self._interceptors[type] || []; + + return interceptors.reduceRight(function(promise, interceptor) { + var isPromiseLike = interceptor && angular.isFunction(interceptor.then); + var response = isPromiseLike ? interceptor : null; + + /** + * For interceptors to reject/cancel subsequent portions of the chain, simply + * return a `$q.reject()` + */ + return promise.then(function() { + if (!response) { + try { + response = interceptor(self); + } catch (e) { + response = $q.reject(e); + } + } + + return response; + }); + }, $q.resolve(self)); +}; + + +/** + * Faster, more basic than angular.bind + * http://jsperf.com/angular-bind-vs-custom-vs-native + * @param {function} callback + * @param {!Object} self + * @return {function} Callback function with a bound self. + */ +MdPanelRef.prototype._simpleBind = function(callback, self) { + return function(value) { + return callback.apply(self, value); + }; +}; + + +/** + * @param {function} callback + * @param {!Object} self + * @return {function} Callback function with a self param. + */ +MdPanelRef.prototype._done = function(callback, self) { + return function() { + callback(self); + }; +}; + + +/** + * Adds a panel to a group if the panel does not exist within the group already. + * A panel can only exist within a single group. + * @param {string} groupName The name of the group. + */ +MdPanelRef.prototype.addToGroup = function(groupName) { + if (!this._$mdPanel._groups[groupName]) { + this._$mdPanel.newPanelGroup(groupName); + } + + var group = this._$mdPanel._groups[groupName]; + var index = group.panels.indexOf(this); + + if (index < 0) { + group.panels.push(this); + } +}; + + +/** + * Removes a panel from a group if the panel exists within that group. The group + * must be created ahead of time. + * @param {string} groupName The name of the group. + */ +MdPanelRef.prototype.removeFromGroup = function(groupName) { + if (!this._$mdPanel._groups[groupName]) { + throw new Error('mdPanel: The group ' + groupName + ' does not exist.'); + } + + var group = this._$mdPanel._groups[groupName]; + var index = group.panels.indexOf(this); + + if (index > -1) { + group.panels.splice(index, 1); + } +}; + + +/** + * Possible default closeReasons for the close function. + * @enum {string} + */ +MdPanelRef.closeReasons = { + CLICK_OUTSIDE: 'clickOutsideToClose', + ESCAPE: 'escapeToClose', +}; + + +/***************************************************************************** + * MdPanelPosition * + *****************************************************************************/ + + +/** + * Position configuration object. To use, create an MdPanelPosition with the + * desired properties, then pass the object as part of $mdPanel creation. + * + * Example: + * + * var panelPosition = new MdPanelPosition() + * .relativeTo(myButtonEl) + * .addPanelPosition( + * $mdPanel.xPosition.CENTER, + * $mdPanel.yPosition.ALIGN_TOPS + * ); + * + * $mdPanel.create({ + * position: panelPosition + * }); + * + * @param {!angular.$injector} $injector + * @final @constructor + */ +function MdPanelPosition($injector) { + /** @private @const {!angular.$window} */ + this._$window = $injector.get('$window'); + + /** @private {boolean} */ + this._isRTL = $injector.get('$mdUtil').bidi() === 'rtl'; + + /** @private @const {!angular.$mdConstant} */ + this._$mdConstant = $injector.get('$mdConstant'); + + /** @private {boolean} */ + this._absolute = false; + + /** @private {!angular.JQLite} */ + this._relativeToEl; + + /** @private {string} */ + this._top = ''; + + /** @private {string} */ + this._bottom = ''; + + /** @private {string} */ + this._left = ''; + + /** @private {string} */ + this._right = ''; + + /** @private {!Array} */ + this._translateX = []; + + /** @private {!Array} */ + this._translateY = []; + + /** @private {!Array<{x:string, y:string}>} */ + this._positions = []; + + /** @private {?{x:string, y:string}} */ + this._actualPosition; +} + + +/** + * Possible values of xPosition. + * @enum {string} + */ +MdPanelPosition.xPosition = { + CENTER: 'center', + ALIGN_START: 'align-start', + ALIGN_END: 'align-end', + OFFSET_START: 'offset-start', + OFFSET_END: 'offset-end' +}; + + +/** + * Possible values of yPosition. + * @enum {string} + */ +MdPanelPosition.yPosition = { + CENTER: 'center', + ALIGN_TOPS: 'align-tops', + ALIGN_BOTTOMS: 'align-bottoms', + ABOVE: 'above', + BELOW: 'below' +}; + + +/** + * Possible values of absolute position. + * @enum {string} + */ +MdPanelPosition.absPosition = { + TOP: 'top', + RIGHT: 'right', + BOTTOM: 'bottom', + LEFT: 'left' +}; + +/** + * Margin between the edges of a panel and the viewport. + * @const {number} + */ +MdPanelPosition.viewportMargin = 8; + + +/** + * Sets absolute positioning for the panel. + * @return {!MdPanelPosition} + */ +MdPanelPosition.prototype.absolute = function() { + this._absolute = true; + return this; +}; + + +/** + * Sets the value of a position for the panel. Clears any previously set + * position. + * @param {string} position Position to set + * @param {string=} value Value of the position. Defaults to '0'. + * @returns {!MdPanelPosition} + * @private + */ +MdPanelPosition.prototype._setPosition = function(position, value) { + if (position === MdPanelPosition.absPosition.RIGHT || + position === MdPanelPosition.absPosition.LEFT) { + this._left = this._right = ''; + } else if ( + position === MdPanelPosition.absPosition.BOTTOM || + position === MdPanelPosition.absPosition.TOP) { + this._top = this._bottom = ''; + } else { + var positions = Object.keys(MdPanelPosition.absPosition).join() + .toLowerCase(); + + throw new Error('mdPanel: Position must be one of ' + positions + '.'); + } + + this['_' + position] = angular.isString(value) ? value : '0'; + + return this; +}; + + +/** + * Sets the value of `top` for the panel. Clears any previously set vertical + * position. + * @param {string=} top Value of `top`. Defaults to '0'. + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.top = function(top) { + return this._setPosition(MdPanelPosition.absPosition.TOP, top); +}; + + +/** + * Sets the value of `bottom` for the panel. Clears any previously set vertical + * position. + * @param {string=} bottom Value of `bottom`. Defaults to '0'. + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.bottom = function(bottom) { + return this._setPosition(MdPanelPosition.absPosition.BOTTOM, bottom); +}; + + +/** + * Sets the panel to the start of the page - `left` if `ltr` or `right` for + * `rtl`. Clears any previously set horizontal position. + * @param {string=} start Value of position. Defaults to '0'. + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.start = function(start) { + var position = this._isRTL ? MdPanelPosition.absPosition.RIGHT : MdPanelPosition.absPosition.LEFT; + return this._setPosition(position, start); +}; + + +/** + * Sets the panel to the end of the page - `right` if `ltr` or `left` for `rtl`. + * Clears any previously set horizontal position. + * @param {string=} end Value of position. Defaults to '0'. + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.end = function(end) { + var position = this._isRTL ? MdPanelPosition.absPosition.LEFT : MdPanelPosition.absPosition.RIGHT; + return this._setPosition(position, end); +}; + + +/** + * Sets the value of `left` for the panel. Clears any previously set + * horizontal position. + * @param {string=} left Value of `left`. Defaults to '0'. + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.left = function(left) { + return this._setPosition(MdPanelPosition.absPosition.LEFT, left); +}; + + +/** + * Sets the value of `right` for the panel. Clears any previously set + * horizontal position. + * @param {string=} right Value of `right`. Defaults to '0'. + * @returns {!MdPanelPosition} +*/ +MdPanelPosition.prototype.right = function(right) { + return this._setPosition(MdPanelPosition.absPosition.RIGHT, right); +}; + + +/** + * Centers the panel horizontally in the viewport. Clears any previously set + * horizontal position. + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.centerHorizontally = function() { + this._left = '50%'; + this._right = ''; + this._translateX = ['-50%']; + return this; +}; + + +/** + * Centers the panel vertically in the viewport. Clears any previously set + * vertical position. + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.centerVertically = function() { + this._top = '50%'; + this._bottom = ''; + this._translateY = ['-50%']; + return this; +}; + + +/** + * Centers the panel horizontally and vertically in the viewport. This is + * equivalent to calling both `centerHorizontally` and `centerVertically`. + * Clears any previously set horizontal and vertical positions. + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.center = function() { + return this.centerHorizontally().centerVertically(); +}; + + +/** + * Sets element for relative positioning. + * @param {string|!Element|!angular.JQLite} element Query selector, DOM element, + * or angular element to set the panel relative to. + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.relativeTo = function(element) { + this._absolute = false; + this._relativeToEl = getElement(element); + return this; +}; + + +/** + * Sets the x and y positions for the panel relative to another element. + * @param {string} xPosition must be one of the MdPanelPosition.xPosition + * values. + * @param {string} yPosition must be one of the MdPanelPosition.yPosition + * values. + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.addPanelPosition = function(xPosition, yPosition) { + if (!this._relativeToEl) { + throw new Error('mdPanel: addPanelPosition can only be used with ' + + 'relative positioning. Set relativeTo first.'); + } + + this._validateXPosition(xPosition); + this._validateYPosition(yPosition); + + this._positions.push({ + x: xPosition, + y: yPosition, + }); + return this; +}; + + +/** + * Ensures that yPosition is a valid position name. Throw an exception if not. + * @param {string} yPosition + */ +MdPanelPosition.prototype._validateYPosition = function(yPosition) { + // empty is ok + if (yPosition == null) { + return; + } + + var positionKeys = Object.keys(MdPanelPosition.yPosition); + var positionValues = []; + for (var key, i = 0; key = positionKeys[i]; i++) { + var position = MdPanelPosition.yPosition[key]; + positionValues.push(position); + + if (position === yPosition) { + return; + } + } + + throw new Error('mdPanel: Panel y position only accepts the following ' + + 'values:\n' + positionValues.join(' | ')); +}; + + +/** + * Ensures that xPosition is a valid position name. Throw an exception if not. + * @param {string} xPosition + */ +MdPanelPosition.prototype._validateXPosition = function(xPosition) { + // empty is ok + if (xPosition == null) { + return; + } + + var positionKeys = Object.keys(MdPanelPosition.xPosition); + var positionValues = []; + for (var key, i = 0; key = positionKeys[i]; i++) { + var position = MdPanelPosition.xPosition[key]; + positionValues.push(position); + if (position === xPosition) { + return; + } + } + + throw new Error('mdPanel: Panel x Position only accepts the following ' + + 'values:\n' + positionValues.join(' | ')); +}; + + +/** + * Sets the value of the offset in the x-direction. This will add to any + * previously set offsets. + * @param {string|number|function(MdPanelPosition): string} offsetX + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.withOffsetX = function(offsetX) { + this._translateX.push(addUnits(offsetX)); + return this; +}; + + +/** + * Sets the value of the offset in the y-direction. This will add to any + * previously set offsets. + * @param {string|number|function(MdPanelPosition): string} offsetY + * @returns {!MdPanelPosition} + */ +MdPanelPosition.prototype.withOffsetY = function(offsetY) { + this._translateY.push(addUnits(offsetY)); + return this; +}; + + +/** + * Gets the value of `top` for the panel. + * @returns {string} + */ +MdPanelPosition.prototype.getTop = function() { + return this._top; +}; + + +/** + * Gets the value of `bottom` for the panel. + * @returns {string} + */ +MdPanelPosition.prototype.getBottom = function() { + return this._bottom; +}; + + +/** + * Gets the value of `left` for the panel. + * @returns {string} + */ +MdPanelPosition.prototype.getLeft = function() { + return this._left; +}; + + +/** + * Gets the value of `right` for the panel. + * @returns {string} + */ +MdPanelPosition.prototype.getRight = function() { + return this._right; +}; + + +/** + * Gets the value of `transform` for the panel. + * @returns {string} + */ +MdPanelPosition.prototype.getTransform = function() { + var translateX = this._reduceTranslateValues('translateX', this._translateX); + var translateY = this._reduceTranslateValues('translateY', this._translateY); + + // It's important to trim the result, because the browser will ignore the set + // operation if the string contains only whitespace. + return (translateX + ' ' + translateY).trim(); +}; + + +/** + * Sets the `transform` value for a panel element. + * @param {!angular.JQLite} panelEl + * @returns {!angular.JQLite} + * @private + */ +MdPanelPosition.prototype._setTransform = function(panelEl) { + return panelEl.css(this._$mdConstant.CSS.TRANSFORM, this.getTransform()); +}; + + +/** + * True if the panel is completely on-screen with this positioning; false + * otherwise. + * @param {!angular.JQLite} panelEl + * @return {boolean} + * @private + */ +MdPanelPosition.prototype._isOnscreen = function(panelEl) { + // this works because we always use fixed positioning for the panel, + // which is relative to the viewport. + var left = parseInt(this.getLeft()); + var top = parseInt(this.getTop()); + + if (this._translateX.length || this._translateY.length) { + var prefixedTransform = this._$mdConstant.CSS.TRANSFORM; + var offsets = getComputedTranslations(panelEl, prefixedTransform); + left += offsets.x; + top += offsets.y; + } + + var right = left + panelEl[0].offsetWidth; + var bottom = top + panelEl[0].offsetHeight; + + return (left >= 0) && + (top >= 0) && + (bottom <= this._$window.innerHeight) && + (right <= this._$window.innerWidth); +}; + + +/** + * Gets the first x/y position that can fit on-screen. + * @returns {{x: string, y: string}} + */ +MdPanelPosition.prototype.getActualPosition = function() { + return this._actualPosition; +}; + + +/** + * Reduces a list of translate values to a string that can be used within + * transform. + * @param {string} translateFn + * @param {!Array} values + * @returns {string} + * @private + */ +MdPanelPosition.prototype._reduceTranslateValues = + function(translateFn, values) { + return values.map(function(translation) { + var translationValue = angular.isFunction(translation) ? + addUnits(translation(this)) : translation; + return translateFn + '(' + translationValue + ')'; + }, this).join(' '); + }; + + +/** + * Sets the panel position based on the created panel element and best x/y + * positioning. + * @param {!angular.JQLite} panelEl + * @private + */ +MdPanelPosition.prototype._setPanelPosition = function(panelEl) { + // Remove the "position adjusted" class in case it has been added before. + panelEl.removeClass('_md-panel-position-adjusted'); + + // Only calculate the position if necessary. + if (this._absolute) { + this._setTransform(panelEl); + return; + } + + if (this._actualPosition) { + this._calculatePanelPosition(panelEl, this._actualPosition); + this._setTransform(panelEl); + this._constrainToViewport(panelEl); + return; + } + + for (var i = 0; i < this._positions.length; i++) { + this._actualPosition = this._positions[i]; + this._calculatePanelPosition(panelEl, this._actualPosition); + this._setTransform(panelEl); + + if (this._isOnscreen(panelEl)) { + return; + } + } + + this._constrainToViewport(panelEl); +}; + + +/** + * Constrains a panel's position to the viewport. + * @param {!angular.JQLite} panelEl + * @private + */ +MdPanelPosition.prototype._constrainToViewport = function(panelEl) { + var margin = MdPanelPosition.viewportMargin; + var initialTop = this._top; + var initialLeft = this._left; + + if (this.getTop()) { + var top = parseInt(this.getTop()); + var bottom = panelEl[0].offsetHeight + top; + var viewportHeight = this._$window.innerHeight; + + if (top < margin) { + this._top = margin + 'px'; + } else if (bottom > viewportHeight) { + this._top = top - (bottom - viewportHeight + margin) + 'px'; + } + } + + if (this.getLeft()) { + var left = parseInt(this.getLeft()); + var right = panelEl[0].offsetWidth + left; + var viewportWidth = this._$window.innerWidth; + + if (left < margin) { + this._left = margin + 'px'; + } else if (right > viewportWidth) { + this._left = left - (right - viewportWidth + margin) + 'px'; + } + } + + // Class that can be used to re-style the panel if it was repositioned. + panelEl.toggleClass( + '_md-panel-position-adjusted', + this._top !== initialTop || this._left !== initialLeft + ); +}; + + +/** + * Switches between 'start' and 'end'. + * @param {string} position Horizontal position of the panel + * @returns {string} Reversed position + * @private + */ +MdPanelPosition.prototype._reverseXPosition = function(position) { + if (position === MdPanelPosition.xPosition.CENTER) { + return position; + } + + var start = 'start'; + var end = 'end'; + + return position.indexOf(start) > -1 ? position.replace(start, end) : position.replace(end, start); +}; + + +/** + * Handles horizontal positioning in rtl or ltr environments. + * @param {string} position Horizontal position of the panel + * @returns {string} The correct position according the page direction + * @private + */ +MdPanelPosition.prototype._bidi = function(position) { + return this._isRTL ? this._reverseXPosition(position) : position; +}; + + +/** + * Calculates the panel position based on the created panel element and the + * provided positioning. + * @param {!angular.JQLite} panelEl + * @param {!{x:string, y:string}} position + * @private + */ +MdPanelPosition.prototype._calculatePanelPosition = function(panelEl, position) { + + var panelBounds = panelEl[0].getBoundingClientRect(); + var panelWidth = Math.max(panelBounds.width, panelEl[0].clientWidth); + var panelHeight = Math.max(panelBounds.height, panelEl[0].clientHeight); + + var targetBounds = this._relativeToEl[0].getBoundingClientRect(); + + var targetLeft = targetBounds.left; + var targetRight = targetBounds.right; + var targetWidth = targetBounds.width; + + switch (this._bidi(position.x)) { + case MdPanelPosition.xPosition.OFFSET_START: + this._left = targetLeft - panelWidth + 'px'; + break; + case MdPanelPosition.xPosition.ALIGN_END: + this._left = targetRight - panelWidth + 'px'; + break; + case MdPanelPosition.xPosition.CENTER: + var left = targetLeft + (0.5 * targetWidth) - (0.5 * panelWidth); + this._left = left + 'px'; + break; + case MdPanelPosition.xPosition.ALIGN_START: + this._left = targetLeft + 'px'; + break; + case MdPanelPosition.xPosition.OFFSET_END: + this._left = targetRight + 'px'; + break; + } + + var targetTop = targetBounds.top; + var targetBottom = targetBounds.bottom; + var targetHeight = targetBounds.height; + + switch (position.y) { + case MdPanelPosition.yPosition.ABOVE: + this._top = targetTop - panelHeight + 'px'; + break; + case MdPanelPosition.yPosition.ALIGN_BOTTOMS: + this._top = targetBottom - panelHeight + 'px'; + break; + case MdPanelPosition.yPosition.CENTER: + var top = targetTop + (0.5 * targetHeight) - (0.5 * panelHeight); + this._top = top + 'px'; + break; + case MdPanelPosition.yPosition.ALIGN_TOPS: + this._top = targetTop + 'px'; + break; + case MdPanelPosition.yPosition.BELOW: + this._top = targetBottom + 'px'; + break; + } +}; + + +/***************************************************************************** + * MdPanelAnimation * + *****************************************************************************/ + + +/** + * Animation configuration object. To use, create an MdPanelAnimation with the + * desired properties, then pass the object as part of $mdPanel creation. + * + * Example: + * + * var panelAnimation = new MdPanelAnimation() + * .openFrom(myButtonEl) + * .closeTo('.my-button') + * .withAnimation($mdPanel.animation.SCALE); + * + * $mdPanel.create({ + * animation: panelAnimation + * }); + * + * @param {!angular.$injector} $injector + * @final @constructor + */ +function MdPanelAnimation($injector) { + /** @private @const {!angular.$mdUtil} */ + this._$mdUtil = $injector.get('$mdUtil'); + + /** + * @private {{element: !angular.JQLite|undefined, bounds: !DOMRect}| + * undefined} + */ + this._openFrom; + + /** + * @private {{element: !angular.JQLite|undefined, bounds: !DOMRect}| + * undefined} + */ + this._closeTo; + + /** @private {string|{open: string, close: string}} */ + this._animationClass = ''; + + /** @private {number} */ + this._openDuration; + + /** @private {number} */ + this._closeDuration; + + /** @private {number|{open: number, close: number}} */ + this._rawDuration; +} + + +/** + * Possible default animations. + * @enum {string} + */ +MdPanelAnimation.animation = { + SLIDE: 'md-panel-animate-slide', + SCALE: 'md-panel-animate-scale', + FADE: 'md-panel-animate-fade' +}; + + +/** + * Specifies where to start the open animation. `openFrom` accepts a + * click event object, query selector, DOM element, or a Rect object that + * is used to determine the bounds. When passed a click event, the location + * of the click will be used as the position to start the animation. + * @param {string|!Element|!Event|{top: number, left: number}} openFrom + * @returns {!MdPanelAnimation} + */ +MdPanelAnimation.prototype.openFrom = function(openFrom) { + // Check if 'openFrom' is an Event. + openFrom = openFrom.target ? openFrom.target : openFrom; + + this._openFrom = this._getPanelAnimationTarget(openFrom); + + if (!this._closeTo) { + this._closeTo = this._openFrom; + } + return this; +}; + + +/** + * Specifies where to animate the panel close. `closeTo` accepts a + * query selector, DOM element, or a Rect object that is used to determine + * the bounds. + * @param {string|!Element|{top: number, left: number}} closeTo + * @returns {!MdPanelAnimation} + */ +MdPanelAnimation.prototype.closeTo = function(closeTo) { + this._closeTo = this._getPanelAnimationTarget(closeTo); + return this; +}; + + +/** + * Specifies the duration of the animation in milliseconds. + * @param {number|{open: number, close: number}} duration + * @returns {!MdPanelAnimation} + */ +MdPanelAnimation.prototype.duration = function(duration) { + if (duration) { + if (angular.isNumber(duration)) { + this._openDuration = this._closeDuration = toSeconds(duration); + } else if (angular.isObject(duration)) { + this._openDuration = toSeconds(duration.open); + this._closeDuration = toSeconds(duration.close); + } + } + + // Save the original value so it can be passed to the backdrop. + this._rawDuration = duration; + + return this; + + function toSeconds(value) { + if (angular.isNumber(value)) return value / 1000; + } +}; + + +/** + * Returns the element and bounds for the animation target. + * @param {string|!Element|{top: number, left: number}} location + * @returns {{element: !angular.JQLite|undefined, bounds: !DOMRect}} + * @private + */ +MdPanelAnimation.prototype._getPanelAnimationTarget = function(location) { + if (angular.isDefined(location.top) || angular.isDefined(location.left)) { + return { + element: undefined, + bounds: { + top: location.top || 0, + left: location.left || 0 + } + }; + } else { + return this._getBoundingClientRect(getElement(location)); + } +}; + + +/** + * Specifies the animation class. + * + * There are several default animations that can be used: + * (MdPanelAnimation.animation) + * SLIDE: The panel slides in and out from the specified + * elements. + * SCALE: The panel scales in and out. + * FADE: The panel fades in and out. + * + * @param {string|{open: string, close: string}} cssClass + * @returns {!MdPanelAnimation} + */ +MdPanelAnimation.prototype.withAnimation = function(cssClass) { + this._animationClass = cssClass; + return this; +}; + + +/** + * Animate the panel open. + * @param {!angular.JQLite} panelEl + * @returns {!angular.$q.Promise} A promise that is resolved when the open + * animation is complete. + */ +MdPanelAnimation.prototype.animateOpen = function(panelEl) { + var animator = this._$mdUtil.dom.animator; + + this._fixBounds(panelEl); + var animationOptions = {}; + + // Include the panel transformations when calculating the animations. + var panelTransform = panelEl[0].style.transform || ''; + + var openFrom = animator.toTransformCss(panelTransform); + var openTo = animator.toTransformCss(panelTransform); + + switch (this._animationClass) { + case MdPanelAnimation.animation.SLIDE: + // Slide should start with opacity: 1. + panelEl.css('opacity', '1'); + + animationOptions = { + transitionInClass: '_md-panel-animate-enter' + }; + + var openSlide = animator.calculateSlideToOrigin( + panelEl, this._openFrom) || ''; + openFrom = animator.toTransformCss(openSlide + ' ' + panelTransform); + break; + + case MdPanelAnimation.animation.SCALE: + animationOptions = { + transitionInClass: '_md-panel-animate-enter' + }; + + var openScale = animator.calculateZoomToOrigin( + panelEl, this._openFrom) || ''; + openFrom = animator.toTransformCss(openScale + ' ' + panelTransform); + break; + + case MdPanelAnimation.animation.FADE: + animationOptions = { + transitionInClass: '_md-panel-animate-enter' + }; + break; + + default: + if (angular.isString(this._animationClass)) { + animationOptions = { + transitionInClass: this._animationClass + }; + } else { + animationOptions = { + transitionInClass: this._animationClass['open'], + transitionOutClass: this._animationClass['close'], + }; + } + } + + animationOptions.duration = this._openDuration; + + return animator + .translate3d(panelEl, openFrom, openTo, animationOptions); +}; + + +/** + * Animate the panel close. + * @param {!angular.JQLite} panelEl + * @returns {!angular.$q.Promise} A promise that resolves when the close + * animation is complete. + */ +MdPanelAnimation.prototype.animateClose = function(panelEl) { + var animator = this._$mdUtil.dom.animator; + var reverseAnimationOptions = {}; + + // Include the panel transformations when calculating the animations. + var panelTransform = panelEl[0].style.transform || ''; + + var closeFrom = animator.toTransformCss(panelTransform); + var closeTo = animator.toTransformCss(panelTransform); + + switch (this._animationClass) { + case MdPanelAnimation.animation.SLIDE: + // Slide should start with opacity: 1. + panelEl.css('opacity', '1'); + reverseAnimationOptions = { + transitionInClass: '_md-panel-animate-leave' + }; + + var closeSlide = animator.calculateSlideToOrigin( + panelEl, this._closeTo) || ''; + closeTo = animator.toTransformCss(closeSlide + ' ' + panelTransform); + break; + + case MdPanelAnimation.animation.SCALE: + reverseAnimationOptions = { + transitionInClass: '_md-panel-animate-scale-out _md-panel-animate-leave' + }; + + var closeScale = animator.calculateZoomToOrigin( + panelEl, this._closeTo) || ''; + closeTo = animator.toTransformCss(closeScale + ' ' + panelTransform); + break; + + case MdPanelAnimation.animation.FADE: + reverseAnimationOptions = { + transitionInClass: '_md-panel-animate-fade-out _md-panel-animate-leave' + }; + break; + + default: + if (angular.isString(this._animationClass)) { + reverseAnimationOptions = { + transitionOutClass: this._animationClass + }; + } else { + reverseAnimationOptions = { + transitionInClass: this._animationClass['close'], + transitionOutClass: this._animationClass['open'] + }; + } + } + + reverseAnimationOptions.duration = this._closeDuration; + + return animator + .translate3d(panelEl, closeFrom, closeTo, reverseAnimationOptions); +}; + + +/** + * Set the height and width to match the panel if not provided. + * @param {!angular.JQLite} panelEl + * @private + */ +MdPanelAnimation.prototype._fixBounds = function(panelEl) { + var panelWidth = panelEl[0].offsetWidth; + var panelHeight = panelEl[0].offsetHeight; + + if (this._openFrom && this._openFrom.bounds.height == null) { + this._openFrom.bounds.height = panelHeight; + } + if (this._openFrom && this._openFrom.bounds.width == null) { + this._openFrom.bounds.width = panelWidth; + } + if (this._closeTo && this._closeTo.bounds.height == null) { + this._closeTo.bounds.height = panelHeight; + } + if (this._closeTo && this._closeTo.bounds.width == null) { + this._closeTo.bounds.width = panelWidth; + } +}; + + +/** + * Identify the bounding RECT for the target element. + * @param {!angular.JQLite} element + * @returns {{element: !angular.JQLite|undefined, bounds: !DOMRect}} + * @private + */ +MdPanelAnimation.prototype._getBoundingClientRect = function(element) { + if (element instanceof angular.element) { + return { + element: element, + bounds: element[0].getBoundingClientRect() + }; + } +}; + + +/***************************************************************************** + * Util Methods * + *****************************************************************************/ + + +/** + * Returns the angular element associated with a css selector or element. + * @param el {string|!angular.JQLite|!Element} + * @returns {!angular.JQLite} + */ +function getElement(el) { + var queryResult = angular.isString(el) ? + document.querySelector(el) : el; + return angular.element(queryResult); +} + +/** + * Gets the computed values for an element's translateX and translateY in px. + * @param {!angular.JQLite|!Element} el + * @param {string} property + * @return {{x: number, y: number}} + */ +function getComputedTranslations(el, property) { + // The transform being returned by `getComputedStyle` is in the format: + // `matrix(a, b, c, d, translateX, translateY)` if defined and `none` + // if the element doesn't have a transform. + var transform = getComputedStyle(el[0] || el)[property]; + var openIndex = transform.indexOf('('); + var closeIndex = transform.lastIndexOf(')'); + var output = { x: 0, y: 0 }; + + if (openIndex > -1 && closeIndex > -1) { + var parsedValues = transform + .substring(openIndex + 1, closeIndex) + .split(', ') + .slice(-2); + + output.x = parseInt(parsedValues[0]); + output.y = parseInt(parsedValues[1]); + } + + return output; +} + +/** + * Adds units to a number value. + * @param {string|number} value + * @return {string} + */ +function addUnits(value) { + return angular.isNumber(value) ? value + 'px' : value; +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.progressCircular + * @description Module for a circular progressbar + */ + +angular.module('material.components.progressCircular', ['material.core']); + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc directive + * @name mdProgressCircular + * @module material.components.progressCircular + * @restrict E + * + * @description + * The circular progress directive is used to make loading content in your app as delightful and + * painless as possible by minimizing the amount of visual change a user sees before they can view + * and interact with content. + * + * For operations where the percentage of the operation completed can be determined, use a + * determinate indicator. They give users a quick sense of how long an operation will take. + * + * For operations where the user is asked to wait a moment while something finishes up, and it’s + * not necessary to expose what's happening behind the scenes and how long it will take, use an + * indeterminate indicator. + * + * @param {string} md-mode Select from one of two modes: **'determinate'** and **'indeterminate'**. + * + * Note: if the `md-mode` value is set as undefined or specified as not 1 of the two (2) valid modes, then **'indeterminate'** + * will be auto-applied as the mode. + * + * Note: if not configured, the `md-mode="indeterminate"` will be auto injected as an attribute. + * If `value=""` is also specified, however, then `md-mode="determinate"` would be auto-injected instead. + * @param {number=} value In determinate mode, this number represents the percentage of the + * circular progress. Default: 0 + * @param {number=} md-diameter This specifies the diameter of the circular progress. The value + * should be a pixel-size value (eg '100'). If this attribute is + * not present then a default value of '50px' is assumed. + * + * @param {boolean=} ng-disabled Determines whether to disable the progress element. + * + * @usage + * + * + * + * + * + * + * + * + * + */ + +MdProgressCircularDirective.$inject = ["$window", "$mdProgressCircular", "$mdTheming", "$mdUtil", "$interval", "$log"]; +angular + .module('material.components.progressCircular') + .directive('mdProgressCircular', MdProgressCircularDirective); + +/* @ngInject */ +function MdProgressCircularDirective($window, $mdProgressCircular, $mdTheming, + $mdUtil, $interval, $log) { + + // Note that this shouldn't use use $$rAF, because it can cause an infinite loop + // in any tests that call $animate.flush. + var rAF = $window.requestAnimationFrame || + $window.webkitRequestAnimationFrame || + angular.noop; + + var cAF = $window.cancelAnimationFrame || + $window.webkitCancelAnimationFrame || + $window.webkitCancelRequestAnimationFrame || + angular.noop; + + var MODE_DETERMINATE = 'determinate'; + var MODE_INDETERMINATE = 'indeterminate'; + var DISABLED_CLASS = '_md-progress-circular-disabled'; + var INDETERMINATE_CLASS = 'md-mode-indeterminate'; + + return { + restrict: 'E', + scope: { + value: '@', + mdDiameter: '@', + mdMode: '@' + }, + template: + '' + + '' + + '', + compile: function(element, attrs) { + element.attr({ + 'aria-valuemin': 0, + 'aria-valuemax': 100, + 'role': 'progressbar' + }); + + if (angular.isUndefined(attrs.mdMode)) { + var mode = attrs.hasOwnProperty('value') ? MODE_DETERMINATE : MODE_INDETERMINATE; + attrs.$set('mdMode', mode); + } else { + attrs.$set('mdMode', attrs.mdMode.trim()); + } + + return MdProgressCircularLink; + } + }; + + function MdProgressCircularLink(scope, element, attrs) { + var node = element[0]; + var svg = angular.element(node.querySelector('svg')); + var path = angular.element(node.querySelector('path')); + var startIndeterminate = $mdProgressCircular.startIndeterminate; + var endIndeterminate = $mdProgressCircular.endIndeterminate; + var iterationCount = 0; + var lastAnimationId = 0; + var lastDrawFrame; + var interval; + + $mdTheming(element); + element.toggleClass(DISABLED_CLASS, attrs.hasOwnProperty('disabled')); + + // If the mode is indeterminate, it doesn't need to + // wait for the next digest. It can start right away. + if (scope.mdMode === MODE_INDETERMINATE){ + startIndeterminateAnimation(); + } + + scope.$on('$destroy', function(){ + cleanupIndeterminateAnimation(); + + if (lastDrawFrame) { + cAF(lastDrawFrame); + } + }); + + scope.$watchGroup(['value', 'mdMode', function() { + var isDisabled = node.disabled; + + // Sometimes the browser doesn't return a boolean, in + // which case we should check whether the attribute is + // present. + if (isDisabled === true || isDisabled === false){ + return isDisabled; + } + + return angular.isDefined(element.attr('disabled')); + }], function(newValues, oldValues) { + var mode = newValues[1]; + var isDisabled = newValues[2]; + var wasDisabled = oldValues[2]; + var diameter = 0; + var strokeWidth = 0; + + if (isDisabled !== wasDisabled) { + element.toggleClass(DISABLED_CLASS, !!isDisabled); + } + + if (isDisabled) { + cleanupIndeterminateAnimation(); + } else { + if (mode !== MODE_DETERMINATE && mode !== MODE_INDETERMINATE) { + mode = MODE_INDETERMINATE; + attrs.$set('mdMode', mode); + } + + if (mode === MODE_INDETERMINATE) { + if (oldValues[1] === MODE_DETERMINATE) { + diameter = getSize(scope.mdDiameter); + strokeWidth = getStroke(diameter); + path.attr('d', getSvgArc(diameter, strokeWidth, true)); + path.attr('stroke-dasharray', (diameter - strokeWidth) * $window.Math.PI * 0.75); + } + startIndeterminateAnimation(); + } else { + var newValue = clamp(newValues[0]); + var oldValue = clamp(oldValues[0]); + + cleanupIndeterminateAnimation(); + + if (oldValues[1] === MODE_INDETERMINATE) { + diameter = getSize(scope.mdDiameter); + strokeWidth = getStroke(diameter); + path.attr('d', getSvgArc(diameter, strokeWidth, false)); + path.attr('stroke-dasharray', (diameter - strokeWidth) * $window.Math.PI); + } + + element.attr('aria-valuenow', newValue); + renderCircle(oldValue, newValue); + } + } + + }); + + // This is in a separate watch in order to avoid layout, unless + // the value has actually changed. + scope.$watch('mdDiameter', function(newValue) { + var diameter = getSize(newValue); + var strokeWidth = getStroke(diameter); + var value = clamp(scope.value); + var transformOrigin = (diameter / 2) + 'px'; + var dimensions = { + width: diameter + 'px', + height: diameter + 'px' + }; + + // The viewBox has to be applied via setAttribute, because it is + // case-sensitive. If jQuery is included in the page, `.attr` lowercases + // all attribute names. + svg[0].setAttribute('viewBox', '0 0 ' + diameter + ' ' + diameter); + + // Usually viewBox sets the dimensions for the SVG, however that doesn't + // seem to be the case on IE10. + // Important! The transform origin has to be set from here and it has to + // be in the format of "Ypx Ypx Ypx", otherwise the rotation wobbles in + // IE and Edge, because they don't account for the stroke width when + // rotating. Also "center" doesn't help in this case, it has to be a + // precise value. + svg + .css(dimensions) + .css('transform-origin', transformOrigin + ' ' + transformOrigin + ' ' + transformOrigin); + + element.css(dimensions); + + path.attr('stroke-width', strokeWidth); + path.attr('stroke-linecap', 'square'); + if (scope.mdMode == MODE_INDETERMINATE) { + path.attr('d', getSvgArc(diameter, strokeWidth, true)); + path.attr('stroke-dasharray', (diameter - strokeWidth) * $window.Math.PI * 0.75); + path.attr('stroke-dashoffset', getDashLength(diameter, strokeWidth, 1, 75)); + } else { + path.attr('d', getSvgArc(diameter, strokeWidth, false)); + path.attr('stroke-dasharray', (diameter - strokeWidth) * $window.Math.PI); + path.attr('stroke-dashoffset', getDashLength(diameter, strokeWidth, 0, 100)); + renderCircle(value, value); + } + + }); + + function renderCircle(animateFrom, animateTo, easing, duration, iterationCount, maxValue) { + var id = ++lastAnimationId; + var startTime = $mdUtil.now(); + var changeInValue = animateTo - animateFrom; + var diameter = getSize(scope.mdDiameter); + var strokeWidth = getStroke(diameter); + var ease = easing || $mdProgressCircular.easeFn; + var animationDuration = duration || $mdProgressCircular.duration; + var rotation = -90 * (iterationCount || 0); + var dashLimit = maxValue || 100; + + // No need to animate it if the values are the same + if (animateTo === animateFrom) { + renderFrame(animateTo); + } else { + lastDrawFrame = rAF(function animation() { + var currentTime = $window.Math.max(0, $window.Math.min($mdUtil.now() - startTime, animationDuration)); + + renderFrame(ease(currentTime, animateFrom, changeInValue, animationDuration)); + + // Do not allow overlapping animations + if (id === lastAnimationId && currentTime < animationDuration) { + lastDrawFrame = rAF(animation); + } + }); + } + + function renderFrame(value) { + path.attr('stroke-dashoffset', getDashLength(diameter, strokeWidth, value, dashLimit)); + path.attr('transform','rotate(' + (rotation) + ' ' + diameter/2 + ' ' + diameter/2 + ')'); + } + } + + function animateIndeterminate() { + renderCircle( + startIndeterminate, + endIndeterminate, + $mdProgressCircular.easeFnIndeterminate, + $mdProgressCircular.durationIndeterminate, + iterationCount, + 75 + ); + + // The %4 technically isn't necessary, but it keeps the rotation + // under 360, instead of becoming a crazy large number. + iterationCount = ++iterationCount % 4; + + } + + function startIndeterminateAnimation() { + if (!interval) { + // Note that this interval isn't supposed to trigger a digest. + interval = $interval( + animateIndeterminate, + $mdProgressCircular.durationIndeterminate, + 0, + false + ); + + animateIndeterminate(); + + element + .addClass(INDETERMINATE_CLASS) + .removeAttr('aria-valuenow'); + } + } + + function cleanupIndeterminateAnimation() { + if (interval) { + $interval.cancel(interval); + interval = null; + element.removeClass(INDETERMINATE_CLASS); + } + } + } + + /** + * Returns SVG path data for progress circle + * Syntax spec: https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands + * + * @param {number} diameter Diameter of the container. + * @param {number} strokeWidth Stroke width to be used when drawing circle + * @param {boolean} indeterminate Use if progress circle will be used for indeterminate + * + * @returns {string} String representation of an SVG arc. + */ + function getSvgArc(diameter, strokeWidth, indeterminate) { + var radius = diameter / 2; + var offset = strokeWidth / 2; + var start = radius + ',' + offset; // ie: (25, 2.5) or 12 o'clock + var end = offset + ',' + radius; // ie: (2.5, 25) or 9 o'clock + var arcRadius = radius - offset; + return 'M' + start + + 'A' + arcRadius + ',' + arcRadius + ' 0 1 1 ' + end // 75% circle + + (indeterminate ? '' : 'A' + arcRadius + ',' + arcRadius + ' 0 0 1 ' + start); // loop to start + } + + /** + * Return stroke length for progress circle + * + * @param {number} diameter Diameter of the container. + * @param {number} strokeWidth Stroke width to be used when drawing circle + * @param {number} value Percentage of circle (between 0 and 100) + * @param {number} limit Max percentage for circle + * + * @returns {number} Stroke length for progres circle + */ + function getDashLength(diameter, strokeWidth, value, limit) { + return (diameter - strokeWidth) * $window.Math.PI * ((3 * (limit || 100) / 100) - (value/100)); + } + + /** + * Limits a value between 0 and 100. + */ + function clamp(value) { + return $window.Math.max(0, $window.Math.min(value || 0, 100)); + } + + /** + * Determines the size of a progress circle, based on the provided + * value in the following formats: `X`, `Ypx`, `Z%`. + */ + function getSize(value) { + var defaultValue = $mdProgressCircular.progressSize; + + if (value) { + var parsed = parseFloat(value); + + if (value.lastIndexOf('%') === value.length - 1) { + parsed = (parsed / 100) * defaultValue; + } + + return parsed; + } + + return defaultValue; + } + + /** + * Determines the circle's stroke width, based on + * the provided diameter. + */ + function getStroke(diameter) { + return $mdProgressCircular.strokeWidth / 100 * diameter; + } + +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc service + * @name $mdProgressCircular + * @module material.components.progressCircular + * + * @description + * Allows the user to specify the default options for the `progressCircular` directive. + * + * @property {number} progressSize Diameter of the progress circle in pixels. + * @property {number} strokeWidth Width of the circle's stroke as a percentage of the circle's size. + * @property {number} duration Length of the circle animation in milliseconds. + * @property {function} easeFn Default easing animation function. + * @property {object} easingPresets Collection of pre-defined easing functions. + * + * @property {number} durationIndeterminate Duration of the indeterminate animation. + * @property {number} startIndeterminate Indeterminate animation start point. + * @property {number} endIndeterminate Indeterminate animation end point. + * @property {function} easeFnIndeterminate Easing function to be used when animating + * between the indeterminate values. + * + * @property {(function(object): object)} configure Used to modify the default options. + * + * @usage + * + * myAppModule.config(function($mdProgressCircularProvider) { + * + * // Example of changing the default progress options. + * $mdProgressCircularProvider.configure({ + * progressSize: 100, + * strokeWidth: 20, + * duration: 800 + * }); + * }); + * + * + */ + +angular + .module('material.components.progressCircular') + .provider("$mdProgressCircular", MdProgressCircularProvider); + +function MdProgressCircularProvider() { + var progressConfig = { + progressSize: 50, + strokeWidth: 10, + duration: 100, + easeFn: linearEase, + + durationIndeterminate: 1333, + startIndeterminate: 1, + endIndeterminate: 149, + easeFnIndeterminate: materialEase, + + easingPresets: { + linearEase: linearEase, + materialEase: materialEase + } + }; + + return { + configure: function(options) { + progressConfig = angular.extend(progressConfig, options || {}); + return progressConfig; + }, + $get: function() { return progressConfig; } + }; + + function linearEase(t, b, c, d) { + return c * t / d + b; + } + + function materialEase(t, b, c, d) { + // via http://www.timotheegroleau.com/Flash/experiments/easing_function_generator.htm + // with settings of [0, 0, 1, 1] + var ts = (t /= d) * t; + var tc = ts * t; + return b + c * (6 * tc * ts + -15 * ts * ts + 10 * tc); + } +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.progressLinear + * @description Linear Progress module! + */ +MdProgressLinearDirective.$inject = ["$mdTheming", "$mdUtil", "$log"]; +angular.module('material.components.progressLinear', [ + 'material.core' +]) + .directive('mdProgressLinear', MdProgressLinearDirective); + +/** + * @ngdoc directive + * @name mdProgressLinear + * @module material.components.progressLinear + * @restrict E + * + * @description + * The linear progress directive is used to make loading content + * in your app as delightful and painless as possible by minimizing + * the amount of visual change a user sees before they can view + * and interact with content. + * + * Each operation should only be represented by one activity indicator + * For example: one refresh operation should not display both a + * refresh bar and an activity circle. + * + * For operations where the percentage of the operation completed + * can be determined, use a determinate indicator. They give users + * a quick sense of how long an operation will take. + * + * For operations where the user is asked to wait a moment while + * something finishes up, and it’s not necessary to expose what's + * happening behind the scenes and how long it will take, use an + * indeterminate indicator. + * + * @param {string} md-mode Select from one of four modes: determinate, indeterminate, buffer or query. + * + * Note: if the `md-mode` value is set as undefined or specified as 1 of the four (4) valid modes, then `indeterminate` + * will be auto-applied as the mode. + * + * Note: if not configured, the `md-mode="indeterminate"` will be auto injected as an attribute. If `value=""` is also specified, however, + * then `md-mode="determinate"` would be auto-injected instead. + * @param {number=} value In determinate and buffer modes, this number represents the percentage of the primary progress bar. Default: 0 + * @param {number=} md-buffer-value In the buffer mode, this number represents the percentage of the secondary progress bar. Default: 0 + * @param {boolean=} ng-disabled Determines whether to disable the progress element. + * + * @usage + * + * + * + * + * + * + * + * + * + * + * + */ +function MdProgressLinearDirective($mdTheming, $mdUtil, $log) { + var MODE_DETERMINATE = "determinate"; + var MODE_INDETERMINATE = "indeterminate"; + var MODE_BUFFER = "buffer"; + var MODE_QUERY = "query"; + var DISABLED_CLASS = "_md-progress-linear-disabled"; + + return { + restrict: 'E', + template: '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ', + compile: compile + }; + + function compile(tElement, tAttrs, transclude) { + tElement.attr('aria-valuemin', 0); + tElement.attr('aria-valuemax', 100); + tElement.attr('role', 'progressbar'); + + return postLink; + } + function postLink(scope, element, attr) { + $mdTheming(element); + + var lastMode; + var isDisabled = attr.hasOwnProperty('disabled'); + var toVendorCSS = $mdUtil.dom.animator.toCss; + var bar1 = angular.element(element[0].querySelector('.md-bar1')); + var bar2 = angular.element(element[0].querySelector('.md-bar2')); + var container = angular.element(element[0].querySelector('.md-container')); + + element + .attr('md-mode', mode()) + .toggleClass(DISABLED_CLASS, isDisabled); + + validateMode(); + watchAttributes(); + + /** + * Watch the value, md-buffer-value, and md-mode attributes + */ + function watchAttributes() { + attr.$observe('value', function(value) { + var percentValue = clamp(value); + element.attr('aria-valuenow', percentValue); + + if (mode() != MODE_QUERY) animateIndicator(bar2, percentValue); + }); + + attr.$observe('mdBufferValue', function(value) { + animateIndicator(bar1, clamp(value)); + }); + + attr.$observe('disabled', function(value) { + if (value === true || value === false) { + isDisabled = !!value; + } else { + isDisabled = angular.isDefined(value); + } + + element.toggleClass(DISABLED_CLASS, isDisabled); + container.toggleClass(lastMode, !isDisabled); + }); + + attr.$observe('mdMode', function(mode) { + if (lastMode) container.removeClass(lastMode); + + switch (mode) { + case MODE_QUERY: + case MODE_BUFFER: + case MODE_DETERMINATE: + case MODE_INDETERMINATE: + container.addClass(lastMode = "md-mode-" + mode); + break; + default: + container.addClass(lastMode = "md-mode-" + MODE_INDETERMINATE); + break; + } + }); + } + + /** + * Auto-defaults the mode to either `determinate` or `indeterminate` mode; if not specified + */ + function validateMode() { + if (angular.isUndefined(attr.mdMode)) { + var hasValue = angular.isDefined(attr.value); + var mode = hasValue ? MODE_DETERMINATE : MODE_INDETERMINATE; + var info = "Auto-adding the missing md-mode='{0}' to the ProgressLinear element"; + element.attr("md-mode", mode); + attr.mdMode = mode; + } + } + + /** + * Is the md-mode a valid option? + */ + function mode() { + var value = (attr.mdMode || "").trim(); + if (value) { + switch (value) { + case MODE_DETERMINATE: + case MODE_INDETERMINATE: + case MODE_BUFFER: + case MODE_QUERY: + break; + default: + value = MODE_INDETERMINATE; + break; + } + } + return value; + } + + /** + * Manually set CSS to animate the Determinate indicator based on the specified + * percentage value (0-100). + */ + function animateIndicator(target, value) { + if (isDisabled || !mode()) return; + + var to = $mdUtil.supplant("translateX({0}%) scale({1},1)", [(value-100)/2, value/100]); + var styles = toVendorCSS({ transform : to }); + angular.element(target).css(styles); + } + } + + /** + * Clamps the value to be between 0 and 100. + * @param {number} value The value to clamp. + * @returns {number} + */ + function clamp(value) { + return Math.max(0, Math.min(value || 0, 100)); + } +} + + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.radioButton + * @description radioButton module! + */ +mdRadioGroupDirective.$inject = ["$mdUtil", "$mdConstant", "$mdTheming", "$timeout"]; +mdRadioButtonDirective.$inject = ["$mdAria", "$mdUtil", "$mdTheming"]; +angular.module('material.components.radioButton', [ + 'material.core' +]) + .directive('mdRadioGroup', mdRadioGroupDirective) + .directive('mdRadioButton', mdRadioButtonDirective); + +/** + * @ngdoc directive + * @module material.components.radioButton + * @name mdRadioGroup + * + * @restrict E + * + * @description + * The `` directive identifies a grouping + * container for the 1..n grouped radio buttons; specified using nested + * `` elements. + * + * The radio button uses the accent color by default. The primary color palette may be used with + * the `md-primary` class. + * + * Note: `` and `` handle `tabindex` differently + * than the native `` controls. Whereas the native controls + * force the user to tab through all the radio buttons, `` + * is focusable and by default the ``s are not. + * + * @param {string} ng-model Assignable angular expression to data-bind to. + * @param {string=} ng-change AngularJS expression to be executed when input changes due to user + * interaction. + * @param {boolean=} md-no-ink If present, disables ink ripple effects. + * + * @usage + * + * + * + * {{ item.label }} + * + * + * + */ +function mdRadioGroupDirective($mdUtil, $mdConstant, $mdTheming, $timeout) { + RadioGroupController.prototype = createRadioGroupControllerProto(); + + return { + restrict: 'E', + controller: ['$element', RadioGroupController], + require: ['mdRadioGroup', '?ngModel'], + link: { pre: linkRadioGroup } + }; + + function linkRadioGroup(scope, element, attr, ctrls) { + element.addClass('_md'); // private md component indicator for styling + $mdTheming(element); + + var rgCtrl = ctrls[0]; + var ngModelCtrl = ctrls[1] || $mdUtil.fakeNgModel(); + + rgCtrl.init(ngModelCtrl); + + scope.mouseActive = false; + + element + .attr({ + 'role': 'radiogroup', + 'tabIndex': element.attr('tabindex') || '0' + }) + .on('keydown', keydownListener) + .on('mousedown', function(event) { + scope.mouseActive = true; + $timeout(function() { + scope.mouseActive = false; + }, 100); + }) + .on('focus', function() { + if (scope.mouseActive === false) { + rgCtrl.$element.addClass('md-focused'); + } + }) + .on('blur', function() { + rgCtrl.$element.removeClass('md-focused'); + }); + + /** + * + */ + function setFocus() { + if (!element.hasClass('md-focused')) { element.addClass('md-focused'); } + } + + /** + * + */ + function keydownListener(ev) { + var keyCode = ev.which || ev.keyCode; + + // Only listen to events that we originated ourselves + // so that we don't trigger on things like arrow keys in + // inputs. + + if (keyCode != $mdConstant.KEY_CODE.ENTER && + ev.currentTarget != ev.target) { + return; + } + + switch (keyCode) { + case $mdConstant.KEY_CODE.LEFT_ARROW: + case $mdConstant.KEY_CODE.UP_ARROW: + ev.preventDefault(); + rgCtrl.selectPrevious(); + setFocus(); + break; + + case $mdConstant.KEY_CODE.RIGHT_ARROW: + case $mdConstant.KEY_CODE.DOWN_ARROW: + ev.preventDefault(); + rgCtrl.selectNext(); + setFocus(); + break; + + case $mdConstant.KEY_CODE.ENTER: + var form = angular.element($mdUtil.getClosest(element[0], 'form')); + if (form.length > 0) { + form.triggerHandler('submit'); + } + break; + } + + } + } + + function RadioGroupController($element) { + this._radioButtonRenderFns = []; + this.$element = $element; + } + + function createRadioGroupControllerProto() { + return { + init: function(ngModelCtrl) { + this._ngModelCtrl = ngModelCtrl; + this._ngModelCtrl.$render = angular.bind(this, this.render); + }, + add: function(rbRender) { + this._radioButtonRenderFns.push(rbRender); + }, + remove: function(rbRender) { + var index = this._radioButtonRenderFns.indexOf(rbRender); + if (index !== -1) { + this._radioButtonRenderFns.splice(index, 1); + } + }, + render: function() { + this._radioButtonRenderFns.forEach(function(rbRender) { + rbRender(); + }); + }, + setViewValue: function(value, eventType) { + this._ngModelCtrl.$setViewValue(value, eventType); + // update the other radio buttons as well + this.render(); + }, + getViewValue: function() { + return this._ngModelCtrl.$viewValue; + }, + selectNext: function() { + return changeSelectedButton(this.$element, 1); + }, + selectPrevious: function() { + return changeSelectedButton(this.$element, -1); + }, + setActiveDescendant: function (radioId) { + this.$element.attr('aria-activedescendant', radioId); + }, + isDisabled: function() { + return this.$element[0].hasAttribute('disabled'); + } + }; + } + /** + * Change the radio group's selected button by a given increment. + * If no button is selected, select the first button. + */ + function changeSelectedButton(parent, increment) { + // Coerce all child radio buttons into an array, then wrap then in an iterator + var buttons = $mdUtil.iterator(parent[0].querySelectorAll('md-radio-button'), true); + + if (buttons.count()) { + var validate = function (button) { + // If disabled, then NOT valid + return !angular.element(button).attr("disabled"); + }; + + var selected = parent[0].querySelector('md-radio-button.md-checked'); + var target = buttons[increment < 0 ? 'previous' : 'next'](selected, validate) || buttons.first(); + + // Activate radioButton's click listener (triggerHandler won't create a real click event) + angular.element(target).triggerHandler('click'); + } + } + +} + +/** + * @ngdoc directive + * @module material.components.radioButton + * @name mdRadioButton + * + * @restrict E + * + * @description + * The ``directive is the child directive required to be used within `` elements. + * + * While similar to the `` directive, + * the `` directive provides ink effects, ARIA support, and + * supports use within named radio groups. + * + * One of `value` or `ng-value` must be set so that the `md-radio-group`'s model is set properly when the + * `md-radio-button` is selected. + * + * @param {string} value The value to which the model should be set when selected. + * @param {string} ng-value AngularJS expression which sets the value to which the model should + * be set when selected. + * @param {string=} name Property name of the form under which the control is published. + * @param {string=} aria-label Adds label to radio button for accessibility. + * Defaults to radio button's text. If no text content is available, a warning will be logged. + * + * @usage + * + * + * + * Label 1 + * + * + * + * Green + * + * + * + * + */ +function mdRadioButtonDirective($mdAria, $mdUtil, $mdTheming) { + + var CHECKED_CSS = 'md-checked'; + + return { + restrict: 'E', + require: '^mdRadioGroup', + transclude: true, + template: '
    ' + + '
    ' + + '
    ' + + '
    ' + + '
    ', + link: link + }; + + function link(scope, element, attr, rgCtrl) { + var lastChecked; + + $mdTheming(element); + configureAria(element, scope); + + // ngAria overwrites the aria-checked inside a $watch for ngValue. + // We should defer the initialization until all the watches have fired. + // This can also be fixed by removing the `lastChecked` check, but that'll + // cause more DOM manipulation on each digest. + if (attr.ngValue) { + $mdUtil.nextTick(initialize, false); + } else { + initialize(); + } + + /** + * Initializes the component. + */ + function initialize() { + if (!rgCtrl) { + throw 'RadioButton: No RadioGroupController could be found.'; + } + + rgCtrl.add(render); + attr.$observe('value', render); + + element + .on('click', listener) + .on('$destroy', function() { + rgCtrl.remove(render); + }); + } + + /** + * On click functionality. + */ + function listener(ev) { + if (element[0].hasAttribute('disabled') || rgCtrl.isDisabled()) return; + + scope.$apply(function() { + rgCtrl.setViewValue(attr.value, ev && ev.type); + }); + } + + /** + * Add or remove the `.md-checked` class from the RadioButton (and conditionally its parent). + * Update the `aria-activedescendant` attribute. + */ + function render() { + var checked = rgCtrl.getViewValue() == attr.value; + + if (checked === lastChecked) return; + + if (element[0].parentNode.nodeName.toLowerCase() !== 'md-radio-group') { + // If the radioButton is inside a div, then add class so highlighting will work + element.parent().toggleClass(CHECKED_CSS, checked); + } + + if (checked) { + rgCtrl.setActiveDescendant(element.attr('id')); + } + + lastChecked = checked; + + element + .attr('aria-checked', checked) + .toggleClass(CHECKED_CSS, checked); + } + + /** + * Inject ARIA-specific attributes appropriate for each radio button + */ + function configureAria(element, scope){ + element.attr({ + id: attr.id || 'radio_' + $mdUtil.nextUid(), + role: 'radio', + 'aria-checked': 'false' + }); + + $mdAria.expectWithText(element, 'aria-label'); + } + } +} + +})(); +(function(){ +"use strict"; + +/** + * @ngdoc module + * @name material.components.select + */ + +/*************************************************** + + ### TODO ### + - [ ] Abstract placement logic in $mdSelect service to $mdMenu service + + ***************************************************/ + +SelectDirective.$inject = ["$mdSelect", "$mdUtil", "$mdConstant", "$mdTheming", "$mdAria", "$parse", "$sce", "$injector"]; +SelectMenuDirective.$inject = ["$parse", "$mdUtil", "$mdConstant", "$mdTheming"]; +OptionDirective.$inject = ["$mdButtonInkRipple", "$mdUtil", "$mdTheming"]; +SelectProvider.$inject = ["$$interimElementProvider"]; +var SELECT_EDGE_MARGIN = 8; +var selectNextId = 0; +var CHECKBOX_SELECTION_INDICATOR = + angular.element('
    '); + +angular.module('material.components.select', [ + 'material.core', + 'material.components.backdrop' + ]) + .directive('mdSelect', SelectDirective) + .directive('mdSelectMenu', SelectMenuDirective) + .directive('mdOption', OptionDirective) + .directive('mdOptgroup', OptgroupDirective) + .directive('mdSelectHeader', SelectHeaderDirective) + .provider('$mdSelect', SelectProvider); + +/** + * @ngdoc directive + * @name mdSelect + * @restrict E + * @module material.components.select + * + * @description Displays a select box, bound to an `ng-model`. Selectable options are defined using + * the md-option element directive. Options can be grouped + * using the md-optgroup element directive. + * + * When the select is required and uses a floating label, then the label will automatically contain + * an asterisk (`*`). This behavior can be disabled by using the `md-no-asterisk` attribute. + * + * By default, the select will display with an underline to match other form elements. This can be + * disabled by applying the `md-no-underline` CSS class. + * + * @param {expression} ng-model Assignable angular expression to data-bind to. + * @param {expression=} ng-change Expression to be executed when the model value changes. + * @param {boolean=} multiple When present, allows for more than one option to be selected. + * The model is an array with the selected choices. **Note:** This attribute is only evaluated + * once; it is not watched. + * @param {expression=} md-on-close Expression to be evaluated when the select is closed. + * @param {expression=} md-on-open Expression to be evaluated when opening the select. + * Will hide the select options and show a spinner until the evaluated promise resolves. + * @param {expression=} md-selected-text Expression to be evaluated that will return a string + * to be displayed as a placeholder in the select input box when it is closed. The value + * will be treated as *text* (not html). + * @param {expression=} md-selected-html Expression to be evaluated that will return a string + * to be displayed as a placeholder in the select input box when it is closed. The value + * will be treated as *html*. The value must either be explicitly marked as trustedHtml or + * the ngSanitize module must be loaded. + * @param {string=} placeholder Placeholder hint text. + * @param {boolean=} md-no-asterisk When set to true, an asterisk will not be appended to the + * floating label. **Note:** This attribute is only evaluated once; it is not watched. + * @param {string=} aria-label Optional label for accessibility. Only necessary if no placeholder or + * explicit label is present. + * @param {string=} md-container-class Class list to get applied to the `.md-select-menu-container` + * element (for custom styling). + * + * @usage + * With a placeholder (label and aria-label are added dynamically) + * + * + * + * {{ opt }} + * + * + * + * + * With an explicit label + * + * + * + * + * {{ opt }} + * + * + * + * + * Using the `md-select-header` element directive + * + * When a developer needs to put more than just a text label in the `md-select-menu`, they should + * use one or more `md-select-header`s. These elements can contain custom HTML which can be styled + * as desired. Use cases for this element include a sticky search bar and custom option group + * labels. + * + * + * + * + * + * Neighborhoods - + * + * {{ opt }} + * + * + * + * + * ## Selects and object equality + * When using a `md-select` to pick from a list of objects, it is important to realize how javascript handles + * equality. Consider the following example: + * + * angular.controller('MyCtrl', function($scope) { + * $scope.users = [ + * { id: 1, name: 'Bob' }, + * { id: 2, name: 'Alice' }, + * { id: 3, name: 'Steve' } + * ]; + * $scope.selectedUser = { id: 1, name: 'Bob' }; + * }); + * + * + *
    + * + * {{ user.name }} + * + *
    + *
    + * + * At first one might expect that the select should be populated with "Bob" as the selected user. + * However, this is not true. To determine whether something is selected, + * `ngModelController` is looking at whether `$scope.selectedUser == (any user in $scope.users);`; + * + * Javascript's `==` operator does not check for deep equality (ie. that all properties + * on the object are the same), but instead whether the objects are *the same object in memory*. + * In this case, we have two instances of identical objects, but they exist in memory as unique + * entities. Because of this, the select will have no value populated for a selected user. + * + * To get around this, `ngModelController` provides a `track by` option that allows us to specify a + * different expression which will be used for the equality operator. As such, we can update our + * `html` to make use of this by specifying the `ng-model-options="{trackBy: '$value.id'}"` on the + * `md-select` element. This converts our equality expression to be + * `$scope.selectedUser.id == (any id in $scope.users.map(function(u) { return u.id; }));` + * which results in Bob being selected as desired. + * + * **Note:** We do not support AngularJS's `track by` syntax. For instance + * `ng-options="user in users track by user.id"` will not work with `md-select`. + * + * Working HTML: + * + *
    + * + * {{ user.name }} + * + *
    + *
    + */ +function SelectDirective($mdSelect, $mdUtil, $mdConstant, $mdTheming, $mdAria, $parse, $sce, + $injector) { + var keyCodes = $mdConstant.KEY_CODE; + var NAVIGATION_KEYS = [keyCodes.SPACE, keyCodes.ENTER, keyCodes.UP_ARROW, keyCodes.DOWN_ARROW]; + + return { + restrict: 'E', + require: ['^?mdInputContainer', 'mdSelect', 'ngModel', '?^form'], + compile: compile, + controller: function() { + } // empty placeholder controller to be initialized in link + }; + + function compile(element, attr) { + // add the select value that will hold our placeholder or selected option value + var valueEl = angular.element(''); + valueEl.append(''); + valueEl.addClass('md-select-value'); + if (!valueEl[0].hasAttribute('id')) { + valueEl.attr('id', 'select_value_label_' + $mdUtil.nextUid()); + } + + // There's got to be an md-content inside. If there's not one, let's add it. + var mdContentEl = element.find('md-content'); + if (!mdContentEl.length) { + element.append(angular.element('').append(element.contents())); + } + mdContentEl.attr('role', 'presentation'); + + + // Add progress spinner for md-options-loading + if (attr.mdOnOpen) { + + // Show progress indicator while loading async + // Use ng-hide for `display:none` so the indicator does not interfere with the options list + element + .find('md-content') + .prepend(angular.element( + '
    ' + + ' ' + + '
    ' + )); + + // Hide list [of item options] while loading async + element + .find('md-option') + .attr('ng-show', '$$loadingAsyncDone'); + } + + if (attr.name) { + var autofillClone = angular.element(''); + autofillClone.attr({ + 'name': attr.name, + 'aria-hidden': 'true', + 'tabindex': '-1' + }); + var opts = element.find('md-option'); + angular.forEach(opts, function(el) { + var newEl = angular.element(''); + if (el.hasAttribute('ng-value')) newEl.attr('ng-value', el.getAttribute('ng-value')); + else if (el.hasAttribute('value')) newEl.attr('value', el.getAttribute('value')); + autofillClone.append(newEl); + }); + + // Adds an extra option that will hold the selected value for the + // cases where the select is a part of a non-angular form. This can be done with a ng-model, + // however if the `md-option` is being `ng-repeat`-ed, AngularJS seems to insert a similar + // `option` node, but with a value of `? string: ?` which would then get submitted. + // This also goes around having to prepend a dot to the name attribute. + autofillClone.append( + '' + ); + + element.parent().append(autofillClone); + } + + var isMultiple = $mdUtil.parseAttributeBoolean(attr.multiple); + + // Use everything that's left inside element.contents() as the contents of the menu + var multipleContent = isMultiple ? 'multiple' : ''; + var selectTemplate = '' + + ''; + + selectTemplate = $mdUtil.supplant(selectTemplate, [multipleContent, element.html()]); + element.empty().append(valueEl); + element.append(selectTemplate); + + if (!attr.tabindex){ + attr.$set('tabindex', 0); + } + + return function postLink(scope, element, attr, ctrls) { + var untouched = true; + var isDisabled, ariaLabelBase; + + var containerCtrl = ctrls[0]; + var mdSelectCtrl = ctrls[1]; + var ngModelCtrl = ctrls[2]; + var formCtrl = ctrls[3]; + // grab a reference to the select menu value label + var valueEl = element.find('md-select-value'); + var isReadonly = angular.isDefined(attr.readonly); + var disableAsterisk = $mdUtil.parseAttributeBoolean(attr.mdNoAsterisk); + + if (disableAsterisk) { + element.addClass('md-no-asterisk'); + } + + if (containerCtrl) { + var isErrorGetter = containerCtrl.isErrorGetter || function() { + return ngModelCtrl.$invalid && (ngModelCtrl.$touched || (formCtrl && formCtrl.$submitted)); + }; + + if (containerCtrl.input) { + // We ignore inputs that are in the md-select-header (one + // case where this might be useful would be adding as searchbox) + if (element.find('md-select-header').find('input')[0] !== containerCtrl.input[0]) { + throw new Error(" can only have *one* child ,
    -
    -
    - - - it('should auto compile', function() { - var textarea = $('textarea'); - var output = $('div[compile]'); - // The initial state reads 'Hello AngularJS'. - expect(output.getText()).toBe('Hello AngularJS'); - textarea.clear(); - textarea.sendKeys('{{name}}!'); - expect(output.getText()).toBe('AngularJS!'); - }); - - - - * - * - * @param {string|DOMElement} element Element or HTML string to compile into a template function. - * @param {function(angular.Scope, cloneAttachFn=)} transclude function available to directives - DEPRECATED. - * - *
    - * **Note:** Passing a `transclude` function to the $compile function is deprecated, as it - * e.g. will not use the right outer scope. Please pass the transclude function as a - * `parentBoundTranscludeFn` to the link function instead. - *
    - * - * @param {number} maxPriority only apply directives lower than given priority (Only effects the - * root element(s), not their children) - * @returns {function(scope, cloneAttachFn=, options=)} a link function which is used to bind template - * (a DOM element/tree) to a scope. Where: - * - * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to. - * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the - * `template` and call the `cloneAttachFn` function allowing the caller to attach the - * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is - * called as:
    `cloneAttachFn(clonedElement, scope)` where: - * - * * `clonedElement` - is a clone of the original `element` passed into the compiler. - * * `scope` - is the current scope with which the linking function is working with. - * - * * `options` - An optional object hash with linking options. If `options` is provided, then the following - * keys may be used to control linking behavior: - * - * * `parentBoundTranscludeFn` - the transclude function made available to - * directives; if given, it will be passed through to the link functions of - * directives found in `element` during compilation. - * * `transcludeControllers` - an object hash with keys that map controller names - * to a hash with the key `instance`, which maps to the controller instance; - * if given, it will make the controllers available to directives on the compileNode: - * ``` - * { - * parent: { - * instance: parentControllerInstance - * } - * } - * ``` - * * `futureParentElement` - defines the parent to which the `cloneAttachFn` will add - * the cloned elements; only needed for transcludes that are allowed to contain non html - * elements (e.g. SVG elements). See also the directive.controller property. - * - * Calling the linking function returns the element of the template. It is either the original - * element passed in, or the clone of the element if the `cloneAttachFn` is provided. - * - * After linking the view is not updated until after a call to $digest which typically is done by - * AngularJS automatically. - * - * If you need access to the bound view, there are two ways to do it: - * - * - If you are not asking the linking function to clone the template, create the DOM element(s) - * before you send them to the compiler and keep this reference around. - * ```js - * var element = $compile('

    {{total}}

    ')(scope); - * ``` - * - * - if on the other hand, you need the element to be cloned, the view reference from the original - * example would not point to the clone, but rather to the original template that was cloned. In - * this case, you can access the clone via the cloneAttachFn: - * ```js - * var templateElement = angular.element('

    {{total}}

    '), - * scope = ....; - * - * var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) { - * //attach the clone to DOM document at the right place - * }); - * - * //now we have reference to the cloned DOM via `clonedElement` - * ``` - * - * - * For information on how the compiler works, see the - * {@link guide/compiler AngularJS HTML Compiler} section of the Developer Guide. - * - * @knownIssue - * - * ### Double Compilation - * - Double compilation occurs when an already compiled part of the DOM gets - compiled again. This is an undesired effect and can lead to misbehaving directives, performance issues, - and memory leaks. Refer to the Compiler Guide {@link guide/compiler#double-compilation-and-how-to-avoid-it - section on double compilation} for an in-depth explanation and ways to avoid it. - - * @knownIssue - - ### Issues with `replace: true` - * - *
    - * **Note**: {@link $compile#-replace- `replace: true`} is deprecated and not recommended to use, - * mainly due to the issues listed here. It has been completely removed in the new Angular. - *
    - * - * #### Attribute values are not merged - * - * When a `replace` directive encounters the same attribute on the original and the replace node, - * it will simply deduplicate the attribute and join the values with a space or with a `;` in case of - * the `style` attribute. - * ```html - * Original Node: - * Replace Template: - * Result: - * ``` - * - * That means attributes that contain AngularJS expressions will not be merged correctly, e.g. - * {@link ngShow} or {@link ngClass} will cause a {@link $parse} error: - * - * ```html - * Original Node: - * Replace Template: - * Result: - * ``` - * - * See issue [#5695](https://github.com/angular/angular.js/issues/5695). - * - * #### Directives are not deduplicated before compilation - * - * When the original node and the replace template declare the same directive(s), they will be - * {@link guide/compiler#double-compilation-and-how-to-avoid-it compiled twice} because the compiler - * does not deduplicate them. In many cases, this is not noticable, but e.g. {@link ngModel} will - * attach `$formatters` and `$parsers` twice. - * - * See issue [#2573](https://github.com/angular/angular.js/issues/2573). - * - * #### `transclude: element` in the replace template root can have unexpected effects - * - * When the replace template has a directive at the root node that uses - * {@link $compile#-transclude- `transclude: element`}, e.g. - * {@link ngIf} or {@link ngRepeat}, the DOM structure or scope inheritance can be incorrect. - * See the following issues: - * - * - Incorrect scope on replaced element: - * [#9837](https://github.com/angular/angular.js/issues/9837) - * - Different DOM between `template` and `templateUrl`: - * [#10612](https://github.com/angular/angular.js/issues/14326) - * - */ - -/** - * @ngdoc directive - * @name ngProp - * @restrict A - * @element ANY - * - * @usage - * - * ```html - * - * - * ``` - * - * or with uppercase letters in property (e.g. "propName"): - * - * - * ```html - * - * - * ``` - * - * - * @description - * The `ngProp` directive binds an expression to a DOM element property. - * `ngProp` allows writing to arbitrary properties by including - * the property name in the attribute, e.g. `ng-prop-value="'my value'"` binds 'my value' to - * the `value` property. - * - * Usually, it's not necessary to write to properties in AngularJS, as the built-in directives - * handle the most common use cases (instead of the above example, you would use {@link ngValue}). - * - * However, [custom elements](https://developer.mozilla.org/docs/Web/Web_Components/Using_custom_elements) - * often use custom properties to hold data, and `ngProp` can be used to provide input to these - * custom elements. - * - * ## Binding to camelCase properties - * - * Since HTML attributes are case-insensitive, camelCase properties like `innerHTML` must be escaped. - * AngularJS uses the underscore (_) in front of a character to indicate that it is uppercase, so - * `innerHTML` must be written as `ng-prop-inner_h_t_m_l="expression"` (Note that this is just an - * example, and for binding HTML {@link ngBindHtml} should be used. - * - * ## Security - * - * Binding expressions to arbitrary properties poses a security risk, as properties like `innerHTML` - * can insert potentially dangerous HTML into the application, e.g. script tags that execute - * malicious code. - * For this reason, `ngProp` applies Strict Contextual Escaping with the {@link ng.$sce $sce service}. - * This means vulnerable properties require their content to be "trusted", based on the - * context of the property. For example, the `innerHTML` is in the `HTML` context, and the - * `iframe.src` property is in the `RESOURCE_URL` context, which requires that values written to - * this property are trusted as a `RESOURCE_URL`. - * - * This can be set explicitly by calling $sce.trustAs(type, value) on the value that is - * trusted before passing it to the `ng-prop-*` directive. There are exist shorthand methods for - * each context type in the form of {@link ng.$sce#trustAsResourceUrl $sce.trustAsResourceUrl()} et al. - * - * In some cases you can also rely upon automatic sanitization of untrusted values - see below. - * - * Based on the context, other options may exist to mark a value as trusted / configure the behavior - * of {@link ng.$sce}. For example, to restrict the `RESOURCE_URL` context to specific origins, use - * the {@link $sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist()} - * and {@link $sceDelegateProvider#resourceUrlBlacklist resourceUrlBlacklist()}. - * - * {@link ng.$sce#what-trusted-context-types-are-supported- Find out more about the different context types}. - * - * ### HTML Sanitization - * - * By default, `$sce` will throw an error if it detects untrusted HTML content, and will not bind the - * content. - * However, if you include the {@link ngSanitize ngSanitize module}, it will try to sanitize the - * potentially dangerous HTML, e.g. strip non-whitelisted tags and attributes when binding to - * `innerHTML`. - * - * @example - * ### Binding to different contexts - * - * - * - * angular.module('exampleNgProp', []) - * .component('main', { - * templateUrl: 'main.html', - * controller: function($sce) { - * this.safeContent = 'Safe content'; - * this.unsafeContent = ''; - * this.trustedUnsafeContent = $sce.trustAsHtml(this.unsafeContent); - * } - * }); - * - * - *
    - *
    - * Binding to a property without security context: - *
    - * innerText (safeContent) - *
    - * - *
    - * "Safe" content that requires a security context will throw because the contents could potentially be dangerous ... - *
    - * innerHTML (safeContent) - *
    - * - *
    - * ... so that actually dangerous content cannot be executed: - *
    - * innerHTML (unsafeContent) - *
    - * - *
    - * ... but unsafe Content that has been trusted explicitly works - only do this if you are 100% sure! - *
    - * innerHTML (trustedUnsafeContent) - *
    - *
    - *
    - * - *
    - *
    - * - * .prop-unit { - * margin-bottom: 10px; - * } - * - * .prop-binding { - * min-height: 30px; - * border: 1px solid blue; - * } - * - * .prop-note { - * font-family: Monospace; - * } - * - *
    - * - * - * @example - * ### Binding to innerHTML with ngSanitize - * - * - * - * angular.module('exampleNgProp', ['ngSanitize']) - * .component('main', { - * templateUrl: 'main.html', - * controller: function($sce) { - * this.safeContent = 'Safe content'; - * this.unsafeContent = ''; - * this.trustedUnsafeContent = $sce.trustAsHtml(this.unsafeContent); - * } - * }); - * - * - *
    - *
    - * "Safe" content will be sanitized ... - *
    - * innerHTML (safeContent) - *
    - * - *
    - * ... as will dangerous content: - *
    - * innerHTML (unsafeContent) - *
    - * - *
    - * ... and content that has been trusted explicitly works the same as without ngSanitize: - *
    - * innerHTML (trustedUnsafeContent) - *
    - *
    - *
    - * - *
    - *
    - * - * .prop-unit { - * margin-bottom: 10px; - * } - * - * .prop-binding { - * min-height: 30px; - * border: 1px solid blue; - * } - * - * .prop-note { - * font-family: Monospace; - * } - * - *
    - * - */ - -/** @ngdoc directive - * @name ngOn - * @restrict A - * @element ANY - * - * @usage - * - * ```html - * - * - * ``` - * - * or with uppercase letters in property (e.g. "eventName"): - * - * - * ```html - * - * - * ``` - * - * @description - * The `ngOn` directive adds an event listener to a DOM element via - * {@link angular.element angular.element().on()}, and evaluates an expression when the event is - * fired. - * `ngOn` allows adding listeners for arbitrary events by including - * the event name in the attribute, e.g. `ng-on-drop="onDrop()"` executes the 'onDrop()' expression - * when the `drop` event is fired. - * - * AngularJS provides specific directives for many events, such as {@link ngClick}, so in most - * cases it is not necessary to use `ngOn`. However, AngularJS does not support all events - * (e.g. the `drop` event in the example above), and new events might be introduced in later DOM - * standards. - * - * Another use-case for `ngOn` is listening to - * [custom events](https://developer.mozilla.org/docs/Web/Guide/Events/Creating_and_triggering_events) - * fired by - * [custom elements](https://developer.mozilla.org/docs/Web/Web_Components/Using_custom_elements). - * - * ## Binding to camelCase properties - * - * Since HTML attributes are case-insensitive, camelCase properties like `myEvent` must be escaped. - * AngularJS uses the underscore (_) in front of a character to indicate that it is uppercase, so - * `myEvent` must be written as `ng-on-my_event="expression"`. - * - * @example - * ### Bind to built-in DOM events - * - * - * - * angular.module('exampleNgOn', []) - * .component('main', { - * templateUrl: 'main.html', - * controller: function() { - * this.clickCount = 0; - * this.mouseoverCount = 0; - * - * this.loadingState = 0; - * } - * }); - * - * - *
    - * This is equivalent to `ngClick` and `ngMouseover`:
    - *
    - * clickCount: {{$ctrl.clickCount}}
    - * mouseover: {{$ctrl.mouseoverCount}} - * - *
    - * - * For the `error` and `load` event on images no built-in AngularJS directives exist:
    - *
    - *
    - * Image is loading - * Image load error - * Image loaded successfully - *
    - *
    - *
    - * - *
    - *
    - *
    - * - * - * @example - * ### Bind to custom DOM events - * - * - * - * angular.module('exampleNgOn', []) - * .component('main', { - * templateUrl: 'main.html', - * controller: function() { - * this.eventLog = ''; - * - * this.listener = function($event) { - * this.eventLog = 'Event with type "' + $event.type + '" fired at ' + $event.detail; - * }; - * } - * }) - * .component('childComponent', { - * templateUrl: 'child.html', - * controller: function($element) { - * this.fireEvent = function() { - * var event = new CustomEvent('customtype', { detail: new Date()}); - * - * $element[0].dispatchEvent(event); - * }; - * } - * }); - * - * - *
    - * Event log: {{$ctrl.eventLog}} - *
    - * - - * - * - *
    - *
    - *
    - */ - -var $compileMinErr = minErr('$compile'); - -function UNINITIALIZED_VALUE() {} -var _UNINITIALIZED_VALUE = new UNINITIALIZED_VALUE(); - -/** - * @ngdoc provider - * @name $compileProvider - * - * @description - */ -$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider']; -/** @this */ -function $CompileProvider($provide, $$sanitizeUriProvider) { - var hasDirectives = {}, - Suffix = 'Directive', - COMMENT_DIRECTIVE_REGEXP = /^\s*directive:\s*([\w-]+)\s+(.*)$/, - CLASS_DIRECTIVE_REGEXP = /(([\w-]+)(?::([^;]+))?;?)/, - ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'), - REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/; - - // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes - // The assumption is that future DOM event attribute names will begin with - // 'on' and be composed of only English letters. - var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/; - var bindingCache = createMap(); - - function parseIsolateBindings(scope, directiveName, isController) { - var LOCAL_REGEXP = /^([@&]|[=<](\*?))(\??)\s*([\w$]*)$/; - - var bindings = createMap(); - - forEach(scope, function(definition, scopeName) { - definition = definition.trim(); - - if (definition in bindingCache) { - bindings[scopeName] = bindingCache[definition]; - return; - } - var match = definition.match(LOCAL_REGEXP); - - if (!match) { - throw $compileMinErr('iscp', - 'Invalid {3} for directive \'{0}\'.' + - ' Definition: {... {1}: \'{2}\' ...}', - directiveName, scopeName, definition, - (isController ? 'controller bindings definition' : - 'isolate scope definition')); - } - - bindings[scopeName] = { - mode: match[1][0], - collection: match[2] === '*', - optional: match[3] === '?', - attrName: match[4] || scopeName - }; - if (match[4]) { - bindingCache[definition] = bindings[scopeName]; - } - }); - - return bindings; - } - - function parseDirectiveBindings(directive, directiveName) { - var bindings = { - isolateScope: null, - bindToController: null - }; - if (isObject(directive.scope)) { - if (directive.bindToController === true) { - bindings.bindToController = parseIsolateBindings(directive.scope, - directiveName, true); - bindings.isolateScope = {}; - } else { - bindings.isolateScope = parseIsolateBindings(directive.scope, - directiveName, false); - } - } - if (isObject(directive.bindToController)) { - bindings.bindToController = - parseIsolateBindings(directive.bindToController, directiveName, true); - } - if (bindings.bindToController && !directive.controller) { - // There is no controller - throw $compileMinErr('noctrl', - 'Cannot bind to controller without directive \'{0}\'s controller.', - directiveName); - } - return bindings; - } - - function assertValidDirectiveName(name) { - var letter = name.charAt(0); - if (!letter || letter !== lowercase(letter)) { - throw $compileMinErr('baddir', 'Directive/Component name \'{0}\' is invalid. The first character must be a lowercase letter', name); - } - if (name !== name.trim()) { - throw $compileMinErr('baddir', - 'Directive/Component name \'{0}\' is invalid. The name should not contain leading or trailing whitespaces', - name); - } - } - - function getDirectiveRequire(directive) { - var require = directive.require || (directive.controller && directive.name); - - if (!isArray(require) && isObject(require)) { - forEach(require, function(value, key) { - var match = value.match(REQUIRE_PREFIX_REGEXP); - var name = value.substring(match[0].length); - if (!name) require[key] = match[0] + key; - }); - } - - return require; - } - - function getDirectiveRestrict(restrict, name) { - if (restrict && !(isString(restrict) && /[EACM]/.test(restrict))) { - throw $compileMinErr('badrestrict', - 'Restrict property \'{0}\' of directive \'{1}\' is invalid', - restrict, - name); - } - - return restrict || 'EA'; - } - - /** - * @ngdoc method - * @name $compileProvider#directive - * @kind function - * - * @description - * Register a new directive with the compiler. - * - * @param {string|Object} name Name of the directive in camel-case (i.e. ngBind which - * will match as ng-bind), or an object map of directives where the keys are the - * names and the values are the factories. - * @param {Function|Array} directiveFactory An injectable directive factory function. See the - * {@link guide/directive directive guide} and the {@link $compile compile API} for more info. - * @returns {ng.$compileProvider} Self for chaining. - */ - this.directive = function registerDirective(name, directiveFactory) { - assertArg(name, 'name'); - assertNotHasOwnProperty(name, 'directive'); - if (isString(name)) { - assertValidDirectiveName(name); - assertArg(directiveFactory, 'directiveFactory'); - if (!hasDirectives.hasOwnProperty(name)) { - hasDirectives[name] = []; - $provide.factory(name + Suffix, ['$injector', '$exceptionHandler', - function($injector, $exceptionHandler) { - var directives = []; - forEach(hasDirectives[name], function(directiveFactory, index) { - try { - var directive = $injector.invoke(directiveFactory); - if (isFunction(directive)) { - directive = { compile: valueFn(directive) }; - } else if (!directive.compile && directive.link) { - directive.compile = valueFn(directive.link); - } - directive.priority = directive.priority || 0; - directive.index = index; - directive.name = directive.name || name; - directive.require = getDirectiveRequire(directive); - directive.restrict = getDirectiveRestrict(directive.restrict, name); - directive.$$moduleName = directiveFactory.$$moduleName; - directives.push(directive); - } catch (e) { - $exceptionHandler(e); - } - }); - return directives; - }]); - } - hasDirectives[name].push(directiveFactory); - } else { - forEach(name, reverseParams(registerDirective)); - } - return this; - }; - - /** - * @ngdoc method - * @name $compileProvider#component - * @module ng - * @param {string|Object} name Name of the component in camelCase (i.e. `myComp` which will match ``), - * or an object map of components where the keys are the names and the values are the component definition objects. - * @param {Object} options Component definition object (a simplified - * {@link ng.$compile#directive-definition-object directive definition object}), - * with the following properties (all optional): - * - * - `controller` – `{(string|function()=}` – controller constructor function that should be - * associated with newly created scope or the name of a {@link ng.$compile#-controller- - * registered controller} if passed as a string. An empty `noop` function by default. - * - `controllerAs` – `{string=}` – identifier name for to reference the controller in the component's scope. - * If present, the controller will be published to scope under the `controllerAs` name. - * If not present, this will default to be `$ctrl`. - * - `template` – `{string=|function()=}` – html template as a string or a function that - * returns an html template as a string which should be used as the contents of this component. - * Empty string by default. - * - * If `template` is a function, then it is {@link auto.$injector#invoke injected} with - * the following locals: - * - * - `$element` - Current element - * - `$attrs` - Current attributes object for the element - * - * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html - * template that should be used as the contents of this component. - * - * If `templateUrl` is a function, then it is {@link auto.$injector#invoke injected} with - * the following locals: - * - * - `$element` - Current element - * - `$attrs` - Current attributes object for the element - * - * - `bindings` – `{object=}` – defines bindings between DOM attributes and component properties. - * Component properties are always bound to the component controller and not to the scope. - * See {@link ng.$compile#-bindtocontroller- `bindToController`}. - * - `transclude` – `{boolean=}` – whether {@link $compile#transclusion content transclusion} is enabled. - * Disabled by default. - * - `require` - `{Object=}` - requires the controllers of other directives and binds them to - * this component's controller. The object keys specify the property names under which the required - * controllers (object values) will be bound. See {@link ng.$compile#-require- `require`}. - * - `$...` – additional properties to attach to the directive factory function and the controller - * constructor function. (This is used by the component router to annotate) - * - * @returns {ng.$compileProvider} the compile provider itself, for chaining of function calls. - * @description - * Register a **component definition** with the compiler. This is a shorthand for registering a special - * type of directive, which represents a self-contained UI component in your application. Such components - * are always isolated (i.e. `scope: {}`) and are always restricted to elements (i.e. `restrict: 'E'`). - * - * Component definitions are very simple and do not require as much configuration as defining general - * directives. Component definitions usually consist only of a template and a controller backing it. - * - * In order to make the definition easier, components enforce best practices like use of `controllerAs`, - * `bindToController`. They always have **isolate scope** and are restricted to elements. - * - * Here are a few examples of how you would usually define components: - * - * ```js - * var myMod = angular.module(...); - * myMod.component('myComp', { - * template: '
    My name is {{$ctrl.name}}
    ', - * controller: function() { - * this.name = 'shahar'; - * } - * }); - * - * myMod.component('myComp', { - * template: '
    My name is {{$ctrl.name}}
    ', - * bindings: {name: '@'} - * }); - * - * myMod.component('myComp', { - * templateUrl: 'views/my-comp.html', - * controller: 'MyCtrl', - * controllerAs: 'ctrl', - * bindings: {name: '@'} - * }); - * - * ``` - * For more examples, and an in-depth guide, see the {@link guide/component component guide}. - * - *
    - * See also {@link ng.$compileProvider#directive $compileProvider.directive()}. - */ - this.component = function registerComponent(name, options) { - if (!isString(name)) { - forEach(name, reverseParams(bind(this, registerComponent))); - return this; - } - - var controller = options.controller || function() {}; - - function factory($injector) { - function makeInjectable(fn) { - if (isFunction(fn) || isArray(fn)) { - return /** @this */ function(tElement, tAttrs) { - return $injector.invoke(fn, this, {$element: tElement, $attrs: tAttrs}); - }; - } else { - return fn; - } - } - - var template = (!options.template && !options.templateUrl ? '' : options.template); - var ddo = { - controller: controller, - controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl', - template: makeInjectable(template), - templateUrl: makeInjectable(options.templateUrl), - transclude: options.transclude, - scope: {}, - bindToController: options.bindings || {}, - restrict: 'E', - require: options.require - }; - - // Copy annotations (starting with $) over to the DDO - forEach(options, function(val, key) { - if (key.charAt(0) === '$') ddo[key] = val; - }); - - return ddo; - } - - // TODO(pete) remove the following `forEach` before we release 1.6.0 - // The component-router@0.2.0 looks for the annotations on the controller constructor - // Nothing in AngularJS looks for annotations on the factory function but we can't remove - // it from 1.5.x yet. - - // Copy any annotation properties (starting with $) over to the factory and controller constructor functions - // These could be used by libraries such as the new component router - forEach(options, function(val, key) { - if (key.charAt(0) === '$') { - factory[key] = val; - // Don't try to copy over annotations to named controller - if (isFunction(controller)) controller[key] = val; - } - }); - - factory.$inject = ['$injector']; - - return this.directive(name, factory); - }; - - - /** - * @ngdoc method - * @name $compileProvider#aHrefSanitizationWhitelist - * @kind function - * - * @description - * Retrieves or overrides the default regular expression that is used for whitelisting of safe - * urls during a[href] sanitization. - * - * The sanitization is a security measure aimed at preventing XSS attacks via html links. - * - * Any url about to be assigned to a[href] via data-binding is first normalized and turned into - * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist` - * regular expression. If a match is found, the original url is written into the dom. Otherwise, - * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. - * - * @param {RegExp=} regexp New regexp to whitelist urls with. - * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for - * chaining otherwise. - */ - this.aHrefSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp); - return this; - } else { - return $$sanitizeUriProvider.aHrefSanitizationWhitelist(); - } - }; - - - /** - * @ngdoc method - * @name $compileProvider#imgSrcSanitizationWhitelist - * @kind function - * - * @description - * Retrieves or overrides the default regular expression that is used for whitelisting of safe - * urls during img[src] sanitization. - * - * The sanitization is a security measure aimed at prevent XSS attacks via html links. - * - * Any url about to be assigned to img[src] via data-binding is first normalized and turned into - * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist` - * regular expression. If a match is found, the original url is written into the dom. Otherwise, - * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM. - * - * @param {RegExp=} regexp New regexp to whitelist urls with. - * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for - * chaining otherwise. - */ - this.imgSrcSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp); - return this; - } else { - return $$sanitizeUriProvider.imgSrcSanitizationWhitelist(); - } - }; - - /** - * @ngdoc method - * @name $compileProvider#debugInfoEnabled - * - * @param {boolean=} enabled update the debugInfoEnabled state if provided, otherwise just return the - * current debugInfoEnabled state - * @returns {*} current value if used as getter or itself (chaining) if used as setter - * - * @kind function - * - * @description - * Call this method to enable/disable various debug runtime information in the compiler such as adding - * binding information and a reference to the current scope on to DOM elements. - * If enabled, the compiler will add the following to DOM elements that have been bound to the scope - * * `ng-binding` CSS class - * * `ng-scope` and `ng-isolated-scope` CSS classes - * * `$binding` data property containing an array of the binding expressions - * * Data properties used by the {@link angular.element#methods `scope()`/`isolateScope()` methods} to return - * the element's scope. - * * Placeholder comments will contain information about what directive and binding caused the placeholder. - * E.g. ``. - * - * You may want to disable this in production for a significant performance boost. See - * {@link guide/production#disabling-debug-data Disabling Debug Data} for more. - * - * The default value is true. - */ - var debugInfoEnabled = true; - this.debugInfoEnabled = function(enabled) { - if (isDefined(enabled)) { - debugInfoEnabled = enabled; - return this; - } - return debugInfoEnabled; - }; - - /** - * @ngdoc method - * @name $compileProvider#strictComponentBindingsEnabled - * - * @param {boolean=} enabled update the strictComponentBindingsEnabled state if provided, - * otherwise return the current strictComponentBindingsEnabled state. - * @returns {*} current value if used as getter or itself (chaining) if used as setter - * - * @kind function - * - * @description - * Call this method to enable / disable the strict component bindings check. If enabled, the - * compiler will enforce that all scope / controller bindings of a - * {@link $compileProvider#directive directive} / {@link $compileProvider#component component} - * that are not set as optional with `?`, must be provided when the directive is instantiated. - * If not provided, the compiler will throw the - * {@link error/$compile/missingattr $compile:missingattr error}. - * - * The default value is false. - */ - var strictComponentBindingsEnabled = false; - this.strictComponentBindingsEnabled = function(enabled) { - if (isDefined(enabled)) { - strictComponentBindingsEnabled = enabled; - return this; - } - return strictComponentBindingsEnabled; - }; - - var TTL = 10; - /** - * @ngdoc method - * @name $compileProvider#onChangesTtl - * @description - * - * Sets the number of times `$onChanges` hooks can trigger new changes before giving up and - * assuming that the model is unstable. - * - * The current default is 10 iterations. - * - * In complex applications it's possible that dependencies between `$onChanges` hooks and bindings will result - * in several iterations of calls to these hooks. However if an application needs more than the default 10 - * iterations to stabilize then you should investigate what is causing the model to continuously change during - * the `$onChanges` hook execution. - * - * Increasing the TTL could have performance implications, so you should not change it without proper justification. - * - * @param {number} limit The number of `$onChanges` hook iterations. - * @returns {number|object} the current limit (or `this` if called as a setter for chaining) - */ - this.onChangesTtl = function(value) { - if (arguments.length) { - TTL = value; - return this; - } - return TTL; - }; - - var commentDirectivesEnabledConfig = true; - /** - * @ngdoc method - * @name $compileProvider#commentDirectivesEnabled - * @description - * - * It indicates to the compiler - * whether or not directives on comments should be compiled. - * Defaults to `true`. - * - * Calling this function with false disables the compilation of directives - * on comments for the whole application. - * This results in a compilation performance gain, - * as the compiler doesn't have to check comments when looking for directives. - * This should however only be used if you are sure that no comment directives are used in - * the application (including any 3rd party directives). - * - * @param {boolean} enabled `false` if the compiler may ignore directives on comments - * @returns {boolean|object} the current value (or `this` if called as a setter for chaining) - */ - this.commentDirectivesEnabled = function(value) { - if (arguments.length) { - commentDirectivesEnabledConfig = value; - return this; - } - return commentDirectivesEnabledConfig; - }; - - - var cssClassDirectivesEnabledConfig = true; - /** - * @ngdoc method - * @name $compileProvider#cssClassDirectivesEnabled - * @description - * - * It indicates to the compiler - * whether or not directives on element classes should be compiled. - * Defaults to `true`. - * - * Calling this function with false disables the compilation of directives - * on element classes for the whole application. - * This results in a compilation performance gain, - * as the compiler doesn't have to check element classes when looking for directives. - * This should however only be used if you are sure that no class directives are used in - * the application (including any 3rd party directives). - * - * @param {boolean} enabled `false` if the compiler may ignore directives on element classes - * @returns {boolean|object} the current value (or `this` if called as a setter for chaining) - */ - this.cssClassDirectivesEnabled = function(value) { - if (arguments.length) { - cssClassDirectivesEnabledConfig = value; - return this; - } - return cssClassDirectivesEnabledConfig; - }; - - - /** - * The security context of DOM Properties. - * @private - */ - var PROP_CONTEXTS = createMap(); - - /** - * @ngdoc method - * @name $compileProvider#addPropertySecurityContext - * @description - * - * Defines the security context for DOM properties bound by ng-prop-*. - * - * @param {string} elementName The element name or '*' to match any element. - * @param {string} propertyName The DOM property name. - * @param {string} ctx The {@link $sce} security context in which this value is safe for use, e.g. `$sce.URL` - * @returns {object} `this` for chaining - */ - this.addPropertySecurityContext = function(elementName, propertyName, ctx) { - var key = (elementName.toLowerCase() + '|' + propertyName.toLowerCase()); - - if (key in PROP_CONTEXTS && PROP_CONTEXTS[key] !== ctx) { - throw $compileMinErr('ctxoverride', 'Property context \'{0}.{1}\' already set to \'{2}\', cannot override to \'{3}\'.', elementName, propertyName, PROP_CONTEXTS[key], ctx); - } - - PROP_CONTEXTS[key] = ctx; - return this; - }; - - /* Default property contexts. - * - * Copy of https://github.com/angular/angular/blob/6.0.6/packages/compiler/src/schema/dom_security_schema.ts#L31-L58 - * Changing: - * - SecurityContext.* => SCE_CONTEXTS/$sce.* - * - STYLE => CSS - * - various URL => MEDIA_URL - * - *|formAction, form|action URL => RESOURCE_URL (like the attribute) - */ - (function registerNativePropertyContexts() { - function registerContext(ctx, values) { - forEach(values, function(v) { PROP_CONTEXTS[v.toLowerCase()] = ctx; }); - } - - registerContext(SCE_CONTEXTS.HTML, [ - 'iframe|srcdoc', - '*|innerHTML', - '*|outerHTML' - ]); - registerContext(SCE_CONTEXTS.CSS, ['*|style']); - registerContext(SCE_CONTEXTS.URL, [ - 'area|href', 'area|ping', - 'a|href', 'a|ping', - 'blockquote|cite', - 'body|background', - 'del|cite', - 'input|src', - 'ins|cite', - 'q|cite' - ]); - registerContext(SCE_CONTEXTS.MEDIA_URL, [ - 'audio|src', - 'img|src', 'img|srcset', - 'source|src', 'source|srcset', - 'track|src', - 'video|src', 'video|poster' - ]); - registerContext(SCE_CONTEXTS.RESOURCE_URL, [ - '*|formAction', - 'applet|code', 'applet|codebase', - 'base|href', - 'embed|src', - 'frame|src', - 'form|action', - 'head|profile', - 'html|manifest', - 'iframe|src', - 'link|href', - 'media|src', - 'object|codebase', 'object|data', - 'script|src' - ]); - })(); - - - this.$get = [ - '$injector', '$interpolate', '$exceptionHandler', '$templateRequest', '$parse', - '$controller', '$rootScope', '$sce', '$animate', - function($injector, $interpolate, $exceptionHandler, $templateRequest, $parse, - $controller, $rootScope, $sce, $animate) { - - var SIMPLE_ATTR_NAME = /^\w/; - var specialAttrHolder = window.document.createElement('div'); - - - var commentDirectivesEnabled = commentDirectivesEnabledConfig; - var cssClassDirectivesEnabled = cssClassDirectivesEnabledConfig; - - - var onChangesTtl = TTL; - // The onChanges hooks should all be run together in a single digest - // When changes occur, the call to trigger their hooks will be added to this queue - var onChangesQueue; - - // This function is called in a $$postDigest to trigger all the onChanges hooks in a single digest - function flushOnChangesQueue() { - try { - if (!(--onChangesTtl)) { - // We have hit the TTL limit so reset everything - onChangesQueue = undefined; - throw $compileMinErr('infchng', '{0} $onChanges() iterations reached. Aborting!\n', TTL); - } - // We must run this hook in an apply since the $$postDigest runs outside apply - $rootScope.$apply(function() { - for (var i = 0, ii = onChangesQueue.length; i < ii; ++i) { - try { - onChangesQueue[i](); - } catch (e) { - $exceptionHandler(e); - } - } - // Reset the queue to trigger a new schedule next time there is a change - onChangesQueue = undefined; - }); - } finally { - onChangesTtl++; - } - } - - - function sanitizeSrcset(value, invokeType) { - if (!value) { - return value; - } - if (!isString(value)) { - throw $compileMinErr('srcset', 'Can\'t pass trusted values to `{0}`: "{1}"', invokeType, value.toString()); - } - - // Such values are a bit too complex to handle automatically inside $sce. - // Instead, we sanitize each of the URIs individually, which works, even dynamically. - - // It's not possible to work around this using `$sce.trustAsMediaUrl`. - // If you want to programmatically set explicitly trusted unsafe URLs, you should use - // `$sce.trustAsHtml` on the whole `img` tag and inject it into the DOM using the - // `ng-bind-html` directive. - - var result = ''; - - // first check if there are spaces because it's not the same pattern - var trimmedSrcset = trim(value); - // ( 999x ,| 999w ,| ,|, ) - var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/; - var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/; - - // split srcset into tuple of uri and descriptor except for the last item - var rawUris = trimmedSrcset.split(pattern); - - // for each tuples - var nbrUrisWith2parts = Math.floor(rawUris.length / 2); - for (var i = 0; i < nbrUrisWith2parts; i++) { - var innerIdx = i * 2; - // sanitize the uri - result += $sce.getTrustedMediaUrl(trim(rawUris[innerIdx])); - // add the descriptor - result += ' ' + trim(rawUris[innerIdx + 1]); - } - - // split the last item into uri and descriptor - var lastTuple = trim(rawUris[i * 2]).split(/\s/); - - // sanitize the last uri - result += $sce.getTrustedMediaUrl(trim(lastTuple[0])); - - // and add the last descriptor if any - if (lastTuple.length === 2) { - result += (' ' + trim(lastTuple[1])); - } - return result; - } - - - function Attributes(element, attributesToCopy) { - if (attributesToCopy) { - var keys = Object.keys(attributesToCopy); - var i, l, key; - - for (i = 0, l = keys.length; i < l; i++) { - key = keys[i]; - this[key] = attributesToCopy[key]; - } - } else { - this.$attr = {}; - } - - this.$$element = element; - } - - Attributes.prototype = { - /** - * @ngdoc method - * @name $compile.directive.Attributes#$normalize - * @kind function - * - * @description - * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with `x-` or - * `data-`) to its normalized, camelCase form. - * - * Also there is special case for Moz prefix starting with upper case letter. - * - * For further information check out the guide on {@link guide/directive#matching-directives Matching Directives} - * - * @param {string} name Name to normalize - */ - $normalize: directiveNormalize, - - - /** - * @ngdoc method - * @name $compile.directive.Attributes#$addClass - * @kind function - * - * @description - * Adds the CSS class value specified by the classVal parameter to the element. If animations - * are enabled then an animation will be triggered for the class addition. - * - * @param {string} classVal The className value that will be added to the element - */ - $addClass: function(classVal) { - if (classVal && classVal.length > 0) { - $animate.addClass(this.$$element, classVal); - } - }, - - /** - * @ngdoc method - * @name $compile.directive.Attributes#$removeClass - * @kind function - * - * @description - * Removes the CSS class value specified by the classVal parameter from the element. If - * animations are enabled then an animation will be triggered for the class removal. - * - * @param {string} classVal The className value that will be removed from the element - */ - $removeClass: function(classVal) { - if (classVal && classVal.length > 0) { - $animate.removeClass(this.$$element, classVal); - } - }, - - /** - * @ngdoc method - * @name $compile.directive.Attributes#$updateClass - * @kind function - * - * @description - * Adds and removes the appropriate CSS class values to the element based on the difference - * between the new and old CSS class values (specified as newClasses and oldClasses). - * - * @param {string} newClasses The current CSS className value - * @param {string} oldClasses The former CSS className value - */ - $updateClass: function(newClasses, oldClasses) { - var toAdd = tokenDifference(newClasses, oldClasses); - if (toAdd && toAdd.length) { - $animate.addClass(this.$$element, toAdd); - } - - var toRemove = tokenDifference(oldClasses, newClasses); - if (toRemove && toRemove.length) { - $animate.removeClass(this.$$element, toRemove); - } - }, - - /** - * Set a normalized attribute on the element in a way such that all directives - * can share the attribute. This function properly handles boolean attributes. - * @param {string} key Normalized key. (ie ngAttribute) - * @param {string|boolean} value The value to set. If `null` attribute will be deleted. - * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute. - * Defaults to true. - * @param {string=} attrName Optional none normalized name. Defaults to key. - */ - $set: function(key, value, writeAttr, attrName) { - // TODO: decide whether or not to throw an error if "class" - // is set through this function since it may cause $updateClass to - // become unstable. - - var node = this.$$element[0], - booleanKey = getBooleanAttrName(node, key), - aliasedKey = getAliasedAttrName(key), - observer = key, - nodeName; - - if (booleanKey) { - this.$$element.prop(key, value); - attrName = booleanKey; - } else if (aliasedKey) { - this[aliasedKey] = value; - observer = aliasedKey; - } - - this[key] = value; - - // translate normalized key to actual key - if (attrName) { - this.$attr[key] = attrName; - } else { - attrName = this.$attr[key]; - if (!attrName) { - this.$attr[key] = attrName = snake_case(key, '-'); - } - } - - nodeName = nodeName_(this.$$element); - - // Sanitize img[srcset] values. - if (nodeName === 'img' && key === 'srcset') { - this[key] = value = sanitizeSrcset(value, '$set(\'srcset\', value)'); - } - - if (writeAttr !== false) { - if (value === null || isUndefined(value)) { - this.$$element.removeAttr(attrName); - } else { - if (SIMPLE_ATTR_NAME.test(attrName)) { - // jQuery skips special boolean attrs treatment in XML nodes for - // historical reasons and hence AngularJS cannot freely call - // `.attr(attrName, false) with such attributes. To avoid issues - // in XHTML, call `removeAttr` in such cases instead. - // See https://github.com/jquery/jquery/issues/4249 - if (booleanKey && value === false) { - this.$$element.removeAttr(attrName); - } else { - this.$$element.attr(attrName, value); - } - } else { - setSpecialAttr(this.$$element[0], attrName, value); - } - } - } - - // fire observers - var $$observers = this.$$observers; - if ($$observers) { - forEach($$observers[observer], function(fn) { - try { - fn(value); - } catch (e) { - $exceptionHandler(e); - } - }); - } - }, - - - /** - * @ngdoc method - * @name $compile.directive.Attributes#$observe - * @kind function - * - * @description - * Observes an interpolated attribute. - * - * The observer function will be invoked once during the next `$digest` following - * compilation. The observer is then invoked whenever the interpolated value - * changes. - * - * @param {string} key Normalized key. (ie ngAttribute) . - * @param {function(interpolatedValue)} fn Function that will be called whenever - the interpolated value of the attribute changes. - * See the {@link guide/interpolation#how-text-and-attribute-bindings-work Interpolation - * guide} for more info. - * @returns {function()} Returns a deregistration function for this observer. - */ - $observe: function(key, fn) { - var attrs = this, - $$observers = (attrs.$$observers || (attrs.$$observers = createMap())), - listeners = ($$observers[key] || ($$observers[key] = [])); - - listeners.push(fn); - $rootScope.$evalAsync(function() { - if (!listeners.$$inter && attrs.hasOwnProperty(key) && !isUndefined(attrs[key])) { - // no one registered attribute interpolation function, so lets call it manually - fn(attrs[key]); - } - }); - - return function() { - arrayRemove(listeners, fn); - }; - } - }; - - function setSpecialAttr(element, attrName, value) { - // Attributes names that do not start with letters (such as `(click)`) cannot be set using `setAttribute` - // so we have to jump through some hoops to get such an attribute - // https://github.com/angular/angular.js/pull/13318 - specialAttrHolder.innerHTML = ''; - var attributes = specialAttrHolder.firstChild.attributes; - var attribute = attributes[0]; - // We have to remove the attribute from its container element before we can add it to the destination element - attributes.removeNamedItem(attribute.name); - attribute.value = value; - element.attributes.setNamedItem(attribute); - } - - function safeAddClass($element, className) { - try { - $element.addClass(className); - } catch (e) { - // ignore, since it means that we are trying to set class on - // SVG element, where class name is read-only. - } - } - - - var startSymbol = $interpolate.startSymbol(), - endSymbol = $interpolate.endSymbol(), - denormalizeTemplate = (startSymbol === '{{' && endSymbol === '}}') - ? identity - : function denormalizeTemplate(template) { - return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); - }, - NG_PREFIX_BINDING = /^ng(Attr|Prop|On)([A-Z].*)$/; - var MULTI_ELEMENT_DIR_RE = /^(.+)Start$/; - - compile.$$addBindingInfo = debugInfoEnabled ? function $$addBindingInfo($element, binding) { - var bindings = $element.data('$binding') || []; - - if (isArray(binding)) { - bindings = bindings.concat(binding); - } else { - bindings.push(binding); - } - - $element.data('$binding', bindings); - } : noop; - - compile.$$addBindingClass = debugInfoEnabled ? function $$addBindingClass($element) { - safeAddClass($element, 'ng-binding'); - } : noop; - - compile.$$addScopeInfo = debugInfoEnabled ? function $$addScopeInfo($element, scope, isolated, noTemplate) { - var dataName = isolated ? (noTemplate ? '$isolateScopeNoTemplate' : '$isolateScope') : '$scope'; - $element.data(dataName, scope); - } : noop; - - compile.$$addScopeClass = debugInfoEnabled ? function $$addScopeClass($element, isolated) { - safeAddClass($element, isolated ? 'ng-isolate-scope' : 'ng-scope'); - } : noop; - - compile.$$createComment = function(directiveName, comment) { - var content = ''; - if (debugInfoEnabled) { - content = ' ' + (directiveName || '') + ': '; - if (comment) content += comment + ' '; - } - return window.document.createComment(content); - }; - - return compile; - - //================================ - - function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, - previousCompileContext) { - if (!($compileNodes instanceof jqLite)) { - // jquery always rewraps, whereas we need to preserve the original selector so that we can - // modify it. - $compileNodes = jqLite($compileNodes); - } - var compositeLinkFn = - compileNodes($compileNodes, transcludeFn, $compileNodes, - maxPriority, ignoreDirective, previousCompileContext); - compile.$$addScopeClass($compileNodes); - var namespace = null; - return function publicLinkFn(scope, cloneConnectFn, options) { - if (!$compileNodes) { - throw $compileMinErr('multilink', 'This element has already been linked.'); - } - assertArg(scope, 'scope'); - - if (previousCompileContext && previousCompileContext.needsNewScope) { - // A parent directive did a replace and a directive on this element asked - // for transclusion, which caused us to lose a layer of element on which - // we could hold the new transclusion scope, so we will create it manually - // here. - scope = scope.$parent.$new(); - } - - options = options || {}; - var parentBoundTranscludeFn = options.parentBoundTranscludeFn, - transcludeControllers = options.transcludeControllers, - futureParentElement = options.futureParentElement; - - // When `parentBoundTranscludeFn` is passed, it is a - // `controllersBoundTransclude` function (it was previously passed - // as `transclude` to directive.link) so we must unwrap it to get - // its `boundTranscludeFn` - if (parentBoundTranscludeFn && parentBoundTranscludeFn.$$boundTransclude) { - parentBoundTranscludeFn = parentBoundTranscludeFn.$$boundTransclude; - } - - if (!namespace) { - namespace = detectNamespaceForChildElements(futureParentElement); - } - var $linkNode; - if (namespace !== 'html') { - // When using a directive with replace:true and templateUrl the $compileNodes - // (or a child element inside of them) - // might change, so we need to recreate the namespace adapted compileNodes - // for call to the link function. - // Note: This will already clone the nodes... - $linkNode = jqLite( - wrapTemplate(namespace, jqLite('
    ').append($compileNodes).html()) - ); - } else if (cloneConnectFn) { - // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart - // and sometimes changes the structure of the DOM. - $linkNode = JQLitePrototype.clone.call($compileNodes); - } else { - $linkNode = $compileNodes; - } - - if (transcludeControllers) { - for (var controllerName in transcludeControllers) { - $linkNode.data('$' + controllerName + 'Controller', transcludeControllers[controllerName].instance); - } - } - - compile.$$addScopeInfo($linkNode, scope); - - if (cloneConnectFn) cloneConnectFn($linkNode, scope); - if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn); - - if (!cloneConnectFn) { - $compileNodes = compositeLinkFn = null; - } - return $linkNode; - }; - } - - function detectNamespaceForChildElements(parentElement) { - // TODO: Make this detect MathML as well... - var node = parentElement && parentElement[0]; - if (!node) { - return 'html'; - } else { - return nodeName_(node) !== 'foreignobject' && toString.call(node).match(/SVG/) ? 'svg' : 'html'; - } - } - - /** - * Compile function matches each node in nodeList against the directives. Once all directives - * for a particular node are collected their compile functions are executed. The compile - * functions return values - the linking functions - are combined into a composite linking - * function, which is the a linking function for the node. - * - * @param {NodeList} nodeList an array of nodes or NodeList to compile - * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the - * scope argument is auto-generated to the new child of the transcluded parent scope. - * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then - * the rootElement must be set the jqLite collection of the compile root. This is - * needed so that the jqLite collection items can be replaced with widgets. - * @param {number=} maxPriority Max directive priority. - * @returns {Function} A composite linking function of all of the matched directives or null. - */ - function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective, - previousCompileContext) { - var linkFns = [], - // `nodeList` can be either an element's `.childNodes` (live NodeList) - // or a jqLite/jQuery collection or an array - notLiveList = isArray(nodeList) || (nodeList instanceof jqLite), - attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound; - - - for (var i = 0; i < nodeList.length; i++) { - attrs = new Attributes(); - - // Support: IE 11 only - // Workaround for #11781 and #14924 - if (msie === 11) { - mergeConsecutiveTextNodes(nodeList, i, notLiveList); - } - - // We must always refer to `nodeList[i]` hereafter, - // since the nodes can be replaced underneath us. - directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined, - ignoreDirective); - - nodeLinkFn = (directives.length) - ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement, - null, [], [], previousCompileContext) - : null; - - if (nodeLinkFn && nodeLinkFn.scope) { - compile.$$addScopeClass(attrs.$$element); - } - - childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || - !(childNodes = nodeList[i].childNodes) || - !childNodes.length) - ? null - : compileNodes(childNodes, - nodeLinkFn ? ( - (nodeLinkFn.transcludeOnThisElement || !nodeLinkFn.templateOnThisElement) - && nodeLinkFn.transclude) : transcludeFn); - - if (nodeLinkFn || childLinkFn) { - linkFns.push(i, nodeLinkFn, childLinkFn); - linkFnFound = true; - nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn; - } - - //use the previous context only for the first element in the virtual group - previousCompileContext = null; - } - - // return a linking function if we have found anything, null otherwise - return linkFnFound ? compositeLinkFn : null; - - function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) { - var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn; - var stableNodeList; - - - if (nodeLinkFnFound) { - // copy nodeList so that if a nodeLinkFn removes or adds an element at this DOM level our - // offsets don't get screwed up - var nodeListLength = nodeList.length; - stableNodeList = new Array(nodeListLength); - - // create a sparse array by only copying the elements which have a linkFn - for (i = 0; i < linkFns.length; i += 3) { - idx = linkFns[i]; - stableNodeList[idx] = nodeList[idx]; - } - } else { - stableNodeList = nodeList; - } - - for (i = 0, ii = linkFns.length; i < ii;) { - node = stableNodeList[linkFns[i++]]; - nodeLinkFn = linkFns[i++]; - childLinkFn = linkFns[i++]; - - if (nodeLinkFn) { - if (nodeLinkFn.scope) { - childScope = scope.$new(); - compile.$$addScopeInfo(jqLite(node), childScope); - } else { - childScope = scope; - } - - if (nodeLinkFn.transcludeOnThisElement) { - childBoundTranscludeFn = createBoundTranscludeFn( - scope, nodeLinkFn.transclude, parentBoundTranscludeFn); - - } else if (!nodeLinkFn.templateOnThisElement && parentBoundTranscludeFn) { - childBoundTranscludeFn = parentBoundTranscludeFn; - - } else if (!parentBoundTranscludeFn && transcludeFn) { - childBoundTranscludeFn = createBoundTranscludeFn(scope, transcludeFn); - - } else { - childBoundTranscludeFn = null; - } - - nodeLinkFn(childLinkFn, childScope, node, $rootElement, childBoundTranscludeFn); - - } else if (childLinkFn) { - childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn); - } - } - } - } - - function mergeConsecutiveTextNodes(nodeList, idx, notLiveList) { - var node = nodeList[idx]; - var parent = node.parentNode; - var sibling; - - if (node.nodeType !== NODE_TYPE_TEXT) { - return; - } - - while (true) { - sibling = parent ? node.nextSibling : nodeList[idx + 1]; - if (!sibling || sibling.nodeType !== NODE_TYPE_TEXT) { - break; - } - - node.nodeValue = node.nodeValue + sibling.nodeValue; - - if (sibling.parentNode) { - sibling.parentNode.removeChild(sibling); - } - if (notLiveList && sibling === nodeList[idx + 1]) { - nodeList.splice(idx + 1, 1); - } - } - } - - function createBoundTranscludeFn(scope, transcludeFn, previousBoundTranscludeFn) { - function boundTranscludeFn(transcludedScope, cloneFn, controllers, futureParentElement, containingScope) { - - if (!transcludedScope) { - transcludedScope = scope.$new(false, containingScope); - transcludedScope.$$transcluded = true; - } - - return transcludeFn(transcludedScope, cloneFn, { - parentBoundTranscludeFn: previousBoundTranscludeFn, - transcludeControllers: controllers, - futureParentElement: futureParentElement - }); - } - - // We need to attach the transclusion slots onto the `boundTranscludeFn` - // so that they are available inside the `controllersBoundTransclude` function - var boundSlots = boundTranscludeFn.$$slots = createMap(); - for (var slotName in transcludeFn.$$slots) { - if (transcludeFn.$$slots[slotName]) { - boundSlots[slotName] = createBoundTranscludeFn(scope, transcludeFn.$$slots[slotName], previousBoundTranscludeFn); - } else { - boundSlots[slotName] = null; - } - } - - return boundTranscludeFn; - } - - /** - * Looks for directives on the given node and adds them to the directive collection which is - * sorted. - * - * @param node Node to search. - * @param directives An array to which the directives are added to. This array is sorted before - * the function returns. - * @param attrs The shared attrs object which is used to populate the normalized attributes. - * @param {number=} maxPriority Max directive priority. - */ - function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) { - var nodeType = node.nodeType, - attrsMap = attrs.$attr, - match, - nodeName, - className; - - switch (nodeType) { - case NODE_TYPE_ELEMENT: /* Element */ - - nodeName = nodeName_(node); - - // use the node name: - addDirective(directives, - directiveNormalize(nodeName), 'E', maxPriority, ignoreDirective); - - // iterate over the attributes - for (var attr, name, nName, value, ngPrefixMatch, nAttrs = node.attributes, - j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { - var attrStartName = false; - var attrEndName = false; - - var isNgAttr = false, isNgProp = false, isNgEvent = false; - var multiElementMatch; - - attr = nAttrs[j]; - name = attr.name; - value = attr.value; - - nName = directiveNormalize(name.toLowerCase()); - - // Support ng-attr-*, ng-prop-* and ng-on-* - if ((ngPrefixMatch = nName.match(NG_PREFIX_BINDING))) { - isNgAttr = ngPrefixMatch[1] === 'Attr'; - isNgProp = ngPrefixMatch[1] === 'Prop'; - isNgEvent = ngPrefixMatch[1] === 'On'; - - // Normalize the non-prefixed name - name = name.replace(PREFIX_REGEXP, '') - .toLowerCase() - .substr(4 + ngPrefixMatch[1].length).replace(/_(.)/g, function(match, letter) { - return letter.toUpperCase(); - }); - - // Support *-start / *-end multi element directives - } else if ((multiElementMatch = nName.match(MULTI_ELEMENT_DIR_RE)) && directiveIsMultiElement(multiElementMatch[1])) { - attrStartName = name; - attrEndName = name.substr(0, name.length - 5) + 'end'; - name = name.substr(0, name.length - 6); - } - - if (isNgProp || isNgEvent) { - attrs[nName] = value; - attrsMap[nName] = attr.name; - - if (isNgProp) { - addPropertyDirective(node, directives, nName, name); - } else { - addEventDirective(directives, nName, name); - } - } else { - // Update nName for cases where a prefix was removed - // NOTE: the .toLowerCase() is unnecessary and causes https://github.com/angular/angular.js/issues/16624 for ng-attr-* - nName = directiveNormalize(name.toLowerCase()); - attrsMap[nName] = name; - - if (isNgAttr || !attrs.hasOwnProperty(nName)) { - attrs[nName] = value; - if (getBooleanAttrName(node, nName)) { - attrs[nName] = true; // presence means true - } - } - - addAttrInterpolateDirective(node, directives, value, nName, isNgAttr); - addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName, - attrEndName); - } - } - - if (nodeName === 'input' && node.getAttribute('type') === 'hidden') { - // Hidden input elements can have strange behaviour when navigating back to the page - // This tells the browser not to try to cache and reinstate previous values - node.setAttribute('autocomplete', 'off'); - } - - // use class as directive - if (!cssClassDirectivesEnabled) break; - className = node.className; - if (isObject(className)) { - // Maybe SVGAnimatedString - className = className.animVal; - } - if (isString(className) && className !== '') { - while ((match = CLASS_DIRECTIVE_REGEXP.exec(className))) { - nName = directiveNormalize(match[2]); - if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) { - attrs[nName] = trim(match[3]); - } - className = className.substr(match.index + match[0].length); - } - } - break; - case NODE_TYPE_TEXT: /* Text Node */ - addTextInterpolateDirective(directives, node.nodeValue); - break; - case NODE_TYPE_COMMENT: /* Comment */ - if (!commentDirectivesEnabled) break; - collectCommentDirectives(node, directives, attrs, maxPriority, ignoreDirective); - break; - } - - directives.sort(byPriority); - return directives; - } - - function collectCommentDirectives(node, directives, attrs, maxPriority, ignoreDirective) { - // function created because of performance, try/catch disables - // the optimization of the whole function #14848 - try { - var match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); - if (match) { - var nName = directiveNormalize(match[1]); - if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) { - attrs[nName] = trim(match[2]); - } - } - } catch (e) { - // turns out that under some circumstances IE9 throws errors when one attempts to read - // comment's node value. - // Just ignore it and continue. (Can't seem to reproduce in test case.) - } - } - - /** - * Given a node with a directive-start it collects all of the siblings until it finds - * directive-end. - * @param node - * @param attrStart - * @param attrEnd - * @returns {*} - */ - function groupScan(node, attrStart, attrEnd) { - var nodes = []; - var depth = 0; - if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) { - do { - if (!node) { - throw $compileMinErr('uterdir', - 'Unterminated attribute, found \'{0}\' but no matching \'{1}\' found.', - attrStart, attrEnd); - } - if (node.nodeType === NODE_TYPE_ELEMENT) { - if (node.hasAttribute(attrStart)) depth++; - if (node.hasAttribute(attrEnd)) depth--; - } - nodes.push(node); - node = node.nextSibling; - } while (depth > 0); - } else { - nodes.push(node); - } - - return jqLite(nodes); - } - - /** - * Wrapper for linking function which converts normal linking function into a grouped - * linking function. - * @param linkFn - * @param attrStart - * @param attrEnd - * @returns {Function} - */ - function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) { - return function groupedElementsLink(scope, element, attrs, controllers, transcludeFn) { - element = groupScan(element[0], attrStart, attrEnd); - return linkFn(scope, element, attrs, controllers, transcludeFn); - }; - } - - /** - * A function generator that is used to support both eager and lazy compilation - * linking function. - * @param eager - * @param $compileNodes - * @param transcludeFn - * @param maxPriority - * @param ignoreDirective - * @param previousCompileContext - * @returns {Function} - */ - function compilationGenerator(eager, $compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext) { - var compiled; - - if (eager) { - return compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext); - } - return /** @this */ function lazyCompilation() { - if (!compiled) { - compiled = compile($compileNodes, transcludeFn, maxPriority, ignoreDirective, previousCompileContext); - - // Null out all of these references in order to make them eligible for garbage collection - // since this is a potentially long lived closure - $compileNodes = transcludeFn = previousCompileContext = null; - } - return compiled.apply(this, arguments); - }; - } - - /** - * Once the directives have been collected, their compile functions are executed. This method - * is responsible for inlining directive templates as well as terminating the application - * of the directives if the terminal directive has been reached. - * - * @param {Array} directives Array of collected directives to execute their compile function. - * this needs to be pre-sorted by priority order. - * @param {Node} compileNode The raw DOM node to apply the compile functions to - * @param {Object} templateAttrs The shared attribute function - * @param {function(angular.Scope, cloneAttachFn=)} transcludeFn A linking function, where the - * scope argument is auto-generated to the new - * child of the transcluded parent scope. - * @param {JQLite} jqCollection If we are working on the root of the compile tree then this - * argument has the root jqLite array so that we can replace nodes - * on it. - * @param {Object=} originalReplaceDirective An optional directive that will be ignored when - * compiling the transclusion. - * @param {Array.} preLinkFns - * @param {Array.} postLinkFns - * @param {Object} previousCompileContext Context used for previous compilation of the current - * node - * @returns {Function} linkFn - */ - function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, - jqCollection, originalReplaceDirective, preLinkFns, postLinkFns, - previousCompileContext) { - previousCompileContext = previousCompileContext || {}; - - var terminalPriority = -Number.MAX_VALUE, - newScopeDirective = previousCompileContext.newScopeDirective, - controllerDirectives = previousCompileContext.controllerDirectives, - newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, - templateDirective = previousCompileContext.templateDirective, - nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective, - hasTranscludeDirective = false, - hasTemplate = false, - hasElementTranscludeDirective = previousCompileContext.hasElementTranscludeDirective, - $compileNode = templateAttrs.$$element = jqLite(compileNode), - directive, - directiveName, - $template, - replaceDirective = originalReplaceDirective, - childTranscludeFn = transcludeFn, - linkFn, - didScanForMultipleTransclusion = false, - mightHaveMultipleTransclusionError = false, - directiveValue; - - // executes all directives on the current element - for (var i = 0, ii = directives.length; i < ii; i++) { - directive = directives[i]; - var attrStart = directive.$$start; - var attrEnd = directive.$$end; - - // collect multiblock sections - if (attrStart) { - $compileNode = groupScan(compileNode, attrStart, attrEnd); - } - $template = undefined; - - if (terminalPriority > directive.priority) { - break; // prevent further processing of directives - } - - directiveValue = directive.scope; - - if (directiveValue) { - - // skip the check for directives with async templates, we'll check the derived sync - // directive when the template arrives - if (!directive.templateUrl) { - if (isObject(directiveValue)) { - // This directive is trying to add an isolated scope. - // Check that there is no scope of any kind already - assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective, - directive, $compileNode); - newIsolateScopeDirective = directive; - } else { - // This directive is trying to add a child scope. - // Check that there is no isolated scope already - assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive, - $compileNode); - } - } - - newScopeDirective = newScopeDirective || directive; - } - - directiveName = directive.name; - - // If we encounter a condition that can result in transclusion on the directive, - // then scan ahead in the remaining directives for others that may cause a multiple - // transclusion error to be thrown during the compilation process. If a matching directive - // is found, then we know that when we encounter a transcluded directive, we need to eagerly - // compile the `transclude` function rather than doing it lazily in order to throw - // exceptions at the correct time - if (!didScanForMultipleTransclusion && ((directive.replace && (directive.templateUrl || directive.template)) - || (directive.transclude && !directive.$$tlb))) { - var candidateDirective; - - for (var scanningIndex = i + 1; (candidateDirective = directives[scanningIndex++]);) { - if ((candidateDirective.transclude && !candidateDirective.$$tlb) - || (candidateDirective.replace && (candidateDirective.templateUrl || candidateDirective.template))) { - mightHaveMultipleTransclusionError = true; - break; - } - } - - didScanForMultipleTransclusion = true; - } - - if (!directive.templateUrl && directive.controller) { - controllerDirectives = controllerDirectives || createMap(); - assertNoDuplicate('\'' + directiveName + '\' controller', - controllerDirectives[directiveName], directive, $compileNode); - controllerDirectives[directiveName] = directive; - } - - directiveValue = directive.transclude; - - if (directiveValue) { - hasTranscludeDirective = true; - - // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion. - // This option should only be used by directives that know how to safely handle element transclusion, - // where the transcluded nodes are added or replaced after linking. - if (!directive.$$tlb) { - assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode); - nonTlbTranscludeDirective = directive; - } - - if (directiveValue === 'element') { - hasElementTranscludeDirective = true; - terminalPriority = directive.priority; - $template = $compileNode; - $compileNode = templateAttrs.$$element = - jqLite(compile.$$createComment(directiveName, templateAttrs[directiveName])); - compileNode = $compileNode[0]; - replaceWith(jqCollection, sliceArgs($template), compileNode); - - childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, terminalPriority, - replaceDirective && replaceDirective.name, { - // Don't pass in: - // - controllerDirectives - otherwise we'll create duplicates controllers - // - newIsolateScopeDirective or templateDirective - combining templates with - // element transclusion doesn't make sense. - // - // We need only nonTlbTranscludeDirective so that we prevent putting transclusion - // on the same element more than once. - nonTlbTranscludeDirective: nonTlbTranscludeDirective - }); - } else { - - var slots = createMap(); - - if (!isObject(directiveValue)) { - $template = jqLite(jqLiteClone(compileNode)).contents(); - } else { - - // We have transclusion slots, - // collect them up, compile them and store their transclusion functions - $template = window.document.createDocumentFragment(); - - var slotMap = createMap(); - var filledSlots = createMap(); - - // Parse the element selectors - forEach(directiveValue, function(elementSelector, slotName) { - // If an element selector starts with a ? then it is optional - var optional = (elementSelector.charAt(0) === '?'); - elementSelector = optional ? elementSelector.substring(1) : elementSelector; - - slotMap[elementSelector] = slotName; - - // We explicitly assign `null` since this implies that a slot was defined but not filled. - // Later when calling boundTransclusion functions with a slot name we only error if the - // slot is `undefined` - slots[slotName] = null; - - // filledSlots contains `true` for all slots that are either optional or have been - // filled. This is used to check that we have not missed any required slots - filledSlots[slotName] = optional; - }); - - // Add the matching elements into their slot - forEach($compileNode.contents(), function(node) { - var slotName = slotMap[directiveNormalize(nodeName_(node))]; - if (slotName) { - filledSlots[slotName] = true; - slots[slotName] = slots[slotName] || window.document.createDocumentFragment(); - slots[slotName].appendChild(node); - } else { - $template.appendChild(node); - } - }); - - // Check for required slots that were not filled - forEach(filledSlots, function(filled, slotName) { - if (!filled) { - throw $compileMinErr('reqslot', 'Required transclusion slot `{0}` was not filled.', slotName); - } - }); - - for (var slotName in slots) { - if (slots[slotName]) { - // Only define a transclusion function if the slot was filled - var slotCompileNodes = jqLite(slots[slotName].childNodes); - slots[slotName] = compilationGenerator(mightHaveMultipleTransclusionError, slotCompileNodes, transcludeFn); - } - } - - $template = jqLite($template.childNodes); - } - - $compileNode.empty(); // clear contents - childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, undefined, - undefined, { needsNewScope: directive.$$isolateScope || directive.$$newScope}); - childTranscludeFn.$$slots = slots; - } - } - - if (directive.template) { - hasTemplate = true; - assertNoDuplicate('template', templateDirective, directive, $compileNode); - templateDirective = directive; - - directiveValue = (isFunction(directive.template)) - ? directive.template($compileNode, templateAttrs) - : directive.template; - - directiveValue = denormalizeTemplate(directiveValue); - - if (directive.replace) { - replaceDirective = directive; - if (jqLiteIsTextNode(directiveValue)) { - $template = []; - } else { - $template = removeComments(wrapTemplate(directive.templateNamespace, trim(directiveValue))); - } - compileNode = $template[0]; - - if ($template.length !== 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { - throw $compileMinErr('tplrt', - 'Template for directive \'{0}\' must have exactly one root element. {1}', - directiveName, ''); - } - - replaceWith(jqCollection, $compileNode, compileNode); - - var newTemplateAttrs = {$attr: {}}; - - // combine directives from the original node and from the template: - // - take the array of directives for this element - // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed) - // - collect directives from the template and sort them by priority - // - combine directives as: processed + template + unprocessed - var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs); - var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1)); - - if (newIsolateScopeDirective || newScopeDirective) { - // The original directive caused the current element to be replaced but this element - // also needs to have a new scope, so we need to tell the template directives - // that they would need to get their scope from further up, if they require transclusion - markDirectiveScope(templateDirectives, newIsolateScopeDirective, newScopeDirective); - } - directives = directives.concat(templateDirectives).concat(unprocessedDirectives); - mergeTemplateAttributes(templateAttrs, newTemplateAttrs); - - ii = directives.length; - } else { - $compileNode.html(directiveValue); - } - } - - if (directive.templateUrl) { - hasTemplate = true; - assertNoDuplicate('template', templateDirective, directive, $compileNode); - templateDirective = directive; - - if (directive.replace) { - replaceDirective = directive; - } - - // eslint-disable-next-line no-func-assign - nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode, - templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, { - controllerDirectives: controllerDirectives, - newScopeDirective: (newScopeDirective !== directive) && newScopeDirective, - newIsolateScopeDirective: newIsolateScopeDirective, - templateDirective: templateDirective, - nonTlbTranscludeDirective: nonTlbTranscludeDirective - }); - ii = directives.length; - } else if (directive.compile) { - try { - linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); - var context = directive.$$originalDirective || directive; - if (isFunction(linkFn)) { - addLinkFns(null, bind(context, linkFn), attrStart, attrEnd); - } else if (linkFn) { - addLinkFns(bind(context, linkFn.pre), bind(context, linkFn.post), attrStart, attrEnd); - } - } catch (e) { - $exceptionHandler(e, startingTag($compileNode)); - } - } - - if (directive.terminal) { - nodeLinkFn.terminal = true; - terminalPriority = Math.max(terminalPriority, directive.priority); - } - - } - - nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; - nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective; - nodeLinkFn.templateOnThisElement = hasTemplate; - nodeLinkFn.transclude = childTranscludeFn; - - previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective; - - // might be normal or delayed nodeLinkFn depending on if templateUrl is present - return nodeLinkFn; - - //////////////////// - - function addLinkFns(pre, post, attrStart, attrEnd) { - if (pre) { - if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd); - pre.require = directive.require; - pre.directiveName = directiveName; - if (newIsolateScopeDirective === directive || directive.$$isolateScope) { - pre = cloneAndAnnotateFn(pre, {isolateScope: true}); - } - preLinkFns.push(pre); - } - if (post) { - if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd); - post.require = directive.require; - post.directiveName = directiveName; - if (newIsolateScopeDirective === directive || directive.$$isolateScope) { - post = cloneAndAnnotateFn(post, {isolateScope: true}); - } - postLinkFns.push(post); - } - } - - function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) { - var i, ii, linkFn, isolateScope, controllerScope, elementControllers, transcludeFn, $element, - attrs, scopeBindingInfo; - - if (compileNode === linkNode) { - attrs = templateAttrs; - $element = templateAttrs.$$element; - } else { - $element = jqLite(linkNode); - attrs = new Attributes($element, templateAttrs); - } - - controllerScope = scope; - if (newIsolateScopeDirective) { - isolateScope = scope.$new(true); - } else if (newScopeDirective) { - controllerScope = scope.$parent; - } - - if (boundTranscludeFn) { - // track `boundTranscludeFn` so it can be unwrapped if `transcludeFn` - // is later passed as `parentBoundTranscludeFn` to `publicLinkFn` - transcludeFn = controllersBoundTransclude; - transcludeFn.$$boundTransclude = boundTranscludeFn; - // expose the slots on the `$transclude` function - transcludeFn.isSlotFilled = function(slotName) { - return !!boundTranscludeFn.$$slots[slotName]; - }; - } - - if (controllerDirectives) { - elementControllers = setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective); - } - - if (newIsolateScopeDirective) { - // Initialize isolate scope bindings for new isolate scope directive. - compile.$$addScopeInfo($element, isolateScope, true, !(templateDirective && (templateDirective === newIsolateScopeDirective || - templateDirective === newIsolateScopeDirective.$$originalDirective))); - compile.$$addScopeClass($element, true); - isolateScope.$$isolateBindings = - newIsolateScopeDirective.$$isolateBindings; - scopeBindingInfo = initializeDirectiveBindings(scope, attrs, isolateScope, - isolateScope.$$isolateBindings, - newIsolateScopeDirective); - if (scopeBindingInfo.removeWatches) { - isolateScope.$on('$destroy', scopeBindingInfo.removeWatches); - } - } - - // Initialize bindToController bindings - for (var name in elementControllers) { - var controllerDirective = controllerDirectives[name]; - var controller = elementControllers[name]; - var bindings = controllerDirective.$$bindings.bindToController; - - controller.instance = controller(); - $element.data('$' + controllerDirective.name + 'Controller', controller.instance); - controller.bindingInfo = - initializeDirectiveBindings(controllerScope, attrs, controller.instance, bindings, controllerDirective); - } - - // Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy - forEach(controllerDirectives, function(controllerDirective, name) { - var require = controllerDirective.require; - if (controllerDirective.bindToController && !isArray(require) && isObject(require)) { - extend(elementControllers[name].instance, getControllers(name, require, $element, elementControllers)); - } - }); - - // Handle the init and destroy lifecycle hooks on all controllers that have them - forEach(elementControllers, function(controller) { - var controllerInstance = controller.instance; - if (isFunction(controllerInstance.$onChanges)) { - try { - controllerInstance.$onChanges(controller.bindingInfo.initialChanges); - } catch (e) { - $exceptionHandler(e); - } - } - if (isFunction(controllerInstance.$onInit)) { - try { - controllerInstance.$onInit(); - } catch (e) { - $exceptionHandler(e); - } - } - if (isFunction(controllerInstance.$doCheck)) { - controllerScope.$watch(function() { controllerInstance.$doCheck(); }); - controllerInstance.$doCheck(); - } - if (isFunction(controllerInstance.$onDestroy)) { - controllerScope.$on('$destroy', function callOnDestroyHook() { - controllerInstance.$onDestroy(); - }); - } - }); - - // PRELINKING - for (i = 0, ii = preLinkFns.length; i < ii; i++) { - linkFn = preLinkFns[i]; - invokeLinkFn(linkFn, - linkFn.isolateScope ? isolateScope : scope, - $element, - attrs, - linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), - transcludeFn - ); - } - - // RECURSION - // We only pass the isolate scope, if the isolate directive has a template, - // otherwise the child elements do not belong to the isolate directive. - var scopeToChild = scope; - if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) { - scopeToChild = isolateScope; - } - if (childLinkFn) { - childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn); - } - - // POSTLINKING - for (i = postLinkFns.length - 1; i >= 0; i--) { - linkFn = postLinkFns[i]; - invokeLinkFn(linkFn, - linkFn.isolateScope ? isolateScope : scope, - $element, - attrs, - linkFn.require && getControllers(linkFn.directiveName, linkFn.require, $element, elementControllers), - transcludeFn - ); - } - - // Trigger $postLink lifecycle hooks - forEach(elementControllers, function(controller) { - var controllerInstance = controller.instance; - if (isFunction(controllerInstance.$postLink)) { - controllerInstance.$postLink(); - } - }); - - // This is the function that is injected as `$transclude`. - // Note: all arguments are optional! - function controllersBoundTransclude(scope, cloneAttachFn, futureParentElement, slotName) { - var transcludeControllers; - // No scope passed in: - if (!isScope(scope)) { - slotName = futureParentElement; - futureParentElement = cloneAttachFn; - cloneAttachFn = scope; - scope = undefined; - } - - if (hasElementTranscludeDirective) { - transcludeControllers = elementControllers; - } - if (!futureParentElement) { - futureParentElement = hasElementTranscludeDirective ? $element.parent() : $element; - } - if (slotName) { - // slotTranscludeFn can be one of three things: - // * a transclude function - a filled slot - // * `null` - an optional slot that was not filled - // * `undefined` - a slot that was not declared (i.e. invalid) - var slotTranscludeFn = boundTranscludeFn.$$slots[slotName]; - if (slotTranscludeFn) { - return slotTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); - } else if (isUndefined(slotTranscludeFn)) { - throw $compileMinErr('noslot', - 'No parent directive that requires a transclusion with slot name "{0}". ' + - 'Element: {1}', - slotName, startingTag($element)); - } - } else { - return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers, futureParentElement, scopeToChild); - } - } - } - } - - function getControllers(directiveName, require, $element, elementControllers) { - var value; - - if (isString(require)) { - var match = require.match(REQUIRE_PREFIX_REGEXP); - var name = require.substring(match[0].length); - var inheritType = match[1] || match[3]; - var optional = match[2] === '?'; - - //If only parents then start at the parent element - if (inheritType === '^^') { - $element = $element.parent(); - //Otherwise attempt getting the controller from elementControllers in case - //the element is transcluded (and has no data) and to avoid .data if possible - } else { - value = elementControllers && elementControllers[name]; - value = value && value.instance; - } - - if (!value) { - var dataName = '$' + name + 'Controller'; - - if (inheritType === '^^' && $element[0] && $element[0].nodeType === NODE_TYPE_DOCUMENT) { - // inheritedData() uses the documentElement when it finds the document, so we would - // require from the element itself. - value = null; - } else { - value = inheritType ? $element.inheritedData(dataName) : $element.data(dataName); - } - } - - if (!value && !optional) { - throw $compileMinErr('ctreq', - 'Controller \'{0}\', required by directive \'{1}\', can\'t be found!', - name, directiveName); - } - } else if (isArray(require)) { - value = []; - for (var i = 0, ii = require.length; i < ii; i++) { - value[i] = getControllers(directiveName, require[i], $element, elementControllers); - } - } else if (isObject(require)) { - value = {}; - forEach(require, function(controller, property) { - value[property] = getControllers(directiveName, controller, $element, elementControllers); - }); - } - - return value || null; - } - - function setupControllers($element, attrs, transcludeFn, controllerDirectives, isolateScope, scope, newIsolateScopeDirective) { - var elementControllers = createMap(); - for (var controllerKey in controllerDirectives) { - var directive = controllerDirectives[controllerKey]; - var locals = { - $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, - $element: $element, - $attrs: attrs, - $transclude: transcludeFn - }; - - var controller = directive.controller; - if (controller === '@') { - controller = attrs[directive.name]; - } - - var controllerInstance = $controller(controller, locals, true, directive.controllerAs); - - // For directives with element transclusion the element is a comment. - // In this case .data will not attach any data. - // Instead, we save the controllers for the element in a local hash and attach to .data - // later, once we have the actual element. - elementControllers[directive.name] = controllerInstance; - $element.data('$' + directive.name + 'Controller', controllerInstance.instance); - } - return elementControllers; - } - - // Depending upon the context in which a directive finds itself it might need to have a new isolated - // or child scope created. For instance: - // * if the directive has been pulled into a template because another directive with a higher priority - // asked for element transclusion - // * if the directive itself asks for transclusion but it is at the root of a template and the original - // element was replaced. See https://github.com/angular/angular.js/issues/12936 - function markDirectiveScope(directives, isolateScope, newScope) { - for (var j = 0, jj = directives.length; j < jj; j++) { - directives[j] = inherit(directives[j], {$$isolateScope: isolateScope, $$newScope: newScope}); - } - } - - /** - * looks up the directive and decorates it with exception handling and proper parameters. We - * call this the boundDirective. - * - * @param {string} name name of the directive to look up. - * @param {string} location The directive must be found in specific format. - * String containing any of theses characters: - * - * * `E`: element name - * * `A': attribute - * * `C`: class - * * `M`: comment - * @returns {boolean} true if directive was added. - */ - function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName, - endAttrName) { - if (name === ignoreDirective) return null; - var match = null; - if (hasDirectives.hasOwnProperty(name)) { - for (var directive, directives = $injector.get(name + Suffix), - i = 0, ii = directives.length; i < ii; i++) { - directive = directives[i]; - if ((isUndefined(maxPriority) || maxPriority > directive.priority) && - directive.restrict.indexOf(location) !== -1) { - if (startAttrName) { - directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName}); - } - if (!directive.$$bindings) { - var bindings = directive.$$bindings = - parseDirectiveBindings(directive, directive.name); - if (isObject(bindings.isolateScope)) { - directive.$$isolateBindings = bindings.isolateScope; - } - } - tDirectives.push(directive); - match = directive; - } - } - } - return match; - } - - - /** - * looks up the directive and returns true if it is a multi-element directive, - * and therefore requires DOM nodes between -start and -end markers to be grouped - * together. - * - * @param {string} name name of the directive to look up. - * @returns true if directive was registered as multi-element. - */ - function directiveIsMultiElement(name) { - if (hasDirectives.hasOwnProperty(name)) { - for (var directive, directives = $injector.get(name + Suffix), - i = 0, ii = directives.length; i < ii; i++) { - directive = directives[i]; - if (directive.multiElement) { - return true; - } - } - } - return false; - } - - /** - * When the element is replaced with HTML template then the new attributes - * on the template need to be merged with the existing attributes in the DOM. - * The desired effect is to have both of the attributes present. - * - * @param {object} dst destination attributes (original DOM) - * @param {object} src source attributes (from the directive template) - */ - function mergeTemplateAttributes(dst, src) { - var srcAttr = src.$attr, - dstAttr = dst.$attr; - - // reapply the old attributes to the new element - forEach(dst, function(value, key) { - if (key.charAt(0) !== '$') { - if (src[key] && src[key] !== value) { - if (value.length) { - value += (key === 'style' ? ';' : ' ') + src[key]; - } else { - value = src[key]; - } - } - dst.$set(key, value, true, srcAttr[key]); - } - }); - - // copy the new attributes on the old attrs object - forEach(src, function(value, key) { - // Check if we already set this attribute in the loop above. - // `dst` will never contain hasOwnProperty as DOM parser won't let it. - // You will get an "InvalidCharacterError: DOM Exception 5" error if you - // have an attribute like "has-own-property" or "data-has-own-property", etc. - if (!dst.hasOwnProperty(key) && key.charAt(0) !== '$') { - dst[key] = value; - - if (key !== 'class' && key !== 'style') { - dstAttr[key] = srcAttr[key]; - } - } - }); - } - - - function compileTemplateUrl(directives, $compileNode, tAttrs, - $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) { - var linkQueue = [], - afterTemplateNodeLinkFn, - afterTemplateChildLinkFn, - beforeTemplateCompileNode = $compileNode[0], - origAsyncDirective = directives.shift(), - derivedSyncDirective = inherit(origAsyncDirective, { - templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective - }), - templateUrl = (isFunction(origAsyncDirective.templateUrl)) - ? origAsyncDirective.templateUrl($compileNode, tAttrs) - : origAsyncDirective.templateUrl, - templateNamespace = origAsyncDirective.templateNamespace; - - $compileNode.empty(); - - $templateRequest(templateUrl) - .then(function(content) { - var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn; - - content = denormalizeTemplate(content); - - if (origAsyncDirective.replace) { - if (jqLiteIsTextNode(content)) { - $template = []; - } else { - $template = removeComments(wrapTemplate(templateNamespace, trim(content))); - } - compileNode = $template[0]; - - if ($template.length !== 1 || compileNode.nodeType !== NODE_TYPE_ELEMENT) { - throw $compileMinErr('tplrt', - 'Template for directive \'{0}\' must have exactly one root element. {1}', - origAsyncDirective.name, templateUrl); - } - - tempTemplateAttrs = {$attr: {}}; - replaceWith($rootElement, $compileNode, compileNode); - var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs); - - if (isObject(origAsyncDirective.scope)) { - // the original directive that caused the template to be loaded async required - // an isolate scope - markDirectiveScope(templateDirectives, true); - } - directives = templateDirectives.concat(directives); - mergeTemplateAttributes(tAttrs, tempTemplateAttrs); - } else { - compileNode = beforeTemplateCompileNode; - $compileNode.html(content); - } - - directives.unshift(derivedSyncDirective); - - afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, - childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns, - previousCompileContext); - forEach($rootElement, function(node, i) { - if (node === compileNode) { - $rootElement[i] = $compileNode[0]; - } - }); - afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn); - - while (linkQueue.length) { - var scope = linkQueue.shift(), - beforeTemplateLinkNode = linkQueue.shift(), - linkRootElement = linkQueue.shift(), - boundTranscludeFn = linkQueue.shift(), - linkNode = $compileNode[0]; - - if (scope.$$destroyed) continue; - - if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { - var oldClasses = beforeTemplateLinkNode.className; - - if (!(previousCompileContext.hasElementTranscludeDirective && - origAsyncDirective.replace)) { - // it was cloned therefore we have to clone as well. - linkNode = jqLiteClone(compileNode); - } - replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); - - // Copy in CSS classes from original node - safeAddClass(jqLite(linkNode), oldClasses); - } - if (afterTemplateNodeLinkFn.transcludeOnThisElement) { - childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); - } else { - childBoundTranscludeFn = boundTranscludeFn; - } - afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, - childBoundTranscludeFn); - } - linkQueue = null; - }).catch(function(error) { - if (isError(error)) { - $exceptionHandler(error); - } - }); - - return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) { - var childBoundTranscludeFn = boundTranscludeFn; - if (scope.$$destroyed) return; - if (linkQueue) { - linkQueue.push(scope, - node, - rootElement, - childBoundTranscludeFn); - } else { - if (afterTemplateNodeLinkFn.transcludeOnThisElement) { - childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude, boundTranscludeFn); - } - afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, childBoundTranscludeFn); - } - }; - } - - - /** - * Sorting function for bound directives. - */ - function byPriority(a, b) { - var diff = b.priority - a.priority; - if (diff !== 0) return diff; - if (a.name !== b.name) return (a.name < b.name) ? -1 : 1; - return a.index - b.index; - } - - function assertNoDuplicate(what, previousDirective, directive, element) { - - function wrapModuleNameIfDefined(moduleName) { - return moduleName ? - (' (module: ' + moduleName + ')') : - ''; - } - - if (previousDirective) { - throw $compileMinErr('multidir', 'Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}', - previousDirective.name, wrapModuleNameIfDefined(previousDirective.$$moduleName), - directive.name, wrapModuleNameIfDefined(directive.$$moduleName), what, startingTag(element)); - } - } - - - function addTextInterpolateDirective(directives, text) { - var interpolateFn = $interpolate(text, true); - if (interpolateFn) { - directives.push({ - priority: 0, - compile: function textInterpolateCompileFn(templateNode) { - var templateNodeParent = templateNode.parent(), - hasCompileParent = !!templateNodeParent.length; - - // When transcluding a template that has bindings in the root - // we don't have a parent and thus need to add the class during linking fn. - if (hasCompileParent) compile.$$addBindingClass(templateNodeParent); - - return function textInterpolateLinkFn(scope, node) { - var parent = node.parent(); - if (!hasCompileParent) compile.$$addBindingClass(parent); - compile.$$addBindingInfo(parent, interpolateFn.expressions); - scope.$watch(interpolateFn, function interpolateFnWatchAction(value) { - node[0].nodeValue = value; - }); - }; - } - }); - } - } - - - function wrapTemplate(type, template) { - type = lowercase(type || 'html'); - switch (type) { - case 'svg': - case 'math': - var wrapper = window.document.createElement('div'); - wrapper.innerHTML = '<' + type + '>' + template + ''; - return wrapper.childNodes[0].childNodes; - default: - return template; - } - } - - - function getTrustedAttrContext(nodeName, attrNormalizedName) { - if (attrNormalizedName === 'srcdoc') { - return $sce.HTML; - } - // All nodes with src attributes require a RESOURCE_URL value, except for - // img and various html5 media nodes, which require the MEDIA_URL context. - if (attrNormalizedName === 'src' || attrNormalizedName === 'ngSrc') { - if (['img', 'video', 'audio', 'source', 'track'].indexOf(nodeName) === -1) { - return $sce.RESOURCE_URL; - } - return $sce.MEDIA_URL; - } else if (attrNormalizedName === 'xlinkHref') { - // Some xlink:href are okay, most aren't - if (nodeName === 'image') return $sce.MEDIA_URL; - if (nodeName === 'a') return $sce.URL; - return $sce.RESOURCE_URL; - } else if ( - // Formaction - (nodeName === 'form' && attrNormalizedName === 'action') || - // If relative URLs can go where they are not expected to, then - // all sorts of trust issues can arise. - (nodeName === 'base' && attrNormalizedName === 'href') || - // links can be stylesheets or imports, which can run script in the current origin - (nodeName === 'link' && attrNormalizedName === 'href') - ) { - return $sce.RESOURCE_URL; - } else if (nodeName === 'a' && (attrNormalizedName === 'href' || - attrNormalizedName === 'ngHref')) { - return $sce.URL; - } - } - - function getTrustedPropContext(nodeName, propNormalizedName) { - var prop = propNormalizedName.toLowerCase(); - return PROP_CONTEXTS[nodeName + '|' + prop] || PROP_CONTEXTS['*|' + prop]; - } - - function sanitizeSrcsetPropertyValue(value) { - return sanitizeSrcset($sce.valueOf(value), 'ng-prop-srcset'); - } - function addPropertyDirective(node, directives, attrName, propName) { - if (EVENT_HANDLER_ATTR_REGEXP.test(propName)) { - throw $compileMinErr('nodomevents', 'Property bindings for HTML DOM event properties are disallowed'); - } - - var nodeName = nodeName_(node); - var trustedContext = getTrustedPropContext(nodeName, propName); - - var sanitizer = identity; - // Sanitize img[srcset] + source[srcset] values. - if (propName === 'srcset' && (nodeName === 'img' || nodeName === 'source')) { - sanitizer = sanitizeSrcsetPropertyValue; - } else if (trustedContext) { - sanitizer = $sce.getTrusted.bind($sce, trustedContext); - } - - directives.push({ - priority: 100, - compile: function ngPropCompileFn(_, attr) { - var ngPropGetter = $parse(attr[attrName]); - var ngPropWatch = $parse(attr[attrName], function sceValueOf(val) { - // Unwrap the value to compare the actual inner safe value, not the wrapper object. - return $sce.valueOf(val); - }); - - return { - pre: function ngPropPreLinkFn(scope, $element) { - function applyPropValue() { - var propValue = ngPropGetter(scope); - $element[0][propName] = sanitizer(propValue); - } - - applyPropValue(); - scope.$watch(ngPropWatch, applyPropValue); - } - }; - } - }); - } - - function addEventDirective(directives, attrName, eventName) { - directives.push( - createEventDirective($parse, $rootScope, $exceptionHandler, attrName, eventName, /*forceAsync=*/false) - ); - } - - function addAttrInterpolateDirective(node, directives, value, name, isNgAttr) { - var nodeName = nodeName_(node); - var trustedContext = getTrustedAttrContext(nodeName, name); - var mustHaveExpression = !isNgAttr; - var allOrNothing = ALL_OR_NOTHING_ATTRS[name] || isNgAttr; - - var interpolateFn = $interpolate(value, mustHaveExpression, trustedContext, allOrNothing); - - // no interpolation found -> ignore - if (!interpolateFn) return; - - if (name === 'multiple' && nodeName === 'select') { - throw $compileMinErr('selmulti', - 'Binding to the \'multiple\' attribute is not supported. Element: {0}', - startingTag(node)); - } - - if (EVENT_HANDLER_ATTR_REGEXP.test(name)) { - throw $compileMinErr('nodomevents', 'Interpolations for HTML DOM event attributes are disallowed'); - } - - directives.push({ - priority: 100, - compile: function() { - return { - pre: function attrInterpolatePreLinkFn(scope, element, attr) { - var $$observers = (attr.$$observers || (attr.$$observers = createMap())); - - // If the attribute has changed since last $interpolate()ed - var newValue = attr[name]; - if (newValue !== value) { - // we need to interpolate again since the attribute value has been updated - // (e.g. by another directive's compile function) - // ensure unset/empty values make interpolateFn falsy - interpolateFn = newValue && $interpolate(newValue, true, trustedContext, allOrNothing); - value = newValue; - } - - // if attribute was updated so that there is no interpolation going on we don't want to - // register any observers - if (!interpolateFn) return; - - // initialize attr object so that it's ready in case we need the value for isolate - // scope initialization, otherwise the value would not be available from isolate - // directive's linking fn during linking phase - attr[name] = interpolateFn(scope); - - ($$observers[name] || ($$observers[name] = [])).$$inter = true; - (attr.$$observers && attr.$$observers[name].$$scope || scope). - $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) { - //special case for class attribute addition + removal - //so that class changes can tap into the animation - //hooks provided by the $animate service. Be sure to - //skip animations when the first digest occurs (when - //both the new and the old values are the same) since - //the CSS classes are the non-interpolated values - if (name === 'class' && newValue !== oldValue) { - attr.$updateClass(newValue, oldValue); - } else { - attr.$set(name, newValue); - } - }); - } - }; - } - }); - } - - - /** - * This is a special jqLite.replaceWith, which can replace items which - * have no parents, provided that the containing jqLite collection is provided. - * - * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes - * in the root of the tree. - * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep - * the shell, but replace its DOM node reference. - * @param {Node} newNode The new DOM node. - */ - function replaceWith($rootElement, elementsToRemove, newNode) { - var firstElementToRemove = elementsToRemove[0], - removeCount = elementsToRemove.length, - parent = firstElementToRemove.parentNode, - i, ii; - - if ($rootElement) { - for (i = 0, ii = $rootElement.length; i < ii; i++) { - if ($rootElement[i] === firstElementToRemove) { - $rootElement[i++] = newNode; - for (var j = i, j2 = j + removeCount - 1, - jj = $rootElement.length; - j < jj; j++, j2++) { - if (j2 < jj) { - $rootElement[j] = $rootElement[j2]; - } else { - delete $rootElement[j]; - } - } - $rootElement.length -= removeCount - 1; - - // If the replaced element is also the jQuery .context then replace it - // .context is a deprecated jQuery api, so we should set it only when jQuery set it - // http://api.jquery.com/context/ - if ($rootElement.context === firstElementToRemove) { - $rootElement.context = newNode; - } - break; - } - } - } - - if (parent) { - parent.replaceChild(newNode, firstElementToRemove); - } - - // Append all the `elementsToRemove` to a fragment. This will... - // - remove them from the DOM - // - allow them to still be traversed with .nextSibling - // - allow a single fragment.qSA to fetch all elements being removed - var fragment = window.document.createDocumentFragment(); - for (i = 0; i < removeCount; i++) { - fragment.appendChild(elementsToRemove[i]); - } - - if (jqLite.hasData(firstElementToRemove)) { - // Copy over user data (that includes AngularJS's $scope etc.). Don't copy private - // data here because there's no public interface in jQuery to do that and copying over - // event listeners (which is the main use of private data) wouldn't work anyway. - jqLite.data(newNode, jqLite.data(firstElementToRemove)); - - // Remove $destroy event listeners from `firstElementToRemove` - jqLite(firstElementToRemove).off('$destroy'); - } - - // Cleanup any data/listeners on the elements and children. - // This includes invoking the $destroy event on any elements with listeners. - jqLite.cleanData(fragment.querySelectorAll('*')); - - // Update the jqLite collection to only contain the `newNode` - for (i = 1; i < removeCount; i++) { - delete elementsToRemove[i]; - } - elementsToRemove[0] = newNode; - elementsToRemove.length = 1; - } - - - function cloneAndAnnotateFn(fn, annotation) { - return extend(function() { return fn.apply(null, arguments); }, fn, annotation); - } - - - function invokeLinkFn(linkFn, scope, $element, attrs, controllers, transcludeFn) { - try { - linkFn(scope, $element, attrs, controllers, transcludeFn); - } catch (e) { - $exceptionHandler(e, startingTag($element)); - } - } - - function strictBindingsCheck(attrName, directiveName) { - if (strictComponentBindingsEnabled) { - throw $compileMinErr('missingattr', - 'Attribute \'{0}\' of \'{1}\' is non-optional and must be set!', - attrName, directiveName); - } - } - - // Set up $watches for isolate scope and controller bindings. - function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) { - var removeWatchCollection = []; - var initialChanges = {}; - var changes; - - forEach(bindings, function initializeBinding(definition, scopeName) { - var attrName = definition.attrName, - optional = definition.optional, - mode = definition.mode, // @, =, <, or & - lastValue, - parentGet, parentSet, compare, removeWatch; - - switch (mode) { - - case '@': - if (!optional && !hasOwnProperty.call(attrs, attrName)) { - strictBindingsCheck(attrName, directive.name); - destination[scopeName] = attrs[attrName] = undefined; - - } - removeWatch = attrs.$observe(attrName, function(value) { - if (isString(value) || isBoolean(value)) { - var oldValue = destination[scopeName]; - recordChanges(scopeName, value, oldValue); - destination[scopeName] = value; - } - }); - attrs.$$observers[attrName].$$scope = scope; - lastValue = attrs[attrName]; - if (isString(lastValue)) { - // If the attribute has been provided then we trigger an interpolation to ensure - // the value is there for use in the link fn - destination[scopeName] = $interpolate(lastValue)(scope); - } else if (isBoolean(lastValue)) { - // If the attributes is one of the BOOLEAN_ATTR then AngularJS will have converted - // the value to boolean rather than a string, so we special case this situation - destination[scopeName] = lastValue; - } - initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]); - removeWatchCollection.push(removeWatch); - break; - - case '=': - if (!hasOwnProperty.call(attrs, attrName)) { - if (optional) break; - strictBindingsCheck(attrName, directive.name); - attrs[attrName] = undefined; - } - if (optional && !attrs[attrName]) break; - - parentGet = $parse(attrs[attrName]); - if (parentGet.literal) { - compare = equals; - } else { - compare = simpleCompare; - } - parentSet = parentGet.assign || function() { - // reset the change, or we will throw this exception on every $digest - lastValue = destination[scopeName] = parentGet(scope); - throw $compileMinErr('nonassign', - 'Expression \'{0}\' in attribute \'{1}\' used with directive \'{2}\' is non-assignable!', - attrs[attrName], attrName, directive.name); - }; - lastValue = destination[scopeName] = parentGet(scope); - var parentValueWatch = function parentValueWatch(parentValue) { - if (!compare(parentValue, destination[scopeName])) { - // we are out of sync and need to copy - if (!compare(parentValue, lastValue)) { - // parent changed and it has precedence - destination[scopeName] = parentValue; - } else { - // if the parent can be assigned then do so - parentSet(scope, parentValue = destination[scopeName]); - } - } - lastValue = parentValue; - return lastValue; - }; - parentValueWatch.$stateful = true; - if (definition.collection) { - removeWatch = scope.$watchCollection(attrs[attrName], parentValueWatch); - } else { - removeWatch = scope.$watch($parse(attrs[attrName], parentValueWatch), null, parentGet.literal); - } - removeWatchCollection.push(removeWatch); - break; - - case '<': - if (!hasOwnProperty.call(attrs, attrName)) { - if (optional) break; - strictBindingsCheck(attrName, directive.name); - attrs[attrName] = undefined; - } - if (optional && !attrs[attrName]) break; - - parentGet = $parse(attrs[attrName]); - var isLiteral = parentGet.literal; - - var initialValue = destination[scopeName] = parentGet(scope); - initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]); - - removeWatch = scope[definition.collection ? '$watchCollection' : '$watch'](parentGet, function parentValueWatchAction(newValue, oldValue) { - if (oldValue === newValue) { - if (oldValue === initialValue || (isLiteral && equals(oldValue, initialValue))) { - return; - } - oldValue = initialValue; - } - recordChanges(scopeName, newValue, oldValue); - destination[scopeName] = newValue; - }); - - removeWatchCollection.push(removeWatch); - break; - - case '&': - if (!optional && !hasOwnProperty.call(attrs, attrName)) { - strictBindingsCheck(attrName, directive.name); - } - // Don't assign Object.prototype method to scope - parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop; - - // Don't assign noop to destination if expression is not valid - if (parentGet === noop && optional) break; - - destination[scopeName] = function(locals) { - return parentGet(scope, locals); - }; - break; - } - }); - - function recordChanges(key, currentValue, previousValue) { - if (isFunction(destination.$onChanges) && !simpleCompare(currentValue, previousValue)) { - // If we have not already scheduled the top level onChangesQueue handler then do so now - if (!onChangesQueue) { - scope.$$postDigest(flushOnChangesQueue); - onChangesQueue = []; - } - // If we have not already queued a trigger of onChanges for this controller then do so now - if (!changes) { - changes = {}; - onChangesQueue.push(triggerOnChangesHook); - } - // If the has been a change on this property already then we need to reuse the previous value - if (changes[key]) { - previousValue = changes[key].previousValue; - } - // Store this change - changes[key] = new SimpleChange(previousValue, currentValue); - } - } - - function triggerOnChangesHook() { - destination.$onChanges(changes); - // Now clear the changes so that we schedule onChanges when more changes arrive - changes = undefined; - } - - return { - initialChanges: initialChanges, - removeWatches: removeWatchCollection.length && function removeWatches() { - for (var i = 0, ii = removeWatchCollection.length; i < ii; ++i) { - removeWatchCollection[i](); - } - } - }; - } - }]; -} - -function SimpleChange(previous, current) { - this.previousValue = previous; - this.currentValue = current; -} -SimpleChange.prototype.isFirstChange = function() { return this.previousValue === _UNINITIALIZED_VALUE; }; - - -var PREFIX_REGEXP = /^((?:x|data)[:\-_])/i; -var SPECIAL_CHARS_REGEXP = /[:\-_]+(.)/g; - -/** - * Converts all accepted directives format into proper directive name. - * @param name Name to normalize - */ -function directiveNormalize(name) { - return name - .replace(PREFIX_REGEXP, '') - .replace(SPECIAL_CHARS_REGEXP, function(_, letter, offset) { - return offset ? letter.toUpperCase() : letter; - }); -} - -/** - * @ngdoc type - * @name $compile.directive.Attributes - * - * @description - * A shared object between directive compile / linking functions which contains normalized DOM - * element attributes. The values reflect current binding state `{{ }}`. The normalization is - * needed since all of these are treated as equivalent in AngularJS: - * - * ``` - * - * ``` - */ - -/** - * @ngdoc property - * @name $compile.directive.Attributes#$attr - * - * @description - * A map of DOM element attribute names to the normalized name. This is - * needed to do reverse lookup from normalized name back to actual name. - */ - - -/** - * @ngdoc method - * @name $compile.directive.Attributes#$set - * @kind function - * - * @description - * Set DOM element attribute value. - * - * - * @param {string} name Normalized element attribute name of the property to modify. The name is - * reverse-translated using the {@link ng.$compile.directive.Attributes#$attr $attr} - * property to the original name. - * @param {string} value Value to set the attribute to. The value can be an interpolated string. - */ - - - -/** - * Closure compiler type information - */ - -function nodesetLinkingFn( - /* angular.Scope */ scope, - /* NodeList */ nodeList, - /* Element */ rootElement, - /* function(Function) */ boundTranscludeFn -) {} - -function directiveLinkingFn( - /* nodesetLinkingFn */ nodesetLinkingFn, - /* angular.Scope */ scope, - /* Node */ node, - /* Element */ rootElement, - /* function(Function) */ boundTranscludeFn -) {} - -function tokenDifference(str1, str2) { - var values = '', - tokens1 = str1.split(/\s+/), - tokens2 = str2.split(/\s+/); - - outer: - for (var i = 0; i < tokens1.length; i++) { - var token = tokens1[i]; - for (var j = 0; j < tokens2.length; j++) { - if (token === tokens2[j]) continue outer; - } - values += (values.length > 0 ? ' ' : '') + token; - } - return values; -} - -function removeComments(jqNodes) { - jqNodes = jqLite(jqNodes); - var i = jqNodes.length; - - if (i <= 1) { - return jqNodes; - } - - while (i--) { - var node = jqNodes[i]; - if (node.nodeType === NODE_TYPE_COMMENT || - (node.nodeType === NODE_TYPE_TEXT && node.nodeValue.trim() === '')) { - splice.call(jqNodes, i, 1); - } - } - return jqNodes; -} - -var $controllerMinErr = minErr('$controller'); - - -var CNTRL_REG = /^(\S+)(\s+as\s+([\w$]+))?$/; -function identifierForController(controller, ident) { - if (ident && isString(ident)) return ident; - if (isString(controller)) { - var match = CNTRL_REG.exec(controller); - if (match) return match[3]; - } -} - - -/** - * @ngdoc provider - * @name $controllerProvider - * @this - * - * @description - * The {@link ng.$controller $controller service} is used by AngularJS to create new - * controllers. - * - * This provider allows controller registration via the - * {@link ng.$controllerProvider#register register} method. - */ -function $ControllerProvider() { - var controllers = {}; - - /** - * @ngdoc method - * @name $controllerProvider#has - * @param {string} name Controller name to check. - */ - this.has = function(name) { - return controllers.hasOwnProperty(name); - }; - - /** - * @ngdoc method - * @name $controllerProvider#register - * @param {string|Object} name Controller name, or an object map of controllers where the keys are - * the names and the values are the constructors. - * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI - * annotations in the array notation). - */ - this.register = function(name, constructor) { - assertNotHasOwnProperty(name, 'controller'); - if (isObject(name)) { - extend(controllers, name); - } else { - controllers[name] = constructor; - } - }; - - this.$get = ['$injector', function($injector) { - - /** - * @ngdoc service - * @name $controller - * @requires $injector - * - * @param {Function|string} constructor If called with a function then it's considered to be the - * controller constructor function. Otherwise it's considered to be a string which is used - * to retrieve the controller constructor using the following steps: - * - * * check if a controller with given name is registered via `$controllerProvider` - * * check if evaluating the string on the current scope returns a constructor - * - * The string can use the `controller as property` syntax, where the controller instance is published - * as the specified property on the `scope`; the `scope` must be injected into `locals` param for this - * to work correctly. - * - * @param {Object} locals Injection locals for Controller. - * @return {Object} Instance of given controller. - * - * @description - * `$controller` service is responsible for instantiating controllers. - * - * It's just a simple call to {@link auto.$injector $injector}, but extracted into - * a service, so that one can override this service with [BC version](https://gist.github.com/1649788). - */ - return function $controller(expression, locals, later, ident) { - // PRIVATE API: - // param `later` --- indicates that the controller's constructor is invoked at a later time. - // If true, $controller will allocate the object with the correct - // prototype chain, but will not invoke the controller until a returned - // callback is invoked. - // param `ident` --- An optional label which overrides the label parsed from the controller - // expression, if any. - var instance, match, constructor, identifier; - later = later === true; - if (ident && isString(ident)) { - identifier = ident; - } - - if (isString(expression)) { - match = expression.match(CNTRL_REG); - if (!match) { - throw $controllerMinErr('ctrlfmt', - 'Badly formed controller string \'{0}\'. ' + - 'Must match `__name__ as __id__` or `__name__`.', expression); - } - constructor = match[1]; - identifier = identifier || match[3]; - expression = controllers.hasOwnProperty(constructor) - ? controllers[constructor] - : getter(locals.$scope, constructor, true); - - if (!expression) { - throw $controllerMinErr('ctrlreg', - 'The controller with the name \'{0}\' is not registered.', constructor); - } - - assertArgFn(expression, constructor, true); - } - - if (later) { - // Instantiate controller later: - // This machinery is used to create an instance of the object before calling the - // controller's constructor itself. - // - // This allows properties to be added to the controller before the constructor is - // invoked. Primarily, this is used for isolate scope bindings in $compile. - // - // This feature is not intended for use by applications, and is thus not documented - // publicly. - // Object creation: http://jsperf.com/create-constructor/2 - var controllerPrototype = (isArray(expression) ? - expression[expression.length - 1] : expression).prototype; - instance = Object.create(controllerPrototype || null); - - if (identifier) { - addIdentifier(locals, identifier, instance, constructor || expression.name); - } - - return extend(function $controllerInit() { - var result = $injector.invoke(expression, instance, locals, constructor); - if (result !== instance && (isObject(result) || isFunction(result))) { - instance = result; - if (identifier) { - // If result changed, re-assign controllerAs value to scope. - addIdentifier(locals, identifier, instance, constructor || expression.name); - } - } - return instance; - }, { - instance: instance, - identifier: identifier - }); - } - - instance = $injector.instantiate(expression, locals, constructor); - - if (identifier) { - addIdentifier(locals, identifier, instance, constructor || expression.name); - } - - return instance; - }; - - function addIdentifier(locals, identifier, instance, name) { - if (!(locals && isObject(locals.$scope))) { - throw minErr('$controller')('noscp', - 'Cannot export controller \'{0}\' as \'{1}\'! No $scope object provided via `locals`.', - name, identifier); - } - - locals.$scope[identifier] = instance; - } - }]; -} - -/** - * @ngdoc service - * @name $document - * @requires $window - * @this - * - * @description - * A {@link angular.element jQuery or jqLite} wrapper for the browser's `window.document` object. - * - * @example - - -
    -

    $document title:

    -

    window.document title:

    -
    -
    - - angular.module('documentExample', []) - .controller('ExampleController', ['$scope', '$document', function($scope, $document) { - $scope.title = $document[0].title; - $scope.windowTitle = angular.element(window.document)[0].title; - }]); - -
    - */ -function $DocumentProvider() { - this.$get = ['$window', function(window) { - return jqLite(window.document); - }]; -} - - -/** - * @private - * @this - * Listens for document visibility change and makes the current status accessible. - */ -function $$IsDocumentHiddenProvider() { - this.$get = ['$document', '$rootScope', function($document, $rootScope) { - var doc = $document[0]; - var hidden = doc && doc.hidden; - - $document.on('visibilitychange', changeListener); - - $rootScope.$on('$destroy', function() { - $document.off('visibilitychange', changeListener); - }); - - function changeListener() { - hidden = doc.hidden; - } - - return function() { - return hidden; - }; - }]; -} - -/** - * @ngdoc service - * @name $exceptionHandler - * @requires ng.$log - * @this - * - * @description - * Any uncaught exception in AngularJS expressions is delegated to this service. - * The default implementation simply delegates to `$log.error` which logs it into - * the browser console. - * - * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by - * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing. - * - * ## Example: - * - * The example below will overwrite the default `$exceptionHandler` in order to (a) log uncaught - * errors to the backend for later inspection by the developers and (b) to use `$log.warn()` instead - * of `$log.error()`. - * - * ```js - * angular. - * module('exceptionOverwrite', []). - * factory('$exceptionHandler', ['$log', 'logErrorsToBackend', function($log, logErrorsToBackend) { - * return function myExceptionHandler(exception, cause) { - * logErrorsToBackend(exception, cause); - * $log.warn(exception, cause); - * }; - * }]); - * ``` - * - *
    - * Note, that code executed in event-listeners (even those registered using jqLite's `on`/`bind` - * methods) does not delegate exceptions to the {@link ng.$exceptionHandler $exceptionHandler} - * (unless executed during a digest). - * - * If you wish, you can manually delegate exceptions, e.g. - * `try { ... } catch(e) { $exceptionHandler(e); }` - * - * @param {Error} exception Exception associated with the error. - * @param {string=} cause Optional information about the context in which - * the error was thrown. - * - */ -function $ExceptionHandlerProvider() { - this.$get = ['$log', function($log) { - return function(exception, cause) { - $log.error.apply($log, arguments); - }; - }]; -} - -var $$ForceReflowProvider = /** @this */ function() { - this.$get = ['$document', function($document) { - return function(domNode) { - //the line below will force the browser to perform a repaint so - //that all the animated elements within the animation frame will - //be properly updated and drawn on screen. This is required to - //ensure that the preparation animation is properly flushed so that - //the active state picks up from there. DO NOT REMOVE THIS LINE. - //DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH - //WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND - //WILL TAKE YEARS AWAY FROM YOUR LIFE. - if (domNode) { - if (!domNode.nodeType && domNode instanceof jqLite) { - domNode = domNode[0]; - } - } else { - domNode = $document[0].body; - } - return domNode.offsetWidth + 1; - }; - }]; -}; - -var APPLICATION_JSON = 'application/json'; -var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'}; -var JSON_START = /^\[|^\{(?!\{)/; -var JSON_ENDS = { - '[': /]$/, - '{': /}$/ -}; -var JSON_PROTECTION_PREFIX = /^\)]\}',?\n/; -var $httpMinErr = minErr('$http'); - -function serializeValue(v) { - if (isObject(v)) { - return isDate(v) ? v.toISOString() : toJson(v); - } - return v; -} - - -/** @this */ -function $HttpParamSerializerProvider() { - /** - * @ngdoc service - * @name $httpParamSerializer - * @description - * - * Default {@link $http `$http`} params serializer that converts objects to strings - * according to the following rules: - * - * * `{'foo': 'bar'}` results in `foo=bar` - * * `{'foo': Date.now()}` results in `foo=2015-04-01T09%3A50%3A49.262Z` (`toISOString()` and encoded representation of a Date object) - * * `{'foo': ['bar', 'baz']}` results in `foo=bar&foo=baz` (repeated key for each array element) - * * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D` (stringified and encoded representation of an object) - * - * Note that serializer will sort the request parameters alphabetically. - */ - - this.$get = function() { - return function ngParamSerializer(params) { - if (!params) return ''; - var parts = []; - forEachSorted(params, function(value, key) { - if (value === null || isUndefined(value) || isFunction(value)) return; - if (isArray(value)) { - forEach(value, function(v) { - parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(v))); - }); - } else { - parts.push(encodeUriQuery(key) + '=' + encodeUriQuery(serializeValue(value))); - } - }); - - return parts.join('&'); - }; - }; -} - -/** @this */ -function $HttpParamSerializerJQLikeProvider() { - /** - * @ngdoc service - * @name $httpParamSerializerJQLike - * - * @description - * - * Alternative {@link $http `$http`} params serializer that follows - * jQuery's [`param()`](http://api.jquery.com/jquery.param/) method logic. - * The serializer will also sort the params alphabetically. - * - * To use it for serializing `$http` request parameters, set it as the `paramSerializer` property: - * - * ```js - * $http({ - * url: myUrl, - * method: 'GET', - * params: myParams, - * paramSerializer: '$httpParamSerializerJQLike' - * }); - * ``` - * - * It is also possible to set it as the default `paramSerializer` in the - * {@link $httpProvider#defaults `$httpProvider`}. - * - * Additionally, you can inject the serializer and use it explicitly, for example to serialize - * form data for submission: - * - * ```js - * .controller(function($http, $httpParamSerializerJQLike) { - * //... - * - * $http({ - * url: myUrl, - * method: 'POST', - * data: $httpParamSerializerJQLike(myData), - * headers: { - * 'Content-Type': 'application/x-www-form-urlencoded' - * } - * }); - * - * }); - * ``` - * - */ - this.$get = function() { - return function jQueryLikeParamSerializer(params) { - if (!params) return ''; - var parts = []; - serialize(params, '', true); - return parts.join('&'); - - function serialize(toSerialize, prefix, topLevel) { - if (isArray(toSerialize)) { - forEach(toSerialize, function(value, index) { - serialize(value, prefix + '[' + (isObject(value) ? index : '') + ']'); - }); - } else if (isObject(toSerialize) && !isDate(toSerialize)) { - forEachSorted(toSerialize, function(value, key) { - serialize(value, prefix + - (topLevel ? '' : '[') + - key + - (topLevel ? '' : ']')); - }); - } else { - if (isFunction(toSerialize)) { - toSerialize = toSerialize(); - } - parts.push(encodeUriQuery(prefix) + '=' + - (toSerialize == null ? '' : encodeUriQuery(serializeValue(toSerialize)))); - } - } - }; - }; -} - -function defaultHttpResponseTransform(data, headers) { - if (isString(data)) { - // Strip json vulnerability protection prefix and trim whitespace - var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim(); - - if (tempData) { - var contentType = headers('Content-Type'); - var hasJsonContentType = contentType && (contentType.indexOf(APPLICATION_JSON) === 0); - - if (hasJsonContentType || isJsonLike(tempData)) { - try { - data = fromJson(tempData); - } catch (e) { - if (!hasJsonContentType) { - return data; - } - throw $httpMinErr('baddata', 'Data must be a valid JSON object. Received: "{0}". ' + - 'Parse error: "{1}"', data, e); - } - } - } - } - - return data; -} - -function isJsonLike(str) { - var jsonStart = str.match(JSON_START); - return jsonStart && JSON_ENDS[jsonStart[0]].test(str); -} - -/** - * Parse headers into key value object - * - * @param {string} headers Raw headers as a string - * @returns {Object} Parsed headers as key value object - */ -function parseHeaders(headers) { - var parsed = createMap(), i; - - function fillInParsed(key, val) { - if (key) { - parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; - } - } - - if (isString(headers)) { - forEach(headers.split('\n'), function(line) { - i = line.indexOf(':'); - fillInParsed(lowercase(trim(line.substr(0, i))), trim(line.substr(i + 1))); - }); - } else if (isObject(headers)) { - forEach(headers, function(headerVal, headerKey) { - fillInParsed(lowercase(headerKey), trim(headerVal)); - }); - } - - return parsed; -} - - -/** - * Returns a function that provides access to parsed headers. - * - * Headers are lazy parsed when first requested. - * @see parseHeaders - * - * @param {(string|Object)} headers Headers to provide access to. - * @returns {function(string=)} Returns a getter function which if called with: - * - * - if called with an argument returns a single header value or null - * - if called with no arguments returns an object containing all headers. - */ -function headersGetter(headers) { - var headersObj; - - return function(name) { - if (!headersObj) headersObj = parseHeaders(headers); - - if (name) { - var value = headersObj[lowercase(name)]; - if (value === undefined) { - value = null; - } - return value; - } - - return headersObj; - }; -} - - -/** - * Chain all given functions - * - * This function is used for both request and response transforming - * - * @param {*} data Data to transform. - * @param {function(string=)} headers HTTP headers getter fn. - * @param {number} status HTTP status code of the response. - * @param {(Function|Array.)} fns Function or an array of functions. - * @returns {*} Transformed data. - */ -function transformData(data, headers, status, fns) { - if (isFunction(fns)) { - return fns(data, headers, status); - } - - forEach(fns, function(fn) { - data = fn(data, headers, status); - }); - - return data; -} - - -function isSuccess(status) { - return 200 <= status && status < 300; -} - - -/** - * @ngdoc provider - * @name $httpProvider - * @this - * - * @description - * Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service. - */ -function $HttpProvider() { - /** - * @ngdoc property - * @name $httpProvider#defaults - * @description - * - * Object containing default values for all {@link ng.$http $http} requests. - * - * - **`defaults.cache`** - {boolean|Object} - A boolean value or object created with - * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of HTTP responses - * by default. See {@link $http#caching $http Caching} for more information. - * - * - **`defaults.headers`** - {Object} - Default headers for all $http requests. - * Refer to {@link ng.$http#setting-http-headers $http} for documentation on - * setting default headers. - * - **`defaults.headers.common`** - * - **`defaults.headers.post`** - * - **`defaults.headers.put`** - * - **`defaults.headers.patch`** - * - * - **`defaults.jsonpCallbackParam`** - `{string}` - the name of the query parameter that passes the name of the - * callback in a JSONP request. The value of this parameter will be replaced with the expression generated by the - * {@link $jsonpCallbacks} service. Defaults to `'callback'`. - * - * - **`defaults.paramSerializer`** - `{string|function(Object):string}` - A function - * used to the prepare string representation of request parameters (specified as an object). - * If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}. - * Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}. - * - * - **`defaults.transformRequest`** - - * `{Array|function(data, headersGetter)}` - - * An array of functions (or a single function) which are applied to the request data. - * By default, this is an array with one request transformation function: - * - * - If the `data` property of the request configuration object contains an object, serialize it - * into JSON format. - * - * - **`defaults.transformResponse`** - - * `{Array|function(data, headersGetter, status)}` - - * An array of functions (or a single function) which are applied to the response data. By default, - * this is an array which applies one response transformation function that does two things: - * - * - If XSRF prefix is detected, strip it - * (see {@link ng.$http#security-considerations Security Considerations in the $http docs}). - * - If the `Content-Type` is `application/json` or the response looks like JSON, - * deserialize it using a JSON parser. - * - * - **`defaults.xsrfCookieName`** - {string} - Name of cookie containing the XSRF token. - * Defaults value is `'XSRF-TOKEN'`. - * - * - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the - * XSRF token. Defaults value is `'X-XSRF-TOKEN'`. - * - */ - var defaults = this.defaults = { - // transform incoming response data - transformResponse: [defaultHttpResponseTransform], - - // transform outgoing request data - transformRequest: [function(d) { - return isObject(d) && !isFile(d) && !isBlob(d) && !isFormData(d) ? toJson(d) : d; - }], - - // default headers - headers: { - common: { - 'Accept': 'application/json, text/plain, */*' - }, - post: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), - put: shallowCopy(CONTENT_TYPE_APPLICATION_JSON), - patch: shallowCopy(CONTENT_TYPE_APPLICATION_JSON) - }, - - xsrfCookieName: 'XSRF-TOKEN', - xsrfHeaderName: 'X-XSRF-TOKEN', - - paramSerializer: '$httpParamSerializer', - - jsonpCallbackParam: 'callback' - }; - - var useApplyAsync = false; - /** - * @ngdoc method - * @name $httpProvider#useApplyAsync - * @description - * - * Configure $http service to combine processing of multiple http responses received at around - * the same time via {@link ng.$rootScope.Scope#$applyAsync $rootScope.$applyAsync}. This can result in - * significant performance improvement for bigger applications that make many HTTP requests - * concurrently (common during application bootstrap). - * - * Defaults to false. If no value is specified, returns the current configured value. - * - * @param {boolean=} value If true, when requests are loaded, they will schedule a deferred - * "apply" on the next tick, giving time for subsequent requests in a roughly ~10ms window - * to load and share the same digest cycle. - * - * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining. - * otherwise, returns the current configured value. - */ - this.useApplyAsync = function(value) { - if (isDefined(value)) { - useApplyAsync = !!value; - return this; - } - return useApplyAsync; - }; - - /** - * @ngdoc property - * @name $httpProvider#interceptors - * @description - * - * Array containing service factories for all synchronous or asynchronous {@link ng.$http $http} - * pre-processing of request or postprocessing of responses. - * - * These service factories are ordered by request, i.e. they are applied in the same order as the - * array, on request, but reverse order, on response. - * - * {@link ng.$http#interceptors Interceptors detailed info} - */ - var interceptorFactories = this.interceptors = []; - - /** - * @ngdoc property - * @name $httpProvider#xsrfWhitelistedOrigins - * @description - * - * Array containing URLs whose origins are trusted to receive the XSRF token. See the - * {@link ng.$http#security-considerations Security Considerations} sections for more details on - * XSRF. - * - * **Note:** An "origin" consists of the [URI scheme](https://en.wikipedia.org/wiki/URI_scheme), - * the [hostname](https://en.wikipedia.org/wiki/Hostname) and the - * [port number](https://en.wikipedia.org/wiki/Port_(computer_networking). For `http:` and - * `https:`, the port number can be omitted if using th default ports (80 and 443 respectively). - * Examples: `http://example.com`, `https://api.example.com:9876` - * - *
    - * It is not possible to whitelist specific URLs/paths. The `path`, `query` and `fragment` parts - * of a URL will be ignored. For example, `https://foo.com/path/bar?query=baz#fragment` will be - * treated as `https://foo.com`, meaning that **all** requests to URLs starting with - * `https://foo.com/` will include the XSRF token. - *
    - * - * @example - * - * ```js - * // App served from `https://example.com/`. - * angular. - * module('xsrfWhitelistedOriginsExample', []). - * config(['$httpProvider', function($httpProvider) { - * $httpProvider.xsrfWhitelistedOrigins.push('https://api.example.com'); - * }]). - * run(['$http', function($http) { - * // The XSRF token will be sent. - * $http.get('https://api.example.com/preferences').then(...); - * - * // The XSRF token will NOT be sent. - * $http.get('https://stats.example.com/activity').then(...); - * }]); - * ``` - */ - var xsrfWhitelistedOrigins = this.xsrfWhitelistedOrigins = []; - - this.$get = ['$browser', '$httpBackend', '$$cookieReader', '$cacheFactory', '$rootScope', '$q', '$injector', '$sce', - function($browser, $httpBackend, $$cookieReader, $cacheFactory, $rootScope, $q, $injector, $sce) { - - var defaultCache = $cacheFactory('$http'); - - /** - * Make sure that default param serializer is exposed as a function - */ - defaults.paramSerializer = isString(defaults.paramSerializer) ? - $injector.get(defaults.paramSerializer) : defaults.paramSerializer; - - /** - * Interceptors stored in reverse order. Inner interceptors before outer interceptors. - * The reversal is needed so that we can build up the interception chain around the - * server request. - */ - var reversedInterceptors = []; - - forEach(interceptorFactories, function(interceptorFactory) { - reversedInterceptors.unshift(isString(interceptorFactory) - ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory)); - }); - - /** - * A function to check request URLs against a list of allowed origins. - */ - var urlIsAllowedOrigin = urlIsAllowedOriginFactory(xsrfWhitelistedOrigins); - - /** - * @ngdoc service - * @kind function - * @name $http - * @requires ng.$httpBackend - * @requires $cacheFactory - * @requires $rootScope - * @requires $q - * @requires $injector - * - * @description - * The `$http` service is a core AngularJS service that facilitates communication with the remote - * HTTP servers via the browser's [XMLHttpRequest](https://developer.mozilla.org/en/xmlhttprequest) - * object or via [JSONP](http://en.wikipedia.org/wiki/JSONP). - * - * For unit testing applications that use `$http` service, see - * {@link ngMock.$httpBackend $httpBackend mock}. - * - * For a higher level of abstraction, please check out the {@link ngResource.$resource - * $resource} service. - * - * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by - * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage - * it is important to familiarize yourself with these APIs and the guarantees they provide. - * - * - * ## General usage - * The `$http` service is a function which takes a single argument — a {@link $http#usage configuration object} — - * that is used to generate an HTTP request and returns a {@link ng.$q promise} that is - * resolved (request success) or rejected (request failure) with a - * {@link ng.$http#$http-returns response} object. - * - * ```js - * // Simple GET request example: - * $http({ - * method: 'GET', - * url: '/someUrl' - * }).then(function successCallback(response) { - * // this callback will be called asynchronously - * // when the response is available - * }, function errorCallback(response) { - * // called asynchronously if an error occurs - * // or server returns response with an error status. - * }); - * ``` - * - * - * ## Shortcut methods - * - * Shortcut methods are also available. All shortcut methods require passing in the URL, and - * request data must be passed in for POST/PUT requests. An optional config can be passed as the - * last argument. - * - * ```js - * $http.get('/someUrl', config).then(successCallback, errorCallback); - * $http.post('/someUrl', data, config).then(successCallback, errorCallback); - * ``` - * - * Complete list of shortcut methods: - * - * - {@link ng.$http#get $http.get} - * - {@link ng.$http#head $http.head} - * - {@link ng.$http#post $http.post} - * - {@link ng.$http#put $http.put} - * - {@link ng.$http#delete $http.delete} - * - {@link ng.$http#jsonp $http.jsonp} - * - {@link ng.$http#patch $http.patch} - * - * - * ## Writing Unit Tests that use $http - * When unit testing (using {@link ngMock ngMock}), it is necessary to call - * {@link ngMock.$httpBackend#flush $httpBackend.flush()} to flush each pending - * request using trained responses. - * - * ``` - * $httpBackend.expectGET(...); - * $http.get(...); - * $httpBackend.flush(); - * ``` - * - * ## Setting HTTP Headers - * - * The $http service will automatically add certain HTTP headers to all requests. These defaults - * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration - * object, which currently contains this default configuration: - * - * - `$httpProvider.defaults.headers.common` (headers that are common for all requests): - * - Accept: application/json, text/plain, \*/\* - * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests) - * - `Content-Type: application/json` - * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests) - * - `Content-Type: application/json` - * - * To add or overwrite these defaults, simply add or remove a property from these configuration - * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object - * with the lowercased HTTP method name as the key, e.g. - * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }`. - * - * The defaults can also be set at runtime via the `$http.defaults` object in the same - * fashion. For example: - * - * ``` - * module.run(function($http) { - * $http.defaults.headers.common.Authorization = 'Basic YmVlcDpib29w'; - * }); - * ``` - * - * In addition, you can supply a `headers` property in the config object passed when - * calling `$http(config)`, which overrides the defaults without changing them globally. - * - * To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis, - * Use the `headers` property, setting the desired header to `undefined`. For example: - * - * ```js - * var req = { - * method: 'POST', - * url: 'http://example.com', - * headers: { - * 'Content-Type': undefined - * }, - * data: { test: 'test' } - * } - * - * $http(req).then(function(){...}, function(){...}); - * ``` - * - * ## Transforming Requests and Responses - * - * Both requests and responses can be transformed using transformation functions: `transformRequest` - * and `transformResponse`. These properties can be a single function that returns - * the transformed value (`function(data, headersGetter, status)`) or an array of such transformation functions, - * which allows you to `push` or `unshift` a new transformation function into the transformation chain. - * - *
    - * **Note:** AngularJS does not make a copy of the `data` parameter before it is passed into the `transformRequest` pipeline. - * That means changes to the properties of `data` are not local to the transform function (since Javascript passes objects by reference). - * For example, when calling `$http.get(url, $scope.myObject)`, modifications to the object's properties in a transformRequest - * function will be reflected on the scope and in any templates where the object is data-bound. - * To prevent this, transform functions should have no side-effects. - * If you need to modify properties, it is recommended to make a copy of the data, or create new object to return. - *
    - * - * ### Default Transformations - * - * The `$httpProvider` provider and `$http` service expose `defaults.transformRequest` and - * `defaults.transformResponse` properties. If a request does not provide its own transformations - * then these will be applied. - * - * You can augment or replace the default transformations by modifying these properties by adding to or - * replacing the array. - * - * AngularJS provides the following default transformations: - * - * Request transformations (`$httpProvider.defaults.transformRequest` and `$http.defaults.transformRequest`) is - * an array with one function that does the following: - * - * - If the `data` property of the request configuration object contains an object, serialize it - * into JSON format. - * - * Response transformations (`$httpProvider.defaults.transformResponse` and `$http.defaults.transformResponse`) is - * an array with one function that does the following: - * - * - If XSRF prefix is detected, strip it (see Security Considerations section below). - * - If the `Content-Type` is `application/json` or the response looks like JSON, - * deserialize it using a JSON parser. - * - * - * ### Overriding the Default Transformations Per Request - * - * If you wish to override the request/response transformations only for a single request then provide - * `transformRequest` and/or `transformResponse` properties on the configuration object passed - * into `$http`. - * - * Note that if you provide these properties on the config object the default transformations will be - * overwritten. If you wish to augment the default transformations then you must include them in your - * local transformation array. - * - * The following code demonstrates adding a new response transformation to be run after the default response - * transformations have been run. - * - * ```js - * function appendTransform(defaults, transform) { - * - * // We can't guarantee that the default transformation is an array - * defaults = angular.isArray(defaults) ? defaults : [defaults]; - * - * // Append the new transformation to the defaults - * return defaults.concat(transform); - * } - * - * $http({ - * url: '...', - * method: 'GET', - * transformResponse: appendTransform($http.defaults.transformResponse, function(value) { - * return doTransform(value); - * }) - * }); - * ``` - * - * - * ## Caching - * - * {@link ng.$http `$http`} responses are not cached by default. To enable caching, you must - * set the config.cache value or the default cache value to TRUE or to a cache object (created - * with {@link ng.$cacheFactory `$cacheFactory`}). If defined, the value of config.cache takes - * precedence over the default cache value. - * - * In order to: - * * cache all responses - set the default cache value to TRUE or to a cache object - * * cache a specific response - set config.cache value to TRUE or to a cache object - * - * If caching is enabled, but neither the default cache nor config.cache are set to a cache object, - * then the default `$cacheFactory("$http")` object is used. - * - * The default cache value can be set by updating the - * {@link ng.$http#defaults `$http.defaults.cache`} property or the - * {@link $httpProvider#defaults `$httpProvider.defaults.cache`} property. - * - * When caching is enabled, {@link ng.$http `$http`} stores the response from the server using - * the relevant cache object. The next time the same request is made, the response is returned - * from the cache without sending a request to the server. - * - * Take note that: - * - * * Only GET and JSONP requests are cached. - * * The cache key is the request URL including search parameters; headers are not considered. - * * Cached responses are returned asynchronously, in the same way as responses from the server. - * * If multiple identical requests are made using the same cache, which is not yet populated, - * one request will be made to the server and remaining requests will return the same response. - * * A cache-control header on the response does not affect if or how responses are cached. - * - * - * ## Interceptors - * - * Before you start creating interceptors, be sure to understand the - * {@link ng.$q $q and deferred/promise APIs}. - * - * For purposes of global error handling, authentication, or any kind of synchronous or - * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be - * able to intercept requests before they are handed to the server and - * responses before they are handed over to the application code that - * initiated these requests. The interceptors leverage the {@link ng.$q - * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing. - * - * The interceptors are service factories that are registered with the `$httpProvider` by - * adding them to the `$httpProvider.interceptors` array. The factory is called and - * injected with dependencies (if specified) and returns the interceptor. - * - * There are two kinds of interceptors (and two kinds of rejection interceptors): - * - * * `request`: interceptors get called with a http {@link $http#usage config} object. The function is free to - * modify the `config` object or create a new one. The function needs to return the `config` - * object directly, or a promise containing the `config` or a new `config` object. - * * `requestError`: interceptor gets called when a previous interceptor threw an error or - * resolved with a rejection. - * * `response`: interceptors get called with http `response` object. The function is free to - * modify the `response` object or create a new one. The function needs to return the `response` - * object directly, or as a promise containing the `response` or a new `response` object. - * * `responseError`: interceptor gets called when a previous interceptor threw an error or - * resolved with a rejection. - * - * - * ```js - * // register the interceptor as a service - * $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) { - * return { - * // optional method - * 'request': function(config) { - * // do something on success - * return config; - * }, - * - * // optional method - * 'requestError': function(rejection) { - * // do something on error - * if (canRecover(rejection)) { - * return responseOrNewPromise - * } - * return $q.reject(rejection); - * }, - * - * - * - * // optional method - * 'response': function(response) { - * // do something on success - * return response; - * }, - * - * // optional method - * 'responseError': function(rejection) { - * // do something on error - * if (canRecover(rejection)) { - * return responseOrNewPromise - * } - * return $q.reject(rejection); - * } - * }; - * }); - * - * $httpProvider.interceptors.push('myHttpInterceptor'); - * - * - * // alternatively, register the interceptor via an anonymous factory - * $httpProvider.interceptors.push(function($q, dependency1, dependency2) { - * return { - * 'request': function(config) { - * // same as above - * }, - * - * 'response': function(response) { - * // same as above - * } - * }; - * }); - * ``` - * - * ## Security Considerations - * - * When designing web applications, consider security threats from: - * - * - [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) - * - [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) - * - * Both server and the client must cooperate in order to eliminate these threats. AngularJS comes - * pre-configured with strategies that address these issues, but for this to work backend server - * cooperation is required. - * - * ### JSON Vulnerability Protection - * - * A [JSON vulnerability](http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx) - * allows third party website to turn your JSON resource URL into - * [JSONP](http://en.wikipedia.org/wiki/JSONP) request under some conditions. To - * counter this your server can prefix all JSON requests with following string `")]}',\n"`. - * AngularJS will automatically strip the prefix before processing it as JSON. - * - * For example if your server needs to return: - * ```js - * ['one','two'] - * ``` - * - * which is vulnerable to attack, your server can return: - * ```js - * )]}', - * ['one','two'] - * ``` - * - * AngularJS will strip the prefix, before processing the JSON. - * - * - * ### Cross Site Request Forgery (XSRF) Protection - * - * [XSRF](http://en.wikipedia.org/wiki/Cross-site_request_forgery) is an attack technique by - * which the attacker can trick an authenticated user into unknowingly executing actions on your - * website. AngularJS provides a mechanism to counter XSRF. When performing XHR requests, the - * $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an HTTP - * header (by default `X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read - * the cookie, your server can be assured that the XHR came from JavaScript running on your - * domain. - * - * To take advantage of this, your server needs to set a token in a JavaScript readable session - * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the - * server can verify that the cookie matches the `X-XSRF-TOKEN` HTTP header, and therefore be - * sure that only JavaScript running on your domain could have sent the request. The token must - * be unique for each user and must be verifiable by the server (to prevent the JavaScript from - * making up its own tokens). We recommend that the token is a digest of your site's - * authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography)) - * for added security. - * - * The header will — by default — **not** be set for cross-domain requests. This - * prevents unauthorized servers (e.g. malicious or compromised 3rd-party APIs) from gaining - * access to your users' XSRF tokens and exposing them to Cross Site Request Forgery. If you - * want to, you can whitelist additional origins to also receive the XSRF token, by adding them - * to {@link ng.$httpProvider#xsrfWhitelistedOrigins xsrfWhitelistedOrigins}. This might be - * useful, for example, if your application, served from `example.com`, needs to access your API - * at `api.example.com`. - * See {@link ng.$httpProvider#xsrfWhitelistedOrigins $httpProvider.xsrfWhitelistedOrigins} for - * more details. - * - *
    - * **Warning**
    - * Only whitelist origins that you have control over and make sure you understand the - * implications of doing so. - *
    - * - * The name of the cookie and the header can be specified using the `xsrfCookieName` and - * `xsrfHeaderName` properties of either `$httpProvider.defaults` at config-time, - * `$http.defaults` at run-time, or the per-request config object. - * - * In order to prevent collisions in environments where multiple AngularJS apps share the - * same domain or subdomain, we recommend that each application uses a unique cookie name. - * - * - * @param {object} config Object describing the request to be made and how it should be - * processed. The object has following properties: - * - * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc) - * - **url** – `{string|TrustedObject}` – Absolute or relative URL of the resource that is being requested; - * or an object created by a call to `$sce.trustAsResourceUrl(url)`. - * - **params** – `{Object.}` – Map of strings or objects which will be serialized - * with the `paramSerializer` and appended as GET parameters. - * - **data** – `{string|Object}` – Data to be sent as the request message data. - * - **headers** – `{Object}` – Map of strings or functions which return strings representing - * HTTP headers to send to the server. If the return value of a function is null, the - * header will not be sent. Functions accept a config object as an argument. - * - **eventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest object. - * To bind events to the XMLHttpRequest upload object, use `uploadEventHandlers`. - * The handler will be called in the context of a `$apply` block. - * - **uploadEventHandlers** - `{Object}` - Event listeners to be bound to the XMLHttpRequest upload - * object. To bind events to the XMLHttpRequest object, use `eventHandlers`. - * The handler will be called in the context of a `$apply` block. - * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token. - * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token. - * - **transformRequest** – - * `{function(data, headersGetter)|Array.}` – - * transform function or an array of such functions. The transform function takes the http - * request body and headers and returns its transformed (typically serialized) version. - * See {@link ng.$http#overriding-the-default-transformations-per-request - * Overriding the Default Transformations} - * - **transformResponse** – - * `{function(data, headersGetter, status)|Array.}` – - * transform function or an array of such functions. The transform function takes the http - * response body, headers and status and returns its transformed (typically deserialized) version. - * See {@link ng.$http#overriding-the-default-transformations-per-request - * Overriding the Default Transformations} - * - **paramSerializer** - `{string|function(Object):string}` - A function used to - * prepare the string representation of request parameters (specified as an object). - * If specified as string, it is interpreted as function registered with the - * {@link $injector $injector}, which means you can create your own serializer - * by registering it as a {@link auto.$provide#service service}. - * The default serializer is the {@link $httpParamSerializer $httpParamSerializer}; - * alternatively, you can use the {@link $httpParamSerializerJQLike $httpParamSerializerJQLike} - * - **cache** – `{boolean|Object}` – A boolean value or object created with - * {@link ng.$cacheFactory `$cacheFactory`} to enable or disable caching of the HTTP response. - * See {@link $http#caching $http Caching} for more information. - * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} - * that should abort the request when resolved. - * - * A numerical timeout or a promise returned from {@link ng.$timeout $timeout}, will set - * the `xhrStatus` in the {@link $http#$http-returns response} to "timeout", and any other - * resolved promise will set it to "abort", following standard XMLHttpRequest behavior. - * - * - **withCredentials** - `{boolean}` - whether to set the `withCredentials` flag on the - * XHR object. See [requests with credentials](https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials) - * for more information. - * - **responseType** - `{string}` - see - * [XMLHttpRequest.responseType](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype). - * - * @returns {HttpPromise} A {@link ng.$q `Promise}` that will be resolved (request success) - * or rejected (request failure) with a response object. - * - * The response object has these properties: - * - * - **data** – `{string|Object}` – The response body transformed with - * the transform functions. - * - **status** – `{number}` – HTTP status code of the response. - * - **headers** – `{function([headerName])}` – Header getter function. - * - **config** – `{Object}` – The configuration object that was used - * to generate the request. - * - **statusText** – `{string}` – HTTP status text of the response. - * - **xhrStatus** – `{string}` – Status of the XMLHttpRequest - * (`complete`, `error`, `timeout` or `abort`). - * - * - * A response status code between 200 and 299 is considered a success status - * and will result in the success callback being called. Any response status - * code outside of that range is considered an error status and will result - * in the error callback being called. - * Also, status codes less than -1 are normalized to zero. -1 usually means - * the request was aborted, e.g. using a `config.timeout`. More information - * about the status might be available in the `xhrStatus` property. - * - * Note that if the response is a redirect, XMLHttpRequest will transparently - * follow it, meaning that the outcome (success or error) will be determined - * by the final response status code. - * - * - * @property {Array.} pendingRequests Array of config objects for currently pending - * requests. This is primarily meant to be used for debugging purposes. - * - * - * @example - - -
    - - -
    - - - -
    http status code: {{status}}
    -
    http response data: {{data}}
    -
    -
    - - angular.module('httpExample', []) - .config(['$sceDelegateProvider', function($sceDelegateProvider) { - // We must whitelist the JSONP endpoint that we are using to show that we trust it - $sceDelegateProvider.resourceUrlWhitelist([ - 'self', - 'https://angularjs.org/**' - ]); - }]) - .controller('FetchController', ['$scope', '$http', '$templateCache', - function($scope, $http, $templateCache) { - $scope.method = 'GET'; - $scope.url = 'http-hello.html'; - - $scope.fetch = function() { - $scope.code = null; - $scope.response = null; - - $http({method: $scope.method, url: $scope.url, cache: $templateCache}). - then(function(response) { - $scope.status = response.status; - $scope.data = response.data; - }, function(response) { - $scope.data = response.data || 'Request failed'; - $scope.status = response.status; - }); - }; - - $scope.updateModel = function(method, url) { - $scope.method = method; - $scope.url = url; - }; - }]); - - - Hello, $http! - - - var status = element(by.binding('status')); - var data = element(by.binding('data')); - var fetchBtn = element(by.id('fetchbtn')); - var sampleGetBtn = element(by.id('samplegetbtn')); - var invalidJsonpBtn = element(by.id('invalidjsonpbtn')); - - it('should make an xhr GET request', function() { - sampleGetBtn.click(); - fetchBtn.click(); - expect(status.getText()).toMatch('200'); - expect(data.getText()).toMatch(/Hello, \$http!/); - }); - -// Commented out due to flakes. See https://github.com/angular/angular.js/issues/9185 -// it('should make a JSONP request to angularjs.org', function() { -// var sampleJsonpBtn = element(by.id('samplejsonpbtn')); -// sampleJsonpBtn.click(); -// fetchBtn.click(); -// expect(status.getText()).toMatch('200'); -// expect(data.getText()).toMatch(/Super Hero!/); -// }); - - it('should make JSONP request to invalid URL and invoke the error handler', - function() { - invalidJsonpBtn.click(); - fetchBtn.click(); - expect(status.getText()).toMatch('0'); - expect(data.getText()).toMatch('Request failed'); - }); - -
    - */ - function $http(requestConfig) { - - if (!isObject(requestConfig)) { - throw minErr('$http')('badreq', 'Http request configuration must be an object. Received: {0}', requestConfig); - } - - if (!isString($sce.valueOf(requestConfig.url))) { - throw minErr('$http')('badreq', 'Http request configuration url must be a string or a $sce trusted object. Received: {0}', requestConfig.url); - } - - var config = extend({ - method: 'get', - transformRequest: defaults.transformRequest, - transformResponse: defaults.transformResponse, - paramSerializer: defaults.paramSerializer, - jsonpCallbackParam: defaults.jsonpCallbackParam - }, requestConfig); - - config.headers = mergeHeaders(requestConfig); - config.method = uppercase(config.method); - config.paramSerializer = isString(config.paramSerializer) ? - $injector.get(config.paramSerializer) : config.paramSerializer; - - $browser.$$incOutstandingRequestCount('$http'); - - var requestInterceptors = []; - var responseInterceptors = []; - var promise = $q.resolve(config); - - // apply interceptors - forEach(reversedInterceptors, function(interceptor) { - if (interceptor.request || interceptor.requestError) { - requestInterceptors.unshift(interceptor.request, interceptor.requestError); - } - if (interceptor.response || interceptor.responseError) { - responseInterceptors.push(interceptor.response, interceptor.responseError); - } - }); - - promise = chainInterceptors(promise, requestInterceptors); - promise = promise.then(serverRequest); - promise = chainInterceptors(promise, responseInterceptors); - promise = promise.finally(completeOutstandingRequest); - - return promise; - - - function chainInterceptors(promise, interceptors) { - for (var i = 0, ii = interceptors.length; i < ii;) { - var thenFn = interceptors[i++]; - var rejectFn = interceptors[i++]; - - promise = promise.then(thenFn, rejectFn); - } - - interceptors.length = 0; - - return promise; - } - - function completeOutstandingRequest() { - $browser.$$completeOutstandingRequest(noop, '$http'); - } - - function executeHeaderFns(headers, config) { - var headerContent, processedHeaders = {}; - - forEach(headers, function(headerFn, header) { - if (isFunction(headerFn)) { - headerContent = headerFn(config); - if (headerContent != null) { - processedHeaders[header] = headerContent; - } - } else { - processedHeaders[header] = headerFn; - } - }); - - return processedHeaders; - } - - function mergeHeaders(config) { - var defHeaders = defaults.headers, - reqHeaders = extend({}, config.headers), - defHeaderName, lowercaseDefHeaderName, reqHeaderName; - - defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]); - - // using for-in instead of forEach to avoid unnecessary iteration after header has been found - defaultHeadersIteration: - for (defHeaderName in defHeaders) { - lowercaseDefHeaderName = lowercase(defHeaderName); - - for (reqHeaderName in reqHeaders) { - if (lowercase(reqHeaderName) === lowercaseDefHeaderName) { - continue defaultHeadersIteration; - } - } - - reqHeaders[defHeaderName] = defHeaders[defHeaderName]; - } - - // execute if header value is a function for merged headers - return executeHeaderFns(reqHeaders, shallowCopy(config)); - } - - function serverRequest(config) { - var headers = config.headers; - var reqData = transformData(config.data, headersGetter(headers), undefined, config.transformRequest); - - // strip content-type if data is undefined - if (isUndefined(reqData)) { - forEach(headers, function(value, header) { - if (lowercase(header) === 'content-type') { - delete headers[header]; - } - }); - } - - if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { - config.withCredentials = defaults.withCredentials; - } - - // send request - return sendReq(config, reqData).then(transformResponse, transformResponse); - } - - function transformResponse(response) { - // make a copy since the response must be cacheable - var resp = extend({}, response); - resp.data = transformData(response.data, response.headers, response.status, - config.transformResponse); - return (isSuccess(response.status)) - ? resp - : $q.reject(resp); - } - } - - $http.pendingRequests = []; - - /** - * @ngdoc method - * @name $http#get - * - * @description - * Shortcut method to perform `GET` request. - * - * @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested; - * or an object created by a call to `$sce.trustAsResourceUrl(url)`. - * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}. - * @returns {HttpPromise} A Promise that will be resolved or rejected with a response object. - * See {@link ng.$http#$http-returns `$http()` return value}. - */ - - /** - * @ngdoc method - * @name $http#delete - * - * @description - * Shortcut method to perform `DELETE` request. - * - * @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested; - * or an object created by a call to `$sce.trustAsResourceUrl(url)`. - * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}. - * @returns {HttpPromise} A Promise that will be resolved or rejected with a response object. - * See {@link ng.$http#$http-returns `$http()` return value}. - */ - - /** - * @ngdoc method - * @name $http#head - * - * @description - * Shortcut method to perform `HEAD` request. - * - * @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested; - * or an object created by a call to `$sce.trustAsResourceUrl(url)`. - * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}. - * @returns {HttpPromise} A Promise that will be resolved or rejected with a response object. - * See {@link ng.$http#$http-returns `$http()` return value}. - */ - - /** - * @ngdoc method - * @name $http#jsonp - * - * @description - * Shortcut method to perform `JSONP` request. - * - * Note that, since JSONP requests are sensitive because the response is given full access to the browser, - * the url must be declared, via {@link $sce} as a trusted resource URL. - * You can trust a URL by adding it to the whitelist via - * {@link $sceDelegateProvider#resourceUrlWhitelist `$sceDelegateProvider.resourceUrlWhitelist`} or - * by explicitly trusting the URL via {@link $sce#trustAsResourceUrl `$sce.trustAsResourceUrl(url)`}. - * - * You should avoid generating the URL for the JSONP request from user provided data. - * Provide additional query parameters via `params` property of the `config` parameter, rather than - * modifying the URL itself. - * - * JSONP requests must specify a callback to be used in the response from the server. This callback - * is passed as a query parameter in the request. You must specify the name of this parameter by - * setting the `jsonpCallbackParam` property on the request config object. - * - * ``` - * $http.jsonp('some/trusted/url', {jsonpCallbackParam: 'callback'}) - * ``` - * - * You can also specify a default callback parameter name in `$http.defaults.jsonpCallbackParam`. - * Initially this is set to `'callback'`. - * - *
    - * You can no longer use the `JSON_CALLBACK` string as a placeholder for specifying where the callback - * parameter value should go. - *
    - * - * If you would like to customise where and how the callbacks are stored then try overriding - * or decorating the {@link $jsonpCallbacks} service. - * - * @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested; - * or an object created by a call to `$sce.trustAsResourceUrl(url)`. - * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}. - * @returns {HttpPromise} A Promise that will be resolved or rejected with a response object. - * See {@link ng.$http#$http-returns `$http()` return value}. - */ - createShortMethods('get', 'delete', 'head', 'jsonp'); - - /** - * @ngdoc method - * @name $http#post - * - * @description - * Shortcut method to perform `POST` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {*} data Request content - * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}. - * @returns {HttpPromise} A Promise that will be resolved or rejected with a response object. - * See {@link ng.$http#$http-returns `$http()` return value}. - */ - - /** - * @ngdoc method - * @name $http#put - * - * @description - * Shortcut method to perform `PUT` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {*} data Request content - * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}. - * @returns {HttpPromise} A Promise that will be resolved or rejected with a response object. - * See {@link ng.$http#$http-returns `$http()` return value}. - */ - - /** - * @ngdoc method - * @name $http#patch - * - * @description - * Shortcut method to perform `PATCH` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {*} data Request content - * @param {Object=} config Optional configuration object. See {@link ng.$http#$http-arguments `$http()` arguments}. - * @returns {HttpPromise} A Promise that will be resolved or rejected with a response object. - * See {@link ng.$http#$http-returns `$http()` return value}. - */ - createShortMethodsWithData('post', 'put', 'patch'); - - /** - * @ngdoc property - * @name $http#defaults - * - * @description - * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of - * default headers, withCredentials as well as request and response transformations. - * - * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above. - */ - $http.defaults = defaults; - - - return $http; - - - function createShortMethods(names) { - forEach(arguments, function(name) { - $http[name] = function(url, config) { - return $http(extend({}, config || {}, { - method: name, - url: url - })); - }; - }); - } - - - function createShortMethodsWithData(name) { - forEach(arguments, function(name) { - $http[name] = function(url, data, config) { - return $http(extend({}, config || {}, { - method: name, - url: url, - data: data - })); - }; - }); - } - - - /** - * Makes the request. - * - * !!! ACCESSES CLOSURE VARS: - * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests - */ - function sendReq(config, reqData) { - var deferred = $q.defer(), - promise = deferred.promise, - cache, - cachedResp, - reqHeaders = config.headers, - isJsonp = lowercase(config.method) === 'jsonp', - url = config.url; - - if (isJsonp) { - // JSONP is a pretty sensitive operation where we're allowing a script to have full access to - // our DOM and JS space. So we require that the URL satisfies SCE.RESOURCE_URL. - url = $sce.getTrustedResourceUrl(url); - } else if (!isString(url)) { - // If it is not a string then the URL must be a $sce trusted object - url = $sce.valueOf(url); - } - - url = buildUrl(url, config.paramSerializer(config.params)); - - if (isJsonp) { - // Check the url and add the JSONP callback placeholder - url = sanitizeJsonpCallbackParam(url, config.jsonpCallbackParam); - } - - $http.pendingRequests.push(config); - promise.then(removePendingReq, removePendingReq); - - if ((config.cache || defaults.cache) && config.cache !== false && - (config.method === 'GET' || config.method === 'JSONP')) { - cache = isObject(config.cache) ? config.cache - : isObject(/** @type {?} */ (defaults).cache) - ? /** @type {?} */ (defaults).cache - : defaultCache; - } - - if (cache) { - cachedResp = cache.get(url); - if (isDefined(cachedResp)) { - if (isPromiseLike(cachedResp)) { - // cached request has already been sent, but there is no response yet - cachedResp.then(resolvePromiseWithResult, resolvePromiseWithResult); - } else { - // serving from cache - if (isArray(cachedResp)) { - resolvePromise(cachedResp[1], cachedResp[0], shallowCopy(cachedResp[2]), cachedResp[3], cachedResp[4]); - } else { - resolvePromise(cachedResp, 200, {}, 'OK', 'complete'); - } - } - } else { - // put the promise for the non-transformed response into cache as a placeholder - cache.put(url, promise); - } - } - - - // if we won't have the response in cache, set the xsrf headers and - // send the request to the backend - if (isUndefined(cachedResp)) { - var xsrfValue = urlIsAllowedOrigin(config.url) - ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName] - : undefined; - if (xsrfValue) { - reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue; - } - - $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, - config.withCredentials, config.responseType, - createApplyHandlers(config.eventHandlers), - createApplyHandlers(config.uploadEventHandlers)); - } - - return promise; - - function createApplyHandlers(eventHandlers) { - if (eventHandlers) { - var applyHandlers = {}; - forEach(eventHandlers, function(eventHandler, key) { - applyHandlers[key] = function(event) { - if (useApplyAsync) { - $rootScope.$applyAsync(callEventHandler); - } else if ($rootScope.$$phase) { - callEventHandler(); - } else { - $rootScope.$apply(callEventHandler); - } - - function callEventHandler() { - eventHandler(event); - } - }; - }); - return applyHandlers; - } - } - - - /** - * Callback registered to $httpBackend(): - * - caches the response if desired - * - resolves the raw $http promise - * - calls $apply - */ - function done(status, response, headersString, statusText, xhrStatus) { - if (cache) { - if (isSuccess(status)) { - cache.put(url, [status, response, parseHeaders(headersString), statusText, xhrStatus]); - } else { - // remove promise from the cache - cache.remove(url); - } - } - - function resolveHttpPromise() { - resolvePromise(response, status, headersString, statusText, xhrStatus); - } - - if (useApplyAsync) { - $rootScope.$applyAsync(resolveHttpPromise); - } else { - resolveHttpPromise(); - if (!$rootScope.$$phase) $rootScope.$apply(); - } - } - - - /** - * Resolves the raw $http promise. - */ - function resolvePromise(response, status, headers, statusText, xhrStatus) { - //status: HTTP response status code, 0, -1 (aborted by timeout / promise) - status = status >= -1 ? status : 0; - - (isSuccess(status) ? deferred.resolve : deferred.reject)({ - data: response, - status: status, - headers: headersGetter(headers), - config: config, - statusText: statusText, - xhrStatus: xhrStatus - }); - } - - function resolvePromiseWithResult(result) { - resolvePromise(result.data, result.status, shallowCopy(result.headers()), result.statusText, result.xhrStatus); - } - - function removePendingReq() { - var idx = $http.pendingRequests.indexOf(config); - if (idx !== -1) $http.pendingRequests.splice(idx, 1); - } - } - - - function buildUrl(url, serializedParams) { - if (serializedParams.length > 0) { - url += ((url.indexOf('?') === -1) ? '?' : '&') + serializedParams; - } - return url; - } - - function sanitizeJsonpCallbackParam(url, cbKey) { - var parts = url.split('?'); - if (parts.length > 2) { - // Throw if the url contains more than one `?` query indicator - throw $httpMinErr('badjsonp', 'Illegal use more than one "?", in url, "{1}"', url); - } - var params = parseKeyValue(parts[1]); - forEach(params, function(value, key) { - if (value === 'JSON_CALLBACK') { - // Throw if the url already contains a reference to JSON_CALLBACK - throw $httpMinErr('badjsonp', 'Illegal use of JSON_CALLBACK in url, "{0}"', url); - } - if (key === cbKey) { - // Throw if the callback param was already provided - throw $httpMinErr('badjsonp', 'Illegal use of callback param, "{0}", in url, "{1}"', cbKey, url); - } - }); - - // Add in the JSON_CALLBACK callback param value - url += ((url.indexOf('?') === -1) ? '?' : '&') + cbKey + '=JSON_CALLBACK'; - - return url; - } - }]; -} - -/** - * @ngdoc service - * @name $xhrFactory - * @this - * - * @description - * Factory function used to create XMLHttpRequest objects. - * - * Replace or decorate this service to create your own custom XMLHttpRequest objects. - * - * ``` - * angular.module('myApp', []) - * .factory('$xhrFactory', function() { - * return function createXhr(method, url) { - * return new window.XMLHttpRequest({mozSystem: true}); - * }; - * }); - * ``` - * - * @param {string} method HTTP method of the request (GET, POST, PUT, ..) - * @param {string} url URL of the request. - */ -function $xhrFactoryProvider() { - this.$get = function() { - return function createXhr() { - return new window.XMLHttpRequest(); - }; - }; -} - -/** - * @ngdoc service - * @name $httpBackend - * @requires $jsonpCallbacks - * @requires $document - * @requires $xhrFactory - * @this - * - * @description - * HTTP backend used by the {@link ng.$http service} that delegates to - * XMLHttpRequest object or JSONP and deals with browser incompatibilities. - * - * You should never need to use this service directly, instead use the higher-level abstractions: - * {@link ng.$http $http} or {@link ngResource.$resource $resource}. - * - * During testing this implementation is swapped with {@link ngMock.$httpBackend mock - * $httpBackend} which can be trained with responses. - */ -function $HttpBackendProvider() { - this.$get = ['$browser', '$jsonpCallbacks', '$document', '$xhrFactory', function($browser, $jsonpCallbacks, $document, $xhrFactory) { - return createHttpBackend($browser, $xhrFactory, $browser.defer, $jsonpCallbacks, $document[0]); - }]; -} - -function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { - // TODO(vojta): fix the signature - return function(method, url, post, callback, headers, timeout, withCredentials, responseType, eventHandlers, uploadEventHandlers) { - url = url || $browser.url(); - - if (lowercase(method) === 'jsonp') { - var callbackPath = callbacks.createCallback(url); - var jsonpDone = jsonpReq(url, callbackPath, function(status, text) { - // jsonpReq only ever sets status to 200 (OK), 404 (ERROR) or -1 (WAITING) - var response = (status === 200) && callbacks.getResponse(callbackPath); - completeRequest(callback, status, response, '', text, 'complete'); - callbacks.removeCallback(callbackPath); - }); - } else { - - var xhr = createXhr(method, url); - var abortedByTimeout = false; - - xhr.open(method, url, true); - forEach(headers, function(value, key) { - if (isDefined(value)) { - xhr.setRequestHeader(key, value); - } - }); - - xhr.onload = function requestLoaded() { - var statusText = xhr.statusText || ''; - - // responseText is the old-school way of retrieving response (supported by IE9) - // response/responseType properties were introduced in XHR Level2 spec (supported by IE10) - var response = ('response' in xhr) ? xhr.response : xhr.responseText; - - // normalize IE9 bug (http://bugs.jquery.com/ticket/1450) - var status = xhr.status === 1223 ? 204 : xhr.status; - - // fix status code when it is 0 (0 status is undocumented). - // Occurs when accessing file resources or on Android 4.1 stock browser - // while retrieving files from application cache. - if (status === 0) { - status = response ? 200 : urlResolve(url).protocol === 'file' ? 404 : 0; - } - - completeRequest(callback, - status, - response, - xhr.getAllResponseHeaders(), - statusText, - 'complete'); - }; - - var requestError = function() { - // The response is always empty - // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error - completeRequest(callback, -1, null, null, '', 'error'); - }; - - var requestAborted = function() { - completeRequest(callback, -1, null, null, '', abortedByTimeout ? 'timeout' : 'abort'); - }; - - var requestTimeout = function() { - // The response is always empty - // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error - completeRequest(callback, -1, null, null, '', 'timeout'); - }; - - xhr.onerror = requestError; - xhr.ontimeout = requestTimeout; - xhr.onabort = requestAborted; - - forEach(eventHandlers, function(value, key) { - xhr.addEventListener(key, value); - }); - - forEach(uploadEventHandlers, function(value, key) { - xhr.upload.addEventListener(key, value); - }); - - if (withCredentials) { - xhr.withCredentials = true; - } - - if (responseType) { - try { - xhr.responseType = responseType; - } catch (e) { - // WebKit added support for the json responseType value on 09/03/2013 - // https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are - // known to throw when setting the value "json" as the response type. Other older - // browsers implementing the responseType - // - // The json response type can be ignored if not supported, because JSON payloads are - // parsed on the client-side regardless. - if (responseType !== 'json') { - throw e; - } - } - } - - xhr.send(isUndefined(post) ? null : post); - } - - // Since we are using xhr.abort() when a request times out, we have to set a flag that - // indicates to requestAborted if the request timed out or was aborted. - // - // http.timeout = numerical timeout timeout - // http.timeout = $timeout timeout - // http.timeout = promise abort - // xhr.abort() abort (The xhr object is normally inaccessible, but - // can be exposed with the xhrFactory) - if (timeout > 0) { - var timeoutId = $browserDefer(function() { - timeoutRequest('timeout'); - }, timeout); - } else if (isPromiseLike(timeout)) { - timeout.then(function() { - timeoutRequest(isDefined(timeout.$$timeoutId) ? 'timeout' : 'abort'); - }); - } - - function timeoutRequest(reason) { - abortedByTimeout = reason === 'timeout'; - if (jsonpDone) { - jsonpDone(); - } - if (xhr) { - xhr.abort(); - } - } - - function completeRequest(callback, status, response, headersString, statusText, xhrStatus) { - // cancel timeout and subsequent timeout promise resolution - if (isDefined(timeoutId)) { - $browserDefer.cancel(timeoutId); - } - jsonpDone = xhr = null; - - callback(status, response, headersString, statusText, xhrStatus); - } - }; - - function jsonpReq(url, callbackPath, done) { - url = url.replace('JSON_CALLBACK', callbackPath); - // we can't use jQuery/jqLite here because jQuery does crazy stuff with script elements, e.g.: - // - fetches local scripts via XHR and evals them - // - adds and immediately removes script elements from the document - var script = rawDocument.createElement('script'), callback = null; - script.type = 'text/javascript'; - script.src = url; - script.async = true; - - callback = function(event) { - script.removeEventListener('load', callback); - script.removeEventListener('error', callback); - rawDocument.body.removeChild(script); - script = null; - var status = -1; - var text = 'unknown'; - - if (event) { - if (event.type === 'load' && !callbacks.wasCalled(callbackPath)) { - event = { type: 'error' }; - } - text = event.type; - status = event.type === 'error' ? 404 : 200; - } - - if (done) { - done(status, text); - } - }; - - script.addEventListener('load', callback); - script.addEventListener('error', callback); - rawDocument.body.appendChild(script); - return callback; - } -} - -var $interpolateMinErr = angular.$interpolateMinErr = minErr('$interpolate'); -$interpolateMinErr.throwNoconcat = function(text) { - throw $interpolateMinErr('noconcat', - 'Error while interpolating: {0}\nStrict Contextual Escaping disallows ' + - 'interpolations that concatenate multiple expressions when a trusted value is ' + - 'required. See http://docs.angularjs.org/api/ng.$sce', text); -}; - -$interpolateMinErr.interr = function(text, err) { - return $interpolateMinErr('interr', 'Can\'t interpolate: {0}\n{1}', text, err.toString()); -}; - -/** - * @ngdoc provider - * @name $interpolateProvider - * @this - * - * @description - * - * Used for configuring the interpolation markup. Defaults to `{{` and `}}`. - * - *
    - * This feature is sometimes used to mix different markup languages, e.g. to wrap an AngularJS - * template within a Python Jinja template (or any other template language). Mixing templating - * languages is **very dangerous**. The embedding template language will not safely escape AngularJS - * expressions, so any user-controlled values in the template will cause Cross Site Scripting (XSS) - * security bugs! - *
    - * - * @example - - - -
    - //demo.label// -
    -
    - - it('should interpolate binding with custom symbols', function() { - expect(element(by.binding('demo.label')).getText()).toBe('This binding is brought you by // interpolation symbols.'); - }); - -
    - */ -function $InterpolateProvider() { - var startSymbol = '{{'; - var endSymbol = '}}'; - - /** - * @ngdoc method - * @name $interpolateProvider#startSymbol - * @description - * Symbol to denote start of expression in the interpolated string. Defaults to `{{`. - * - * @param {string=} value new value to set the starting symbol to. - * @returns {string|self} Returns the symbol when used as getter and self if used as setter. - */ - this.startSymbol = function(value) { - if (value) { - startSymbol = value; - return this; - } - return startSymbol; - }; - - /** - * @ngdoc method - * @name $interpolateProvider#endSymbol - * @description - * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. - * - * @param {string=} value new value to set the ending symbol to. - * @returns {string|self} Returns the symbol when used as getter and self if used as setter. - */ - this.endSymbol = function(value) { - if (value) { - endSymbol = value; - return this; - } - return endSymbol; - }; - - - this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) { - var startSymbolLength = startSymbol.length, - endSymbolLength = endSymbol.length, - escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'), - escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g'); - - function escape(ch) { - return '\\\\\\' + ch; - } - - function unescapeText(text) { - return text.replace(escapedStartRegexp, startSymbol). - replace(escapedEndRegexp, endSymbol); - } - - // TODO: this is the same as the constantWatchDelegate in parse.js - function constantWatchDelegate(scope, listener, objectEquality, constantInterp) { - var unwatch = scope.$watch(function constantInterpolateWatch(scope) { - unwatch(); - return constantInterp(scope); - }, listener, objectEquality); - return unwatch; - } - - /** - * @ngdoc service - * @name $interpolate - * @kind function - * - * @requires $parse - * @requires $sce - * - * @description - * - * Compiles a string with markup into an interpolation function. This service is used by the - * HTML {@link ng.$compile $compile} service for data binding. See - * {@link ng.$interpolateProvider $interpolateProvider} for configuring the - * interpolation markup. - * - * - * ```js - * var $interpolate = ...; // injected - * var exp = $interpolate('Hello {{name | uppercase}}!'); - * expect(exp({name:'AngularJS'})).toEqual('Hello ANGULARJS!'); - * ``` - * - * `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is - * `true`, the interpolation function will return `undefined` unless all embedded expressions - * evaluate to a value other than `undefined`. - * - * ```js - * var $interpolate = ...; // injected - * var context = {greeting: 'Hello', name: undefined }; - * - * // default "forgiving" mode - * var exp = $interpolate('{{greeting}} {{name}}!'); - * expect(exp(context)).toEqual('Hello !'); - * - * // "allOrNothing" mode - * exp = $interpolate('{{greeting}} {{name}}!', false, null, true); - * expect(exp(context)).toBeUndefined(); - * context.name = 'AngularJS'; - * expect(exp(context)).toEqual('Hello AngularJS!'); - * ``` - * - * `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior. - * - * #### Escaped Interpolation - * $interpolate provides a mechanism for escaping interpolation markers. Start and end markers - * can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash). - * It will be rendered as a regular start/end marker, and will not be interpreted as an expression - * or binding. - * - * This enables web-servers to prevent script injection attacks and defacing attacks, to some - * degree, while also enabling code examples to work without relying on the - * {@link ng.directive:ngNonBindable ngNonBindable} directive. - * - * **For security purposes, it is strongly encouraged that web servers escape user-supplied data, - * replacing angle brackets (<, >) with &lt; and &gt; respectively, and replacing all - * interpolation start/end markers with their escaped counterparts.** - * - * Escaped interpolation markers are only replaced with the actual interpolation markers in rendered - * output when the $interpolate service processes the text. So, for HTML elements interpolated - * by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter - * set to `true`, the interpolated text must contain an unescaped interpolation expression. As such, - * this is typically useful only when user-data is used in rendering a template from the server, or - * when otherwise untrusted data is used by a directive. - * - * - * - *
    - *

    {{apptitle}}: \{\{ username = "defaced value"; \}\} - *

    - *

    {{username}} attempts to inject code which will deface the - * application, but fails to accomplish their task, because the server has correctly - * escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash) - * characters.

    - *

    Instead, the result of the attempted script injection is visible, and can be removed - * from the database by an administrator.

    - *
    - *
    - *
    - * - * @knownIssue - * It is currently not possible for an interpolated expression to contain the interpolation end - * symbol. For example, `{{ '}}' }}` will be incorrectly interpreted as `{{ ' }}` + `' }}`, i.e. - * an interpolated expression consisting of a single-quote (`'`) and the `' }}` string. - * - * @knownIssue - * All directives and components must use the standard `{{` `}}` interpolation symbols - * in their templates. If you change the application interpolation symbols the {@link $compile} - * service will attempt to denormalize the standard symbols to the custom symbols. - * The denormalization process is not clever enough to know not to replace instances of the standard - * symbols where they would not normally be treated as interpolation symbols. For example in the following - * code snippet the closing braces of the literal object will get incorrectly denormalized: - * - * ``` - *
    - * ``` - * - * See https://github.com/angular/angular.js/pull/14610#issuecomment-219401099 for more information. - * - * @param {string} text The text with markup to interpolate. - * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have - * embedded expression in order to return an interpolation function. Strings with no - * embedded expression will return null for the interpolation function. - * @param {string=} trustedContext when provided, the returned function passes the interpolated - * result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult, - * trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that - * provides Strict Contextual Escaping for details. - * @param {boolean=} allOrNothing if `true`, then the returned function returns undefined - * unless all embedded expressions evaluate to a value other than `undefined`. - * @returns {function(context)} an interpolation function which is used to compute the - * interpolated string. The function has these parameters: - * - * - `context`: evaluation context for all expressions embedded in the interpolated text - */ - function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) { - var contextAllowsConcatenation = trustedContext === $sce.URL || trustedContext === $sce.MEDIA_URL; - - // Provide a quick exit and simplified result function for text with no interpolation - if (!text.length || text.indexOf(startSymbol) === -1) { - if (mustHaveExpression) return; - - var unescapedText = unescapeText(text); - if (contextAllowsConcatenation) { - unescapedText = $sce.getTrusted(trustedContext, unescapedText); - } - var constantInterp = valueFn(unescapedText); - constantInterp.exp = text; - constantInterp.expressions = []; - constantInterp.$$watchDelegate = constantWatchDelegate; - - return constantInterp; - } - - allOrNothing = !!allOrNothing; - var startIndex, - endIndex, - index = 0, - expressions = [], - parseFns, - textLength = text.length, - exp, - concat = [], - expressionPositions = [], - singleExpression; - - - while (index < textLength) { - if (((startIndex = text.indexOf(startSymbol, index)) !== -1) && - ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) !== -1)) { - if (index !== startIndex) { - concat.push(unescapeText(text.substring(index, startIndex))); - } - exp = text.substring(startIndex + startSymbolLength, endIndex); - expressions.push(exp); - index = endIndex + endSymbolLength; - expressionPositions.push(concat.length); - concat.push(''); // Placeholder that will get replaced with the evaluated expression. - } else { - // we did not find an interpolation, so we have to add the remainder to the separators array - if (index !== textLength) { - concat.push(unescapeText(text.substring(index))); - } - break; - } - } - - singleExpression = concat.length === 1 && expressionPositions.length === 1; - // Intercept expression if we need to stringify concatenated inputs, which may be SCE trusted - // objects rather than simple strings - // (we don't modify the expression if the input consists of only a single trusted input) - var interceptor = contextAllowsConcatenation && singleExpression ? undefined : parseStringifyInterceptor; - parseFns = expressions.map(function(exp) { return $parse(exp, interceptor); }); - - // Concatenating expressions makes it hard to reason about whether some combination of - // concatenated values are unsafe to use and could easily lead to XSS. By requiring that a - // single expression be used for some $sce-managed secure contexts (RESOURCE_URLs mostly), - // we ensure that the value that's used is assigned or constructed by some JS code somewhere - // that is more testable or make it obvious that you bound the value to some user controlled - // value. This helps reduce the load when auditing for XSS issues. - - // Note that URL and MEDIA_URL $sce contexts do not need this, since `$sce` can sanitize the values - // passed to it. In that case, `$sce.getTrusted` will be called on either the single expression - // or on the overall concatenated string (losing trusted types used in the mix, by design). - // Both these methods will sanitize plain strings. Also, HTML could be included, but since it's - // only used in srcdoc attributes, this would not be very useful. - - if (!mustHaveExpression || expressions.length) { - var compute = function(values) { - for (var i = 0, ii = expressions.length; i < ii; i++) { - if (allOrNothing && isUndefined(values[i])) return; - concat[expressionPositions[i]] = values[i]; - } - - if (contextAllowsConcatenation) { - // If `singleExpression` then `concat[0]` might be a "trusted" value or `null`, rather than a string - return $sce.getTrusted(trustedContext, singleExpression ? concat[0] : concat.join('')); - } else if (trustedContext && concat.length > 1) { - // This context does not allow more than one part, e.g. expr + string or exp + exp. - $interpolateMinErr.throwNoconcat(text); - } - // In an unprivileged context or only one part: just concatenate and return. - return concat.join(''); - }; - - return extend(function interpolationFn(context) { - var i = 0; - var ii = expressions.length; - var values = new Array(ii); - - try { - for (; i < ii; i++) { - values[i] = parseFns[i](context); - } - - return compute(values); - } catch (err) { - $exceptionHandler($interpolateMinErr.interr(text, err)); - } - - }, { - // all of these properties are undocumented for now - exp: text, //just for compatibility with regular watchers created via $watch - expressions: expressions, - $$watchDelegate: function(scope, listener) { - var lastValue; - return scope.$watchGroup(parseFns, /** @this */ function interpolateFnWatcher(values, oldValues) { - var currValue = compute(values); - listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope); - lastValue = currValue; - }); - } - }); - } - - function parseStringifyInterceptor(value) { - try { - // In concatenable contexts, getTrusted comes at the end, to avoid sanitizing individual - // parts of a full URL. We don't care about losing the trustedness here. - // In non-concatenable contexts, where there is only one expression, this interceptor is - // not applied to the expression. - value = (trustedContext && !contextAllowsConcatenation) ? - $sce.getTrusted(trustedContext, value) : - $sce.valueOf(value); - return allOrNothing && !isDefined(value) ? value : stringify(value); - } catch (err) { - $exceptionHandler($interpolateMinErr.interr(text, err)); - } - } - } - - - /** - * @ngdoc method - * @name $interpolate#startSymbol - * @description - * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`. - * - * Use {@link ng.$interpolateProvider#startSymbol `$interpolateProvider.startSymbol`} to change - * the symbol. - * - * @returns {string} start symbol. - */ - $interpolate.startSymbol = function() { - return startSymbol; - }; - - - /** - * @ngdoc method - * @name $interpolate#endSymbol - * @description - * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. - * - * Use {@link ng.$interpolateProvider#endSymbol `$interpolateProvider.endSymbol`} to change - * the symbol. - * - * @returns {string} end symbol. - */ - $interpolate.endSymbol = function() { - return endSymbol; - }; - - return $interpolate; - }]; -} - -var $intervalMinErr = minErr('$interval'); - -/** @this */ -function $IntervalProvider() { - this.$get = ['$$intervalFactory', '$window', - function($$intervalFactory, $window) { - var intervals = {}; - var setIntervalFn = function(tick, delay, deferred) { - var id = $window.setInterval(tick, delay); - intervals[id] = deferred; - return id; - }; - var clearIntervalFn = function(id) { - $window.clearInterval(id); - delete intervals[id]; - }; - - /** - * @ngdoc service - * @name $interval - * - * @description - * AngularJS's wrapper for `window.setInterval`. The `fn` function is executed every `delay` - * milliseconds. - * - * The return value of registering an interval function is a promise. This promise will be - * notified upon each tick of the interval, and will be resolved after `count` iterations, or - * run indefinitely if `count` is not defined. The value of the notification will be the - * number of iterations that have run. - * To cancel an interval, call `$interval.cancel(promise)`. - * - * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to - * move forward by `millis` milliseconds and trigger any functions scheduled to run in that - * time. - * - *
    - * **Note**: Intervals created by this service must be explicitly destroyed when you are finished - * with them. In particular they are not automatically destroyed when a controller's scope or a - * directive's element are destroyed. - * You should take this into consideration and make sure to always cancel the interval at the - * appropriate moment. See the example below for more details on how and when to do this. - *
    - * - * @param {function()} fn A function that should be called repeatedly. If no additional arguments - * are passed (see below), the function is called with the current iteration count. - * @param {number} delay Number of milliseconds between each function call. - * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat - * indefinitely. - * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise - * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. - * @param {...*=} Pass additional parameters to the executed function. - * @returns {promise} A promise which will be notified on each iteration. It will resolve once all iterations of the interval complete. - * - * @example - * - * - * - * - *
    - *
    - *
    - * Current time is: - *
    - * Blood 1 : {{blood_1}} - * Blood 2 : {{blood_2}} - * - * - * - *
    - *
    - * - *
    - *
    - */ - var interval = $$intervalFactory(setIntervalFn, clearIntervalFn); - - /** - * @ngdoc method - * @name $interval#cancel - * - * @description - * Cancels a task associated with the `promise`. - * - * @param {Promise=} promise returned by the `$interval` function. - * @returns {boolean} Returns `true` if the task was successfully canceled. - */ - interval.cancel = function(promise) { - if (!promise) return false; - - if (!promise.hasOwnProperty('$$intervalId')) { - throw $intervalMinErr('badprom', - '`$interval.cancel()` called with a promise that was not generated by `$interval()`.'); - } - - if (!intervals.hasOwnProperty(promise.$$intervalId)) return false; - - var id = promise.$$intervalId; - var deferred = intervals[id]; - - // Interval cancels should not report an unhandled promise. - markQExceptionHandled(deferred.promise); - deferred.reject('canceled'); - clearIntervalFn(id); - - return true; - }; - - return interval; - }]; -} - -/** @this */ -function $$IntervalFactoryProvider() { - this.$get = ['$browser', '$q', '$$q', '$rootScope', - function($browser, $q, $$q, $rootScope) { - return function intervalFactory(setIntervalFn, clearIntervalFn) { - return function intervalFn(fn, delay, count, invokeApply) { - var hasParams = arguments.length > 4, - args = hasParams ? sliceArgs(arguments, 4) : [], - iteration = 0, - skipApply = isDefined(invokeApply) && !invokeApply, - deferred = (skipApply ? $$q : $q).defer(), - promise = deferred.promise; - - count = isDefined(count) ? count : 0; - - function callback() { - if (!hasParams) { - fn(iteration); - } else { - fn.apply(null, args); - } - } - - function tick() { - if (skipApply) { - $browser.defer(callback); - } else { - $rootScope.$evalAsync(callback); - } - deferred.notify(iteration++); - - if (count > 0 && iteration >= count) { - deferred.resolve(iteration); - clearIntervalFn(promise.$$intervalId); - } - - if (!skipApply) $rootScope.$apply(); - } - - promise.$$intervalId = setIntervalFn(tick, delay, deferred, skipApply); - - return promise; - }; - }; - }]; -} - -/** - * @ngdoc service - * @name $jsonpCallbacks - * @requires $window - * @description - * This service handles the lifecycle of callbacks to handle JSONP requests. - * Override this service if you wish to customise where the callbacks are stored and - * how they vary compared to the requested url. - */ -var $jsonpCallbacksProvider = /** @this */ function() { - this.$get = function() { - var callbacks = angular.callbacks; - var callbackMap = {}; - - function createCallback(callbackId) { - var callback = function(data) { - callback.data = data; - callback.called = true; - }; - callback.id = callbackId; - return callback; - } - - return { - /** - * @ngdoc method - * @name $jsonpCallbacks#createCallback - * @param {string} url the url of the JSONP request - * @returns {string} the callback path to send to the server as part of the JSONP request - * @description - * {@link $httpBackend} calls this method to create a callback and get hold of the path to the callback - * to pass to the server, which will be used to call the callback with its payload in the JSONP response. - */ - createCallback: function(url) { - var callbackId = '_' + (callbacks.$$counter++).toString(36); - var callbackPath = 'angular.callbacks.' + callbackId; - var callback = createCallback(callbackId); - callbackMap[callbackPath] = callbacks[callbackId] = callback; - return callbackPath; - }, - /** - * @ngdoc method - * @name $jsonpCallbacks#wasCalled - * @param {string} callbackPath the path to the callback that was sent in the JSONP request - * @returns {boolean} whether the callback has been called, as a result of the JSONP response - * @description - * {@link $httpBackend} calls this method to find out whether the JSONP response actually called the - * callback that was passed in the request. - */ - wasCalled: function(callbackPath) { - return callbackMap[callbackPath].called; - }, - /** - * @ngdoc method - * @name $jsonpCallbacks#getResponse - * @param {string} callbackPath the path to the callback that was sent in the JSONP request - * @returns {*} the data received from the response via the registered callback - * @description - * {@link $httpBackend} calls this method to get hold of the data that was provided to the callback - * in the JSONP response. - */ - getResponse: function(callbackPath) { - return callbackMap[callbackPath].data; - }, - /** - * @ngdoc method - * @name $jsonpCallbacks#removeCallback - * @param {string} callbackPath the path to the callback that was sent in the JSONP request - * @description - * {@link $httpBackend} calls this method to remove the callback after the JSONP request has - * completed or timed-out. - */ - removeCallback: function(callbackPath) { - var callback = callbackMap[callbackPath]; - delete callbacks[callback.id]; - delete callbackMap[callbackPath]; - } - }; - }; -}; - -/** - * @ngdoc service - * @name $locale - * - * @description - * $locale service provides localization rules for various AngularJS components. As of right now the - * only public api is: - * - * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`) - */ - -/* global stripHash: true */ - -var PATH_MATCH = /^([^?#]*)(\?([^#]*))?(#(.*))?$/, - DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21}; -var $locationMinErr = minErr('$location'); - - -/** - * Encode path using encodeUriSegment, ignoring forward slashes - * - * @param {string} path Path to encode - * @returns {string} - */ -function encodePath(path) { - var segments = path.split('/'), - i = segments.length; - - while (i--) { - // decode forward slashes to prevent them from being double encoded - segments[i] = encodeUriSegment(segments[i].replace(/%2F/g, '/')); - } - - return segments.join('/'); -} - -function decodePath(path, html5Mode) { - var segments = path.split('/'), - i = segments.length; - - while (i--) { - segments[i] = decodeURIComponent(segments[i]); - if (html5Mode) { - // encode forward slashes to prevent them from being mistaken for path separators - segments[i] = segments[i].replace(/\//g, '%2F'); - } - } - - return segments.join('/'); -} - -function normalizePath(pathValue, searchValue, hashValue) { - var search = toKeyValue(searchValue), - hash = hashValue ? '#' + encodeUriSegment(hashValue) : '', - path = encodePath(pathValue); - - return path + (search ? '?' + search : '') + hash; -} - -function parseAbsoluteUrl(absoluteUrl, locationObj) { - var parsedUrl = urlResolve(absoluteUrl); - - locationObj.$$protocol = parsedUrl.protocol; - locationObj.$$host = parsedUrl.hostname; - locationObj.$$port = toInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null; -} - -var DOUBLE_SLASH_REGEX = /^\s*[\\/]{2,}/; -function parseAppUrl(url, locationObj, html5Mode) { - - if (DOUBLE_SLASH_REGEX.test(url)) { - throw $locationMinErr('badpath', 'Invalid url "{0}".', url); - } - - var prefixed = (url.charAt(0) !== '/'); - if (prefixed) { - url = '/' + url; - } - var match = urlResolve(url); - var path = prefixed && match.pathname.charAt(0) === '/' ? match.pathname.substring(1) : match.pathname; - locationObj.$$path = decodePath(path, html5Mode); - locationObj.$$search = parseKeyValue(match.search); - locationObj.$$hash = decodeURIComponent(match.hash); - - // make sure path starts with '/'; - if (locationObj.$$path && locationObj.$$path.charAt(0) !== '/') { - locationObj.$$path = '/' + locationObj.$$path; - } -} - -function startsWith(str, search) { - return str.slice(0, search.length) === search; -} - -/** - * - * @param {string} base - * @param {string} url - * @returns {string} returns text from `url` after `base` or `undefined` if it does not begin with - * the expected string. - */ -function stripBaseUrl(base, url) { - if (startsWith(url, base)) { - return url.substr(base.length); - } -} - -function stripHash(url) { - var index = url.indexOf('#'); - return index === -1 ? url : url.substr(0, index); -} - -function stripFile(url) { - return url.substr(0, stripHash(url).lastIndexOf('/') + 1); -} - -/* return the server only (scheme://host:port) */ -function serverBase(url) { - return url.substring(0, url.indexOf('/', url.indexOf('//') + 2)); -} - - -/** - * LocationHtml5Url represents a URL - * This object is exposed as $location service when HTML5 mode is enabled and supported - * - * @constructor - * @param {string} appBase application base URL - * @param {string} appBaseNoFile application base URL stripped of any filename - * @param {string} basePrefix URL path prefix - */ -function LocationHtml5Url(appBase, appBaseNoFile, basePrefix) { - this.$$html5 = true; - basePrefix = basePrefix || ''; - parseAbsoluteUrl(appBase, this); - - - /** - * Parse given HTML5 (regular) URL string into properties - * @param {string} url HTML5 URL - * @private - */ - this.$$parse = function(url) { - var pathUrl = stripBaseUrl(appBaseNoFile, url); - if (!isString(pathUrl)) { - throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url, - appBaseNoFile); - } - - parseAppUrl(pathUrl, this, true); - - if (!this.$$path) { - this.$$path = '/'; - } - - this.$$compose(); - }; - - this.$$normalizeUrl = function(url) { - return appBaseNoFile + url.substr(1); // first char is always '/' - }; - - this.$$parseLinkUrl = function(url, relHref) { - if (relHref && relHref[0] === '#') { - // special case for links to hash fragments: - // keep the old url and only replace the hash fragment - this.hash(relHref.slice(1)); - return true; - } - var appUrl, prevAppUrl; - var rewrittenUrl; - - - if (isDefined(appUrl = stripBaseUrl(appBase, url))) { - prevAppUrl = appUrl; - if (basePrefix && isDefined(appUrl = stripBaseUrl(basePrefix, appUrl))) { - rewrittenUrl = appBaseNoFile + (stripBaseUrl('/', appUrl) || appUrl); - } else { - rewrittenUrl = appBase + prevAppUrl; - } - } else if (isDefined(appUrl = stripBaseUrl(appBaseNoFile, url))) { - rewrittenUrl = appBaseNoFile + appUrl; - } else if (appBaseNoFile === url + '/') { - rewrittenUrl = appBaseNoFile; - } - if (rewrittenUrl) { - this.$$parse(rewrittenUrl); - } - return !!rewrittenUrl; - }; -} - - -/** - * LocationHashbangUrl represents URL - * This object is exposed as $location service when developer doesn't opt into html5 mode. - * It also serves as the base class for html5 mode fallback on legacy browsers. - * - * @constructor - * @param {string} appBase application base URL - * @param {string} appBaseNoFile application base URL stripped of any filename - * @param {string} hashPrefix hashbang prefix - */ -function LocationHashbangUrl(appBase, appBaseNoFile, hashPrefix) { - - parseAbsoluteUrl(appBase, this); - - - /** - * Parse given hashbang URL into properties - * @param {string} url Hashbang URL - * @private - */ - this.$$parse = function(url) { - var withoutBaseUrl = stripBaseUrl(appBase, url) || stripBaseUrl(appBaseNoFile, url); - var withoutHashUrl; - - if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') { - - // The rest of the URL starts with a hash so we have - // got either a hashbang path or a plain hash fragment - withoutHashUrl = stripBaseUrl(hashPrefix, withoutBaseUrl); - if (isUndefined(withoutHashUrl)) { - // There was no hashbang prefix so we just have a hash fragment - withoutHashUrl = withoutBaseUrl; - } - - } else { - // There was no hashbang path nor hash fragment: - // If we are in HTML5 mode we use what is left as the path; - // Otherwise we ignore what is left - if (this.$$html5) { - withoutHashUrl = withoutBaseUrl; - } else { - withoutHashUrl = ''; - if (isUndefined(withoutBaseUrl)) { - appBase = url; - /** @type {?} */ (this).replace(); - } - } - } - - parseAppUrl(withoutHashUrl, this, false); - - this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase); - - this.$$compose(); - - /* - * In Windows, on an anchor node on documents loaded from - * the filesystem, the browser will return a pathname - * prefixed with the drive name ('/C:/path') when a - * pathname without a drive is set: - * * a.setAttribute('href', '/foo') - * * a.pathname === '/C:/foo' //true - * - * Inside of AngularJS, we're always using pathnames that - * do not include drive names for routing. - */ - function removeWindowsDriveName(path, url, base) { - /* - Matches paths for file protocol on windows, - such as /C:/foo/bar, and captures only /foo/bar. - */ - var windowsFilePathExp = /^\/[A-Z]:(\/.*)/; - - var firstPathSegmentMatch; - - //Get the relative path from the input URL. - if (startsWith(url, base)) { - url = url.replace(base, ''); - } - - // The input URL intentionally contains a first path segment that ends with a colon. - if (windowsFilePathExp.exec(url)) { - return path; - } - - firstPathSegmentMatch = windowsFilePathExp.exec(path); - return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path; - } - }; - - this.$$normalizeUrl = function(url) { - return appBase + (url ? hashPrefix + url : ''); - }; - - this.$$parseLinkUrl = function(url, relHref) { - if (stripHash(appBase) === stripHash(url)) { - this.$$parse(url); - return true; - } - return false; - }; -} - - -/** - * LocationHashbangUrl represents URL - * This object is exposed as $location service when html5 history api is enabled but the browser - * does not support it. - * - * @constructor - * @param {string} appBase application base URL - * @param {string} appBaseNoFile application base URL stripped of any filename - * @param {string} hashPrefix hashbang prefix - */ -function LocationHashbangInHtml5Url(appBase, appBaseNoFile, hashPrefix) { - this.$$html5 = true; - LocationHashbangUrl.apply(this, arguments); - - this.$$parseLinkUrl = function(url, relHref) { - if (relHref && relHref[0] === '#') { - // special case for links to hash fragments: - // keep the old url and only replace the hash fragment - this.hash(relHref.slice(1)); - return true; - } - - var rewrittenUrl; - var appUrl; - - if (appBase === stripHash(url)) { - rewrittenUrl = url; - } else if ((appUrl = stripBaseUrl(appBaseNoFile, url))) { - rewrittenUrl = appBase + hashPrefix + appUrl; - } else if (appBaseNoFile === url + '/') { - rewrittenUrl = appBaseNoFile; - } - if (rewrittenUrl) { - this.$$parse(rewrittenUrl); - } - return !!rewrittenUrl; - }; - - this.$$normalizeUrl = function(url) { - // include hashPrefix in $$absUrl when $$url is empty so IE9 does not reload page because of removal of '#' - return appBase + hashPrefix + url; - }; -} - - -var locationPrototype = { - - /** - * Ensure absolute URL is initialized. - * @private - */ - $$absUrl:'', - - /** - * Are we in html5 mode? - * @private - */ - $$html5: false, - - /** - * Has any change been replacing? - * @private - */ - $$replace: false, - - /** - * Compose url and update `url` and `absUrl` property - * @private - */ - $$compose: function() { - this.$$url = normalizePath(this.$$path, this.$$search, this.$$hash); - this.$$absUrl = this.$$normalizeUrl(this.$$url); - this.$$urlUpdatedByLocation = true; - }, - - /** - * @ngdoc method - * @name $location#absUrl - * - * @description - * This method is getter only. - * - * Return full URL representation with all segments encoded according to rules specified in - * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt). - * - * - * ```js - * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo - * var absUrl = $location.absUrl(); - * // => "http://example.com/#/some/path?foo=bar&baz=xoxo" - * ``` - * - * @return {string} full URL - */ - absUrl: locationGetter('$$absUrl'), - - /** - * @ngdoc method - * @name $location#url - * - * @description - * This method is getter / setter. - * - * Return URL (e.g. `/path?a=b#hash`) when called without any parameter. - * - * Change path, search and hash, when called with parameter and return `$location`. - * - * - * ```js - * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo - * var url = $location.url(); - * // => "/some/path?foo=bar&baz=xoxo" - * ``` - * - * @param {string=} url New URL without base prefix (e.g. `/path?a=b#hash`) - * @return {string} url - */ - url: function(url) { - if (isUndefined(url)) { - return this.$$url; - } - - var match = PATH_MATCH.exec(url); - if (match[1] || url === '') this.path(decodeURIComponent(match[1])); - if (match[2] || match[1] || url === '') this.search(match[3] || ''); - this.hash(match[5] || ''); - - return this; - }, - - /** - * @ngdoc method - * @name $location#protocol - * - * @description - * This method is getter only. - * - * Return protocol of current URL. - * - * - * ```js - * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo - * var protocol = $location.protocol(); - * // => "http" - * ``` - * - * @return {string} protocol of current URL - */ - protocol: locationGetter('$$protocol'), - - /** - * @ngdoc method - * @name $location#host - * - * @description - * This method is getter only. - * - * Return host of current URL. - * - * Note: compared to the non-AngularJS version `location.host` which returns `hostname:port`, this returns the `hostname` portion only. - * - * - * ```js - * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo - * var host = $location.host(); - * // => "example.com" - * - * // given URL http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo - * host = $location.host(); - * // => "example.com" - * host = location.host; - * // => "example.com:8080" - * ``` - * - * @return {string} host of current URL. - */ - host: locationGetter('$$host'), - - /** - * @ngdoc method - * @name $location#port - * - * @description - * This method is getter only. - * - * Return port of current URL. - * - * - * ```js - * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo - * var port = $location.port(); - * // => 80 - * ``` - * - * @return {Number} port - */ - port: locationGetter('$$port'), - - /** - * @ngdoc method - * @name $location#path - * - * @description - * This method is getter / setter. - * - * Return path of current URL when called without any parameter. - * - * Change path when called with parameter and return `$location`. - * - * Note: Path should always begin with forward slash (/), this method will add the forward slash - * if it is missing. - * - * - * ```js - * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo - * var path = $location.path(); - * // => "/some/path" - * ``` - * - * @param {(string|number)=} path New path - * @return {(string|object)} path if called with no parameters, or `$location` if called with a parameter - */ - path: locationGetterSetter('$$path', function(path) { - path = path !== null ? path.toString() : ''; - return path.charAt(0) === '/' ? path : '/' + path; - }), - - /** - * @ngdoc method - * @name $location#search - * - * @description - * This method is getter / setter. - * - * Return search part (as object) of current URL when called without any parameter. - * - * Change search part when called with parameter and return `$location`. - * - * - * ```js - * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo - * var searchObject = $location.search(); - * // => {foo: 'bar', baz: 'xoxo'} - * - * // set foo to 'yipee' - * $location.search('foo', 'yipee'); - * // $location.search() => {foo: 'yipee', baz: 'xoxo'} - * ``` - * - * @param {string|Object.|Object.>} search New search params - string or - * hash object. - * - * When called with a single argument the method acts as a setter, setting the `search` component - * of `$location` to the specified value. - * - * If the argument is a hash object containing an array of values, these values will be encoded - * as duplicate search parameters in the URL. - * - * @param {(string|Number|Array|boolean)=} paramValue If `search` is a string or number, then `paramValue` - * will override only a single search property. - * - * If `paramValue` is an array, it will override the property of the `search` component of - * `$location` specified via the first argument. - * - * If `paramValue` is `null`, the property specified via the first argument will be deleted. - * - * If `paramValue` is `true`, the property specified via the first argument will be added with no - * value nor trailing equal sign. - * - * @return {Object} If called with no arguments returns the parsed `search` object. If called with - * one or more arguments returns `$location` object itself. - */ - search: function(search, paramValue) { - switch (arguments.length) { - case 0: - return this.$$search; - case 1: - if (isString(search) || isNumber(search)) { - search = search.toString(); - this.$$search = parseKeyValue(search); - } else if (isObject(search)) { - search = copy(search, {}); - // remove object undefined or null properties - forEach(search, function(value, key) { - if (value == null) delete search[key]; - }); - - this.$$search = search; - } else { - throw $locationMinErr('isrcharg', - 'The first argument of the `$location#search()` call must be a string or an object.'); - } - break; - default: - if (isUndefined(paramValue) || paramValue === null) { - delete this.$$search[search]; - } else { - this.$$search[search] = paramValue; - } - } - - this.$$compose(); - return this; - }, - - /** - * @ngdoc method - * @name $location#hash - * - * @description - * This method is getter / setter. - * - * Returns the hash fragment when called without any parameters. - * - * Changes the hash fragment when called with a parameter and returns `$location`. - * - * - * ```js - * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo#hashValue - * var hash = $location.hash(); - * // => "hashValue" - * ``` - * - * @param {(string|number)=} hash New hash fragment - * @return {string} hash - */ - hash: locationGetterSetter('$$hash', function(hash) { - return hash !== null ? hash.toString() : ''; - }), - - /** - * @ngdoc method - * @name $location#replace - * - * @description - * If called, all changes to $location during the current `$digest` will replace the current history - * record, instead of adding a new one. - */ - replace: function() { - this.$$replace = true; - return this; - } -}; - -forEach([LocationHashbangInHtml5Url, LocationHashbangUrl, LocationHtml5Url], function(Location) { - Location.prototype = Object.create(locationPrototype); - - /** - * @ngdoc method - * @name $location#state - * - * @description - * This method is getter / setter. - * - * Return the history state object when called without any parameter. - * - * Change the history state object when called with one parameter and return `$location`. - * The state object is later passed to `pushState` or `replaceState`. - * - * NOTE: This method is supported only in HTML5 mode and only in browsers supporting - * the HTML5 History API (i.e. methods `pushState` and `replaceState`). If you need to support - * older browsers (like IE9 or Android < 4.0), don't use this method. - * - * @param {object=} state State object for pushState or replaceState - * @return {object} state - */ - Location.prototype.state = function(state) { - if (!arguments.length) { - return this.$$state; - } - - if (Location !== LocationHtml5Url || !this.$$html5) { - throw $locationMinErr('nostate', 'History API state support is available only ' + - 'in HTML5 mode and only in browsers supporting HTML5 History API'); - } - // The user might modify `stateObject` after invoking `$location.state(stateObject)` - // but we're changing the $$state reference to $browser.state() during the $digest - // so the modification window is narrow. - this.$$state = isUndefined(state) ? null : state; - this.$$urlUpdatedByLocation = true; - - return this; - }; -}); - - -function locationGetter(property) { - return /** @this */ function() { - return this[property]; - }; -} - - -function locationGetterSetter(property, preprocess) { - return /** @this */ function(value) { - if (isUndefined(value)) { - return this[property]; - } - - this[property] = preprocess(value); - this.$$compose(); - - return this; - }; -} - - -/** - * @ngdoc service - * @name $location - * - * @requires $rootElement - * - * @description - * The $location service parses the URL in the browser address bar (based on the - * [window.location](https://developer.mozilla.org/en/window.location)) and makes the URL - * available to your application. Changes to the URL in the address bar are reflected into - * $location service and changes to $location are reflected into the browser address bar. - * - * **The $location service:** - * - * - Exposes the current URL in the browser address bar, so you can - * - Watch and observe the URL. - * - Change the URL. - * - Synchronizes the URL with the browser when the user - * - Changes the address bar. - * - Clicks the back or forward button (or clicks a History link). - * - Clicks on a link. - * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash). - * - * For more information see {@link guide/$location Developer Guide: Using $location} - */ - -/** - * @ngdoc provider - * @name $locationProvider - * @this - * - * @description - * Use the `$locationProvider` to configure how the application deep linking paths are stored. - */ -function $LocationProvider() { - var hashPrefix = '!', - html5Mode = { - enabled: false, - requireBase: true, - rewriteLinks: true - }; - - /** - * @ngdoc method - * @name $locationProvider#hashPrefix - * @description - * The default value for the prefix is `'!'`. - * @param {string=} prefix Prefix for hash part (containing path and search) - * @returns {*} current value if used as getter or itself (chaining) if used as setter - */ - this.hashPrefix = function(prefix) { - if (isDefined(prefix)) { - hashPrefix = prefix; - return this; - } else { - return hashPrefix; - } - }; - - /** - * @ngdoc method - * @name $locationProvider#html5Mode - * @description - * @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value. - * If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported - * properties: - * - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to - * change urls where supported. Will fall back to hash-prefixed paths in browsers that do not - * support `pushState`. - * - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies - * whether or not a tag is required to be present. If `enabled` and `requireBase` are - * true, and a base tag is not present, an error will be thrown when `$location` is injected. - * See the {@link guide/$location $location guide for more information} - * - **rewriteLinks** - `{boolean|string}` - (default: `true`) When html5Mode is enabled, - * enables/disables URL rewriting for relative links. If set to a string, URL rewriting will - * only happen on links with an attribute that matches the given string. For example, if set - * to `'internal-link'`, then the URL will only be rewritten for `` links. - * Note that [attribute name normalization](guide/directive#normalization) does not apply - * here, so `'internalLink'` will **not** match `'internal-link'`. - * - * @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter - */ - this.html5Mode = function(mode) { - if (isBoolean(mode)) { - html5Mode.enabled = mode; - return this; - } else if (isObject(mode)) { - - if (isBoolean(mode.enabled)) { - html5Mode.enabled = mode.enabled; - } - - if (isBoolean(mode.requireBase)) { - html5Mode.requireBase = mode.requireBase; - } - - if (isBoolean(mode.rewriteLinks) || isString(mode.rewriteLinks)) { - html5Mode.rewriteLinks = mode.rewriteLinks; - } - - return this; - } else { - return html5Mode; - } - }; - - /** - * @ngdoc event - * @name $location#$locationChangeStart - * @eventType broadcast on root scope - * @description - * Broadcasted before a URL will change. - * - * This change can be prevented by calling - * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more - * details about event object. Upon successful change - * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired. - * - * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when - * the browser supports the HTML5 History API. - * - * @param {Object} angularEvent Synthetic event object. - * @param {string} newUrl New URL - * @param {string=} oldUrl URL that was before it was changed. - * @param {string=} newState New history state object - * @param {string=} oldState History state object that was before it was changed. - */ - - /** - * @ngdoc event - * @name $location#$locationChangeSuccess - * @eventType broadcast on root scope - * @description - * Broadcasted after a URL was changed. - * - * The `newState` and `oldState` parameters may be defined only in HTML5 mode and when - * the browser supports the HTML5 History API. - * - * @param {Object} angularEvent Synthetic event object. - * @param {string} newUrl New URL - * @param {string=} oldUrl URL that was before it was changed. - * @param {string=} newState New history state object - * @param {string=} oldState History state object that was before it was changed. - */ - - this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', '$window', - function($rootScope, $browser, $sniffer, $rootElement, $window) { - var $location, - LocationMode, - baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to '' - initialUrl = $browser.url(), - appBase; - - if (html5Mode.enabled) { - if (!baseHref && html5Mode.requireBase) { - throw $locationMinErr('nobase', - '$location in HTML5 mode requires a tag to be present!'); - } - appBase = serverBase(initialUrl) + (baseHref || '/'); - LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url; - } else { - appBase = stripHash(initialUrl); - LocationMode = LocationHashbangUrl; - } - var appBaseNoFile = stripFile(appBase); - - $location = new LocationMode(appBase, appBaseNoFile, '#' + hashPrefix); - $location.$$parseLinkUrl(initialUrl, initialUrl); - - $location.$$state = $browser.state(); - - var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i; - - // Determine if two URLs are equal despite potentially having different encoding/normalizing - // such as $location.absUrl() vs $browser.url() - // See https://github.com/angular/angular.js/issues/16592 - function urlsEqual(a, b) { - return a === b || urlResolve(a).href === urlResolve(b).href; - } - - function setBrowserUrlWithFallback(url, replace, state) { - var oldUrl = $location.url(); - var oldState = $location.$$state; - try { - $browser.url(url, replace, state); - - // Make sure $location.state() returns referentially identical (not just deeply equal) - // state object; this makes possible quick checking if the state changed in the digest - // loop. Checking deep equality would be too expensive. - $location.$$state = $browser.state(); - } catch (e) { - // Restore old values if pushState fails - $location.url(oldUrl); - $location.$$state = oldState; - - throw e; - } - } - - $rootElement.on('click', function(event) { - var rewriteLinks = html5Mode.rewriteLinks; - // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) - // currently we open nice url link and redirect then - - if (!rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which === 2 || event.button === 2) return; - - var elm = jqLite(event.target); - - // traverse the DOM up to find first A tag - while (nodeName_(elm[0]) !== 'a') { - // ignore rewriting if no A tag (reached root element, or no parent - removed from document) - if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return; - } - - if (isString(rewriteLinks) && isUndefined(elm.attr(rewriteLinks))) return; - - var absHref = elm.prop('href'); - // get the actual href attribute - see - // http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx - var relHref = elm.attr('href') || elm.attr('xlink:href'); - - if (isObject(absHref) && absHref.toString() === '[object SVGAnimatedString]') { - // SVGAnimatedString.animVal should be identical to SVGAnimatedString.baseVal, unless during - // an animation. - absHref = urlResolve(absHref.animVal).href; - } - - // Ignore when url is started with javascript: or mailto: - if (IGNORE_URI_REGEXP.test(absHref)) return; - - if (absHref && !elm.attr('target') && !event.isDefaultPrevented()) { - if ($location.$$parseLinkUrl(absHref, relHref)) { - // We do a preventDefault for all urls that are part of the AngularJS application, - // in html5mode and also without, so that we are able to abort navigation without - // getting double entries in the location history. - event.preventDefault(); - // update location manually - if ($location.absUrl() !== $browser.url()) { - $rootScope.$apply(); - } - } - } - }); - - - // rewrite hashbang url <> html5 url - if ($location.absUrl() !== initialUrl) { - $browser.url($location.absUrl(), true); - } - - var initializing = true; - - // update $location when $browser url changes - $browser.onUrlChange(function(newUrl, newState) { - - if (!startsWith(newUrl, appBaseNoFile)) { - // If we are navigating outside of the app then force a reload - $window.location.href = newUrl; - return; - } - - $rootScope.$evalAsync(function() { - var oldUrl = $location.absUrl(); - var oldState = $location.$$state; - var defaultPrevented; - $location.$$parse(newUrl); - $location.$$state = newState; - - defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, - newState, oldState).defaultPrevented; - - // if the location was changed by a `$locationChangeStart` handler then stop - // processing this location change - if ($location.absUrl() !== newUrl) return; - - if (defaultPrevented) { - $location.$$parse(oldUrl); - $location.$$state = oldState; - setBrowserUrlWithFallback(oldUrl, false, oldState); - } else { - initializing = false; - afterLocationChange(oldUrl, oldState); - } - }); - if (!$rootScope.$$phase) $rootScope.$digest(); - }); - - // update browser - $rootScope.$watch(function $locationWatch() { - if (initializing || $location.$$urlUpdatedByLocation) { - $location.$$urlUpdatedByLocation = false; - - var oldUrl = $browser.url(); - var newUrl = $location.absUrl(); - var oldState = $browser.state(); - var currentReplace = $location.$$replace; - var urlOrStateChanged = !urlsEqual(oldUrl, newUrl) || - ($location.$$html5 && $sniffer.history && oldState !== $location.$$state); - - if (initializing || urlOrStateChanged) { - initializing = false; - - $rootScope.$evalAsync(function() { - var newUrl = $location.absUrl(); - var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, - $location.$$state, oldState).defaultPrevented; - - // if the location was changed by a `$locationChangeStart` handler then stop - // processing this location change - if ($location.absUrl() !== newUrl) return; - - if (defaultPrevented) { - $location.$$parse(oldUrl); - $location.$$state = oldState; - } else { - if (urlOrStateChanged) { - setBrowserUrlWithFallback(newUrl, currentReplace, - oldState === $location.$$state ? null : $location.$$state); - } - afterLocationChange(oldUrl, oldState); - } - }); - } - } - - $location.$$replace = false; - - // we don't need to return anything because $evalAsync will make the digest loop dirty when - // there is a change - }); - - return $location; - - function afterLocationChange(oldUrl, oldState) { - $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl, - $location.$$state, oldState); - } -}]; -} - -/** - * @ngdoc service - * @name $log - * @requires $window - * - * @description - * Simple service for logging. Default implementation safely writes the message - * into the browser's console (if present). - * - * The main purpose of this service is to simplify debugging and troubleshooting. - * - * To reveal the location of the calls to `$log` in the JavaScript console, - * you can "blackbox" the AngularJS source in your browser: - * - * [Mozilla description of blackboxing](https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Black_box_a_source). - * [Chrome description of blackboxing](https://developer.chrome.com/devtools/docs/blackboxing). - * - * Note: Not all browsers support blackboxing. - * - * The default is to log `debug` messages. You can use - * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this. - * - * @example - - - angular.module('logExample', []) - .controller('LogController', ['$scope', '$log', function($scope, $log) { - $scope.$log = $log; - $scope.message = 'Hello World!'; - }]); - - -
    -

    Reload this page with open console, enter text and hit the log button...

    - - - - - - -
    -
    -
    - */ - -/** - * @ngdoc provider - * @name $logProvider - * @this - * - * @description - * Use the `$logProvider` to configure how the application logs messages - */ -function $LogProvider() { - var debug = true, - self = this; - - /** - * @ngdoc method - * @name $logProvider#debugEnabled - * @description - * @param {boolean=} flag enable or disable debug level messages - * @returns {*} current value if used as getter or itself (chaining) if used as setter - */ - this.debugEnabled = function(flag) { - if (isDefined(flag)) { - debug = flag; - return this; - } else { - return debug; - } - }; - - this.$get = ['$window', function($window) { - // Support: IE 9-11, Edge 12-14+ - // IE/Edge display errors in such a way that it requires the user to click in 4 places - // to see the stack trace. There is no way to feature-detect it so there's a chance - // of the user agent sniffing to go wrong but since it's only about logging, this shouldn't - // break apps. Other browsers display errors in a sensible way and some of them map stack - // traces along source maps if available so it makes sense to let browsers display it - // as they want. - var formatStackTrace = msie || /\bEdge\//.test($window.navigator && $window.navigator.userAgent); - - return { - /** - * @ngdoc method - * @name $log#log - * - * @description - * Write a log message - */ - log: consoleLog('log'), - - /** - * @ngdoc method - * @name $log#info - * - * @description - * Write an information message - */ - info: consoleLog('info'), - - /** - * @ngdoc method - * @name $log#warn - * - * @description - * Write a warning message - */ - warn: consoleLog('warn'), - - /** - * @ngdoc method - * @name $log#error - * - * @description - * Write an error message - */ - error: consoleLog('error'), - - /** - * @ngdoc method - * @name $log#debug - * - * @description - * Write a debug message - */ - debug: (function() { - var fn = consoleLog('debug'); - - return function() { - if (debug) { - fn.apply(self, arguments); - } - }; - })() - }; - - function formatError(arg) { - if (isError(arg)) { - if (arg.stack && formatStackTrace) { - arg = (arg.message && arg.stack.indexOf(arg.message) === -1) - ? 'Error: ' + arg.message + '\n' + arg.stack - : arg.stack; - } else if (arg.sourceURL) { - arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line; - } - } - return arg; - } - - function consoleLog(type) { - var console = $window.console || {}, - logFn = console[type] || console.log || noop; - - return function() { - var args = []; - forEach(arguments, function(arg) { - args.push(formatError(arg)); - }); - // Support: IE 9 only - // console methods don't inherit from Function.prototype in IE 9 so we can't - // call `logFn.apply(console, args)` directly. - return Function.prototype.apply.call(logFn, console, args); - }; - } - }]; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Any commits to this file should be reviewed with security in mind. * - * Changes to this file can potentially create security vulnerabilities. * - * An approval from 2 Core members with history of modifying * - * this file is required. * - * * - * Does the change somehow allow for arbitrary javascript to be executed? * - * Or allows for someone to change the prototype of built-in objects? * - * Or gives undesired access to variables likes document or window? * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -var $parseMinErr = minErr('$parse'); - -var objectValueOf = {}.constructor.prototype.valueOf; - -// Sandboxing AngularJS Expressions -// ------------------------------ -// AngularJS expressions are no longer sandboxed. So it is now even easier to access arbitrary JS code by -// various means such as obtaining a reference to native JS functions like the Function constructor. -// -// As an example, consider the following AngularJS expression: -// -// {}.toString.constructor('alert("evil JS code")') -// -// It is important to realize that if you create an expression from a string that contains user provided -// content then it is possible that your application contains a security vulnerability to an XSS style attack. -// -// See https://docs.angularjs.org/guide/security - - -function getStringValue(name) { - // Property names must be strings. This means that non-string objects cannot be used - // as keys in an object. Any non-string object, including a number, is typecasted - // into a string via the toString method. - // -- MDN, https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors#Property_names - // - // So, to ensure that we are checking the same `name` that JavaScript would use, we cast it - // to a string. It's not always possible. If `name` is an object and its `toString` method is - // 'broken' (doesn't return a string, isn't a function, etc.), an error will be thrown: - // - // TypeError: Cannot convert object to primitive value - // - // For performance reasons, we don't catch this error here and allow it to propagate up the call - // stack. Note that you'll get the same error in JavaScript if you try to access a property using - // such a 'broken' object as a key. - return name + ''; -} - - -var OPERATORS = createMap(); -forEach('+ - * / % === !== == != < > <= >= && || ! = |'.split(' '), function(operator) { OPERATORS[operator] = true; }); -var ESCAPE = {'n':'\n', 'f':'\f', 'r':'\r', 't':'\t', 'v':'\v', '\'':'\'', '"':'"'}; - - -///////////////////////////////////////// - - -/** - * @constructor - */ -var Lexer = function Lexer(options) { - this.options = options; -}; - -Lexer.prototype = { - constructor: Lexer, - - lex: function(text) { - this.text = text; - this.index = 0; - this.tokens = []; - - while (this.index < this.text.length) { - var ch = this.text.charAt(this.index); - if (ch === '"' || ch === '\'') { - this.readString(ch); - } else if (this.isNumber(ch) || ch === '.' && this.isNumber(this.peek())) { - this.readNumber(); - } else if (this.isIdentifierStart(this.peekMultichar())) { - this.readIdent(); - } else if (this.is(ch, '(){}[].,;:?')) { - this.tokens.push({index: this.index, text: ch}); - this.index++; - } else if (this.isWhitespace(ch)) { - this.index++; - } else { - var ch2 = ch + this.peek(); - var ch3 = ch2 + this.peek(2); - var op1 = OPERATORS[ch]; - var op2 = OPERATORS[ch2]; - var op3 = OPERATORS[ch3]; - if (op1 || op2 || op3) { - var token = op3 ? ch3 : (op2 ? ch2 : ch); - this.tokens.push({index: this.index, text: token, operator: true}); - this.index += token.length; - } else { - this.throwError('Unexpected next character ', this.index, this.index + 1); - } - } - } - return this.tokens; - }, - - is: function(ch, chars) { - return chars.indexOf(ch) !== -1; - }, - - peek: function(i) { - var num = i || 1; - return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false; - }, - - isNumber: function(ch) { - return ('0' <= ch && ch <= '9') && typeof ch === 'string'; - }, - - isWhitespace: function(ch) { - // IE treats non-breaking space as \u00A0 - return (ch === ' ' || ch === '\r' || ch === '\t' || - ch === '\n' || ch === '\v' || ch === '\u00A0'); - }, - - isIdentifierStart: function(ch) { - return this.options.isIdentifierStart ? - this.options.isIdentifierStart(ch, this.codePointAt(ch)) : - this.isValidIdentifierStart(ch); - }, - - isValidIdentifierStart: function(ch) { - return ('a' <= ch && ch <= 'z' || - 'A' <= ch && ch <= 'Z' || - '_' === ch || ch === '$'); - }, - - isIdentifierContinue: function(ch) { - return this.options.isIdentifierContinue ? - this.options.isIdentifierContinue(ch, this.codePointAt(ch)) : - this.isValidIdentifierContinue(ch); - }, - - isValidIdentifierContinue: function(ch, cp) { - return this.isValidIdentifierStart(ch, cp) || this.isNumber(ch); - }, - - codePointAt: function(ch) { - if (ch.length === 1) return ch.charCodeAt(0); - // eslint-disable-next-line no-bitwise - return (ch.charCodeAt(0) << 10) + ch.charCodeAt(1) - 0x35FDC00; - }, - - peekMultichar: function() { - var ch = this.text.charAt(this.index); - var peek = this.peek(); - if (!peek) { - return ch; - } - var cp1 = ch.charCodeAt(0); - var cp2 = peek.charCodeAt(0); - if (cp1 >= 0xD800 && cp1 <= 0xDBFF && cp2 >= 0xDC00 && cp2 <= 0xDFFF) { - return ch + peek; - } - return ch; - }, - - isExpOperator: function(ch) { - return (ch === '-' || ch === '+' || this.isNumber(ch)); - }, - - throwError: function(error, start, end) { - end = end || this.index; - var colStr = (isDefined(start) - ? 's ' + start + '-' + this.index + ' [' + this.text.substring(start, end) + ']' - : ' ' + end); - throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].', - error, colStr, this.text); - }, - - readNumber: function() { - var number = ''; - var start = this.index; - while (this.index < this.text.length) { - var ch = lowercase(this.text.charAt(this.index)); - if (ch === '.' || this.isNumber(ch)) { - number += ch; - } else { - var peekCh = this.peek(); - if (ch === 'e' && this.isExpOperator(peekCh)) { - number += ch; - } else if (this.isExpOperator(ch) && - peekCh && this.isNumber(peekCh) && - number.charAt(number.length - 1) === 'e') { - number += ch; - } else if (this.isExpOperator(ch) && - (!peekCh || !this.isNumber(peekCh)) && - number.charAt(number.length - 1) === 'e') { - this.throwError('Invalid exponent'); - } else { - break; - } - } - this.index++; - } - this.tokens.push({ - index: start, - text: number, - constant: true, - value: Number(number) - }); - }, - - readIdent: function() { - var start = this.index; - this.index += this.peekMultichar().length; - while (this.index < this.text.length) { - var ch = this.peekMultichar(); - if (!this.isIdentifierContinue(ch)) { - break; - } - this.index += ch.length; - } - this.tokens.push({ - index: start, - text: this.text.slice(start, this.index), - identifier: true - }); - }, - - readString: function(quote) { - var start = this.index; - this.index++; - var string = ''; - var rawString = quote; - var escape = false; - while (this.index < this.text.length) { - var ch = this.text.charAt(this.index); - rawString += ch; - if (escape) { - if (ch === 'u') { - var hex = this.text.substring(this.index + 1, this.index + 5); - if (!hex.match(/[\da-f]{4}/i)) { - this.throwError('Invalid unicode escape [\\u' + hex + ']'); - } - this.index += 4; - string += String.fromCharCode(parseInt(hex, 16)); - } else { - var rep = ESCAPE[ch]; - string = string + (rep || ch); - } - escape = false; - } else if (ch === '\\') { - escape = true; - } else if (ch === quote) { - this.index++; - this.tokens.push({ - index: start, - text: rawString, - constant: true, - value: string - }); - return; - } else { - string += ch; - } - this.index++; - } - this.throwError('Unterminated quote', start); - } -}; - -var AST = function AST(lexer, options) { - this.lexer = lexer; - this.options = options; -}; - -AST.Program = 'Program'; -AST.ExpressionStatement = 'ExpressionStatement'; -AST.AssignmentExpression = 'AssignmentExpression'; -AST.ConditionalExpression = 'ConditionalExpression'; -AST.LogicalExpression = 'LogicalExpression'; -AST.BinaryExpression = 'BinaryExpression'; -AST.UnaryExpression = 'UnaryExpression'; -AST.CallExpression = 'CallExpression'; -AST.MemberExpression = 'MemberExpression'; -AST.Identifier = 'Identifier'; -AST.Literal = 'Literal'; -AST.ArrayExpression = 'ArrayExpression'; -AST.Property = 'Property'; -AST.ObjectExpression = 'ObjectExpression'; -AST.ThisExpression = 'ThisExpression'; -AST.LocalsExpression = 'LocalsExpression'; - -// Internal use only -AST.NGValueParameter = 'NGValueParameter'; - -AST.prototype = { - ast: function(text) { - this.text = text; - this.tokens = this.lexer.lex(text); - - var value = this.program(); - - if (this.tokens.length !== 0) { - this.throwError('is an unexpected token', this.tokens[0]); - } - - return value; - }, - - program: function() { - var body = []; - while (true) { - if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']')) - body.push(this.expressionStatement()); - if (!this.expect(';')) { - return { type: AST.Program, body: body}; - } - } - }, - - expressionStatement: function() { - return { type: AST.ExpressionStatement, expression: this.filterChain() }; - }, - - filterChain: function() { - var left = this.expression(); - while (this.expect('|')) { - left = this.filter(left); - } - return left; - }, - - expression: function() { - return this.assignment(); - }, - - assignment: function() { - var result = this.ternary(); - if (this.expect('=')) { - if (!isAssignable(result)) { - throw $parseMinErr('lval', 'Trying to assign a value to a non l-value'); - } - - result = { type: AST.AssignmentExpression, left: result, right: this.assignment(), operator: '='}; - } - return result; - }, - - ternary: function() { - var test = this.logicalOR(); - var alternate; - var consequent; - if (this.expect('?')) { - alternate = this.expression(); - if (this.consume(':')) { - consequent = this.expression(); - return { type: AST.ConditionalExpression, test: test, alternate: alternate, consequent: consequent}; - } - } - return test; - }, - - logicalOR: function() { - var left = this.logicalAND(); - while (this.expect('||')) { - left = { type: AST.LogicalExpression, operator: '||', left: left, right: this.logicalAND() }; - } - return left; - }, - - logicalAND: function() { - var left = this.equality(); - while (this.expect('&&')) { - left = { type: AST.LogicalExpression, operator: '&&', left: left, right: this.equality()}; - } - return left; - }, - - equality: function() { - var left = this.relational(); - var token; - while ((token = this.expect('==','!=','===','!=='))) { - left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.relational() }; - } - return left; - }, - - relational: function() { - var left = this.additive(); - var token; - while ((token = this.expect('<', '>', '<=', '>='))) { - left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.additive() }; - } - return left; - }, - - additive: function() { - var left = this.multiplicative(); - var token; - while ((token = this.expect('+','-'))) { - left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.multiplicative() }; - } - return left; - }, - - multiplicative: function() { - var left = this.unary(); - var token; - while ((token = this.expect('*','/','%'))) { - left = { type: AST.BinaryExpression, operator: token.text, left: left, right: this.unary() }; - } - return left; - }, - - unary: function() { - var token; - if ((token = this.expect('+', '-', '!'))) { - return { type: AST.UnaryExpression, operator: token.text, prefix: true, argument: this.unary() }; - } else { - return this.primary(); - } - }, - - primary: function() { - var primary; - if (this.expect('(')) { - primary = this.filterChain(); - this.consume(')'); - } else if (this.expect('[')) { - primary = this.arrayDeclaration(); - } else if (this.expect('{')) { - primary = this.object(); - } else if (this.selfReferential.hasOwnProperty(this.peek().text)) { - primary = copy(this.selfReferential[this.consume().text]); - } else if (this.options.literals.hasOwnProperty(this.peek().text)) { - primary = { type: AST.Literal, value: this.options.literals[this.consume().text]}; - } else if (this.peek().identifier) { - primary = this.identifier(); - } else if (this.peek().constant) { - primary = this.constant(); - } else { - this.throwError('not a primary expression', this.peek()); - } - - var next; - while ((next = this.expect('(', '[', '.'))) { - if (next.text === '(') { - primary = {type: AST.CallExpression, callee: primary, arguments: this.parseArguments() }; - this.consume(')'); - } else if (next.text === '[') { - primary = { type: AST.MemberExpression, object: primary, property: this.expression(), computed: true }; - this.consume(']'); - } else if (next.text === '.') { - primary = { type: AST.MemberExpression, object: primary, property: this.identifier(), computed: false }; - } else { - this.throwError('IMPOSSIBLE'); - } - } - return primary; - }, - - filter: function(baseExpression) { - var args = [baseExpression]; - var result = {type: AST.CallExpression, callee: this.identifier(), arguments: args, filter: true}; - - while (this.expect(':')) { - args.push(this.expression()); - } - - return result; - }, - - parseArguments: function() { - var args = []; - if (this.peekToken().text !== ')') { - do { - args.push(this.filterChain()); - } while (this.expect(',')); - } - return args; - }, - - identifier: function() { - var token = this.consume(); - if (!token.identifier) { - this.throwError('is not a valid identifier', token); - } - return { type: AST.Identifier, name: token.text }; - }, - - constant: function() { - // TODO check that it is a constant - return { type: AST.Literal, value: this.consume().value }; - }, - - arrayDeclaration: function() { - var elements = []; - if (this.peekToken().text !== ']') { - do { - if (this.peek(']')) { - // Support trailing commas per ES5.1. - break; - } - elements.push(this.expression()); - } while (this.expect(',')); - } - this.consume(']'); - - return { type: AST.ArrayExpression, elements: elements }; - }, - - object: function() { - var properties = [], property; - if (this.peekToken().text !== '}') { - do { - if (this.peek('}')) { - // Support trailing commas per ES5.1. - break; - } - property = {type: AST.Property, kind: 'init'}; - if (this.peek().constant) { - property.key = this.constant(); - property.computed = false; - this.consume(':'); - property.value = this.expression(); - } else if (this.peek().identifier) { - property.key = this.identifier(); - property.computed = false; - if (this.peek(':')) { - this.consume(':'); - property.value = this.expression(); - } else { - property.value = property.key; - } - } else if (this.peek('[')) { - this.consume('['); - property.key = this.expression(); - this.consume(']'); - property.computed = true; - this.consume(':'); - property.value = this.expression(); - } else { - this.throwError('invalid key', this.peek()); - } - properties.push(property); - } while (this.expect(',')); - } - this.consume('}'); - - return {type: AST.ObjectExpression, properties: properties }; - }, - - throwError: function(msg, token) { - throw $parseMinErr('syntax', - 'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].', - token.text, msg, (token.index + 1), this.text, this.text.substring(token.index)); - }, - - consume: function(e1) { - if (this.tokens.length === 0) { - throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); - } - - var token = this.expect(e1); - if (!token) { - this.throwError('is unexpected, expecting [' + e1 + ']', this.peek()); - } - return token; - }, - - peekToken: function() { - if (this.tokens.length === 0) { - throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text); - } - return this.tokens[0]; - }, - - peek: function(e1, e2, e3, e4) { - return this.peekAhead(0, e1, e2, e3, e4); - }, - - peekAhead: function(i, e1, e2, e3, e4) { - if (this.tokens.length > i) { - var token = this.tokens[i]; - var t = token.text; - if (t === e1 || t === e2 || t === e3 || t === e4 || - (!e1 && !e2 && !e3 && !e4)) { - return token; - } - } - return false; - }, - - expect: function(e1, e2, e3, e4) { - var token = this.peek(e1, e2, e3, e4); - if (token) { - this.tokens.shift(); - return token; - } - return false; - }, - - selfReferential: { - 'this': {type: AST.ThisExpression }, - '$locals': {type: AST.LocalsExpression } - } -}; - -function ifDefined(v, d) { - return typeof v !== 'undefined' ? v : d; -} - -function plusFn(l, r) { - if (typeof l === 'undefined') return r; - if (typeof r === 'undefined') return l; - return l + r; -} - -function isStateless($filter, filterName) { - var fn = $filter(filterName); - return !fn.$stateful; -} - -var PURITY_ABSOLUTE = 1; -var PURITY_RELATIVE = 2; - -// Detect nodes which could depend on non-shallow state of objects -function isPure(node, parentIsPure) { - switch (node.type) { - // Computed members might invoke a stateful toString() - case AST.MemberExpression: - if (node.computed) { - return false; - } - break; - - // Unary always convert to primative - case AST.UnaryExpression: - return PURITY_ABSOLUTE; - - // The binary + operator can invoke a stateful toString(). - case AST.BinaryExpression: - return node.operator !== '+' ? PURITY_ABSOLUTE : false; - - // Functions / filters probably read state from within objects - case AST.CallExpression: - return false; - } - - return (undefined === parentIsPure) ? PURITY_RELATIVE : parentIsPure; -} - -function findConstantAndWatchExpressions(ast, $filter, parentIsPure) { - var allConstants; - var argsToWatch; - var isStatelessFilter; - - var astIsPure = ast.isPure = isPure(ast, parentIsPure); - - switch (ast.type) { - case AST.Program: - allConstants = true; - forEach(ast.body, function(expr) { - findConstantAndWatchExpressions(expr.expression, $filter, astIsPure); - allConstants = allConstants && expr.expression.constant; - }); - ast.constant = allConstants; - break; - case AST.Literal: - ast.constant = true; - ast.toWatch = []; - break; - case AST.UnaryExpression: - findConstantAndWatchExpressions(ast.argument, $filter, astIsPure); - ast.constant = ast.argument.constant; - ast.toWatch = ast.argument.toWatch; - break; - case AST.BinaryExpression: - findConstantAndWatchExpressions(ast.left, $filter, astIsPure); - findConstantAndWatchExpressions(ast.right, $filter, astIsPure); - ast.constant = ast.left.constant && ast.right.constant; - ast.toWatch = ast.left.toWatch.concat(ast.right.toWatch); - break; - case AST.LogicalExpression: - findConstantAndWatchExpressions(ast.left, $filter, astIsPure); - findConstantAndWatchExpressions(ast.right, $filter, astIsPure); - ast.constant = ast.left.constant && ast.right.constant; - ast.toWatch = ast.constant ? [] : [ast]; - break; - case AST.ConditionalExpression: - findConstantAndWatchExpressions(ast.test, $filter, astIsPure); - findConstantAndWatchExpressions(ast.alternate, $filter, astIsPure); - findConstantAndWatchExpressions(ast.consequent, $filter, astIsPure); - ast.constant = ast.test.constant && ast.alternate.constant && ast.consequent.constant; - ast.toWatch = ast.constant ? [] : [ast]; - break; - case AST.Identifier: - ast.constant = false; - ast.toWatch = [ast]; - break; - case AST.MemberExpression: - findConstantAndWatchExpressions(ast.object, $filter, astIsPure); - if (ast.computed) { - findConstantAndWatchExpressions(ast.property, $filter, astIsPure); - } - ast.constant = ast.object.constant && (!ast.computed || ast.property.constant); - ast.toWatch = ast.constant ? [] : [ast]; - break; - case AST.CallExpression: - isStatelessFilter = ast.filter ? isStateless($filter, ast.callee.name) : false; - allConstants = isStatelessFilter; - argsToWatch = []; - forEach(ast.arguments, function(expr) { - findConstantAndWatchExpressions(expr, $filter, astIsPure); - allConstants = allConstants && expr.constant; - argsToWatch.push.apply(argsToWatch, expr.toWatch); - }); - ast.constant = allConstants; - ast.toWatch = isStatelessFilter ? argsToWatch : [ast]; - break; - case AST.AssignmentExpression: - findConstantAndWatchExpressions(ast.left, $filter, astIsPure); - findConstantAndWatchExpressions(ast.right, $filter, astIsPure); - ast.constant = ast.left.constant && ast.right.constant; - ast.toWatch = [ast]; - break; - case AST.ArrayExpression: - allConstants = true; - argsToWatch = []; - forEach(ast.elements, function(expr) { - findConstantAndWatchExpressions(expr, $filter, astIsPure); - allConstants = allConstants && expr.constant; - argsToWatch.push.apply(argsToWatch, expr.toWatch); - }); - ast.constant = allConstants; - ast.toWatch = argsToWatch; - break; - case AST.ObjectExpression: - allConstants = true; - argsToWatch = []; - forEach(ast.properties, function(property) { - findConstantAndWatchExpressions(property.value, $filter, astIsPure); - allConstants = allConstants && property.value.constant; - argsToWatch.push.apply(argsToWatch, property.value.toWatch); - if (property.computed) { - //`{[key]: value}` implicitly does `key.toString()` which may be non-pure - findConstantAndWatchExpressions(property.key, $filter, /*parentIsPure=*/false); - allConstants = allConstants && property.key.constant; - argsToWatch.push.apply(argsToWatch, property.key.toWatch); - } - }); - ast.constant = allConstants; - ast.toWatch = argsToWatch; - break; - case AST.ThisExpression: - ast.constant = false; - ast.toWatch = []; - break; - case AST.LocalsExpression: - ast.constant = false; - ast.toWatch = []; - break; - } -} - -function getInputs(body) { - if (body.length !== 1) return; - var lastExpression = body[0].expression; - var candidate = lastExpression.toWatch; - if (candidate.length !== 1) return candidate; - return candidate[0] !== lastExpression ? candidate : undefined; -} - -function isAssignable(ast) { - return ast.type === AST.Identifier || ast.type === AST.MemberExpression; -} - -function assignableAST(ast) { - if (ast.body.length === 1 && isAssignable(ast.body[0].expression)) { - return {type: AST.AssignmentExpression, left: ast.body[0].expression, right: {type: AST.NGValueParameter}, operator: '='}; - } -} - -function isLiteral(ast) { - return ast.body.length === 0 || - ast.body.length === 1 && ( - ast.body[0].expression.type === AST.Literal || - ast.body[0].expression.type === AST.ArrayExpression || - ast.body[0].expression.type === AST.ObjectExpression); -} - -function isConstant(ast) { - return ast.constant; -} - -function ASTCompiler($filter) { - this.$filter = $filter; -} - -ASTCompiler.prototype = { - compile: function(ast) { - var self = this; - this.state = { - nextId: 0, - filters: {}, - fn: {vars: [], body: [], own: {}}, - assign: {vars: [], body: [], own: {}}, - inputs: [] - }; - findConstantAndWatchExpressions(ast, self.$filter); - var extra = ''; - var assignable; - this.stage = 'assign'; - if ((assignable = assignableAST(ast))) { - this.state.computing = 'assign'; - var result = this.nextId(); - this.recurse(assignable, result); - this.return_(result); - extra = 'fn.assign=' + this.generateFunction('assign', 's,v,l'); - } - var toWatch = getInputs(ast.body); - self.stage = 'inputs'; - forEach(toWatch, function(watch, key) { - var fnKey = 'fn' + key; - self.state[fnKey] = {vars: [], body: [], own: {}}; - self.state.computing = fnKey; - var intoId = self.nextId(); - self.recurse(watch, intoId); - self.return_(intoId); - self.state.inputs.push({name: fnKey, isPure: watch.isPure}); - watch.watchId = key; - }); - this.state.computing = 'fn'; - this.stage = 'main'; - this.recurse(ast); - var fnString = - // The build and minification steps remove the string "use strict" from the code, but this is done using a regex. - // This is a workaround for this until we do a better job at only removing the prefix only when we should. - '"' + this.USE + ' ' + this.STRICT + '";\n' + - this.filterPrefix() + - 'var fn=' + this.generateFunction('fn', 's,l,a,i') + - extra + - this.watchFns() + - 'return fn;'; - - // eslint-disable-next-line no-new-func - var fn = (new Function('$filter', - 'getStringValue', - 'ifDefined', - 'plus', - fnString))( - this.$filter, - getStringValue, - ifDefined, - plusFn); - this.state = this.stage = undefined; - return fn; - }, - - USE: 'use', - - STRICT: 'strict', - - watchFns: function() { - var result = []; - var inputs = this.state.inputs; - var self = this; - forEach(inputs, function(input) { - result.push('var ' + input.name + '=' + self.generateFunction(input.name, 's')); - if (input.isPure) { - result.push(input.name, '.isPure=' + JSON.stringify(input.isPure) + ';'); - } - }); - if (inputs.length) { - result.push('fn.inputs=[' + inputs.map(function(i) { return i.name; }).join(',') + '];'); - } - return result.join(''); - }, - - generateFunction: function(name, params) { - return 'function(' + params + '){' + - this.varsPrefix(name) + - this.body(name) + - '};'; - }, - - filterPrefix: function() { - var parts = []; - var self = this; - forEach(this.state.filters, function(id, filter) { - parts.push(id + '=$filter(' + self.escape(filter) + ')'); - }); - if (parts.length) return 'var ' + parts.join(',') + ';'; - return ''; - }, - - varsPrefix: function(section) { - return this.state[section].vars.length ? 'var ' + this.state[section].vars.join(',') + ';' : ''; - }, - - body: function(section) { - return this.state[section].body.join(''); - }, - - recurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { - var left, right, self = this, args, expression, computed; - recursionFn = recursionFn || noop; - if (!skipWatchIdCheck && isDefined(ast.watchId)) { - intoId = intoId || this.nextId(); - this.if_('i', - this.lazyAssign(intoId, this.computedMember('i', ast.watchId)), - this.lazyRecurse(ast, intoId, nameId, recursionFn, create, true) - ); - return; - } - switch (ast.type) { - case AST.Program: - forEach(ast.body, function(expression, pos) { - self.recurse(expression.expression, undefined, undefined, function(expr) { right = expr; }); - if (pos !== ast.body.length - 1) { - self.current().body.push(right, ';'); - } else { - self.return_(right); - } - }); - break; - case AST.Literal: - expression = this.escape(ast.value); - this.assign(intoId, expression); - recursionFn(intoId || expression); - break; - case AST.UnaryExpression: - this.recurse(ast.argument, undefined, undefined, function(expr) { right = expr; }); - expression = ast.operator + '(' + this.ifDefined(right, 0) + ')'; - this.assign(intoId, expression); - recursionFn(expression); - break; - case AST.BinaryExpression: - this.recurse(ast.left, undefined, undefined, function(expr) { left = expr; }); - this.recurse(ast.right, undefined, undefined, function(expr) { right = expr; }); - if (ast.operator === '+') { - expression = this.plus(left, right); - } else if (ast.operator === '-') { - expression = this.ifDefined(left, 0) + ast.operator + this.ifDefined(right, 0); - } else { - expression = '(' + left + ')' + ast.operator + '(' + right + ')'; - } - this.assign(intoId, expression); - recursionFn(expression); - break; - case AST.LogicalExpression: - intoId = intoId || this.nextId(); - self.recurse(ast.left, intoId); - self.if_(ast.operator === '&&' ? intoId : self.not(intoId), self.lazyRecurse(ast.right, intoId)); - recursionFn(intoId); - break; - case AST.ConditionalExpression: - intoId = intoId || this.nextId(); - self.recurse(ast.test, intoId); - self.if_(intoId, self.lazyRecurse(ast.alternate, intoId), self.lazyRecurse(ast.consequent, intoId)); - recursionFn(intoId); - break; - case AST.Identifier: - intoId = intoId || this.nextId(); - if (nameId) { - nameId.context = self.stage === 'inputs' ? 's' : this.assign(this.nextId(), this.getHasOwnProperty('l', ast.name) + '?l:s'); - nameId.computed = false; - nameId.name = ast.name; - } - self.if_(self.stage === 'inputs' || self.not(self.getHasOwnProperty('l', ast.name)), - function() { - self.if_(self.stage === 'inputs' || 's', function() { - if (create && create !== 1) { - self.if_( - self.isNull(self.nonComputedMember('s', ast.name)), - self.lazyAssign(self.nonComputedMember('s', ast.name), '{}')); - } - self.assign(intoId, self.nonComputedMember('s', ast.name)); - }); - }, intoId && self.lazyAssign(intoId, self.nonComputedMember('l', ast.name)) - ); - recursionFn(intoId); - break; - case AST.MemberExpression: - left = nameId && (nameId.context = this.nextId()) || this.nextId(); - intoId = intoId || this.nextId(); - self.recurse(ast.object, left, undefined, function() { - self.if_(self.notNull(left), function() { - if (ast.computed) { - right = self.nextId(); - self.recurse(ast.property, right); - self.getStringValue(right); - if (create && create !== 1) { - self.if_(self.not(self.computedMember(left, right)), self.lazyAssign(self.computedMember(left, right), '{}')); - } - expression = self.computedMember(left, right); - self.assign(intoId, expression); - if (nameId) { - nameId.computed = true; - nameId.name = right; - } - } else { - if (create && create !== 1) { - self.if_(self.isNull(self.nonComputedMember(left, ast.property.name)), self.lazyAssign(self.nonComputedMember(left, ast.property.name), '{}')); - } - expression = self.nonComputedMember(left, ast.property.name); - self.assign(intoId, expression); - if (nameId) { - nameId.computed = false; - nameId.name = ast.property.name; - } - } - }, function() { - self.assign(intoId, 'undefined'); - }); - recursionFn(intoId); - }, !!create); - break; - case AST.CallExpression: - intoId = intoId || this.nextId(); - if (ast.filter) { - right = self.filter(ast.callee.name); - args = []; - forEach(ast.arguments, function(expr) { - var argument = self.nextId(); - self.recurse(expr, argument); - args.push(argument); - }); - expression = right + '(' + args.join(',') + ')'; - self.assign(intoId, expression); - recursionFn(intoId); - } else { - right = self.nextId(); - left = {}; - args = []; - self.recurse(ast.callee, right, left, function() { - self.if_(self.notNull(right), function() { - forEach(ast.arguments, function(expr) { - self.recurse(expr, ast.constant ? undefined : self.nextId(), undefined, function(argument) { - args.push(argument); - }); - }); - if (left.name) { - expression = self.member(left.context, left.name, left.computed) + '(' + args.join(',') + ')'; - } else { - expression = right + '(' + args.join(',') + ')'; - } - self.assign(intoId, expression); - }, function() { - self.assign(intoId, 'undefined'); - }); - recursionFn(intoId); - }); - } - break; - case AST.AssignmentExpression: - right = this.nextId(); - left = {}; - this.recurse(ast.left, undefined, left, function() { - self.if_(self.notNull(left.context), function() { - self.recurse(ast.right, right); - expression = self.member(left.context, left.name, left.computed) + ast.operator + right; - self.assign(intoId, expression); - recursionFn(intoId || expression); - }); - }, 1); - break; - case AST.ArrayExpression: - args = []; - forEach(ast.elements, function(expr) { - self.recurse(expr, ast.constant ? undefined : self.nextId(), undefined, function(argument) { - args.push(argument); - }); - }); - expression = '[' + args.join(',') + ']'; - this.assign(intoId, expression); - recursionFn(intoId || expression); - break; - case AST.ObjectExpression: - args = []; - computed = false; - forEach(ast.properties, function(property) { - if (property.computed) { - computed = true; - } - }); - if (computed) { - intoId = intoId || this.nextId(); - this.assign(intoId, '{}'); - forEach(ast.properties, function(property) { - if (property.computed) { - left = self.nextId(); - self.recurse(property.key, left); - } else { - left = property.key.type === AST.Identifier ? - property.key.name : - ('' + property.key.value); - } - right = self.nextId(); - self.recurse(property.value, right); - self.assign(self.member(intoId, left, property.computed), right); - }); - } else { - forEach(ast.properties, function(property) { - self.recurse(property.value, ast.constant ? undefined : self.nextId(), undefined, function(expr) { - args.push(self.escape( - property.key.type === AST.Identifier ? property.key.name : - ('' + property.key.value)) + - ':' + expr); - }); - }); - expression = '{' + args.join(',') + '}'; - this.assign(intoId, expression); - } - recursionFn(intoId || expression); - break; - case AST.ThisExpression: - this.assign(intoId, 's'); - recursionFn(intoId || 's'); - break; - case AST.LocalsExpression: - this.assign(intoId, 'l'); - recursionFn(intoId || 'l'); - break; - case AST.NGValueParameter: - this.assign(intoId, 'v'); - recursionFn(intoId || 'v'); - break; - } - }, - - getHasOwnProperty: function(element, property) { - var key = element + '.' + property; - var own = this.current().own; - if (!own.hasOwnProperty(key)) { - own[key] = this.nextId(false, element + '&&(' + this.escape(property) + ' in ' + element + ')'); - } - return own[key]; - }, - - assign: function(id, value) { - if (!id) return; - this.current().body.push(id, '=', value, ';'); - return id; - }, - - filter: function(filterName) { - if (!this.state.filters.hasOwnProperty(filterName)) { - this.state.filters[filterName] = this.nextId(true); - } - return this.state.filters[filterName]; - }, - - ifDefined: function(id, defaultValue) { - return 'ifDefined(' + id + ',' + this.escape(defaultValue) + ')'; - }, - - plus: function(left, right) { - return 'plus(' + left + ',' + right + ')'; - }, - - return_: function(id) { - this.current().body.push('return ', id, ';'); - }, - - if_: function(test, alternate, consequent) { - if (test === true) { - alternate(); - } else { - var body = this.current().body; - body.push('if(', test, '){'); - alternate(); - body.push('}'); - if (consequent) { - body.push('else{'); - consequent(); - body.push('}'); - } - } - }, - - not: function(expression) { - return '!(' + expression + ')'; - }, - - isNull: function(expression) { - return expression + '==null'; - }, - - notNull: function(expression) { - return expression + '!=null'; - }, - - nonComputedMember: function(left, right) { - var SAFE_IDENTIFIER = /^[$_a-zA-Z][$_a-zA-Z0-9]*$/; - var UNSAFE_CHARACTERS = /[^$_a-zA-Z0-9]/g; - if (SAFE_IDENTIFIER.test(right)) { - return left + '.' + right; - } else { - return left + '["' + right.replace(UNSAFE_CHARACTERS, this.stringEscapeFn) + '"]'; - } - }, - - computedMember: function(left, right) { - return left + '[' + right + ']'; - }, - - member: function(left, right, computed) { - if (computed) return this.computedMember(left, right); - return this.nonComputedMember(left, right); - }, - - getStringValue: function(item) { - this.assign(item, 'getStringValue(' + item + ')'); - }, - - lazyRecurse: function(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck) { - var self = this; - return function() { - self.recurse(ast, intoId, nameId, recursionFn, create, skipWatchIdCheck); - }; - }, - - lazyAssign: function(id, value) { - var self = this; - return function() { - self.assign(id, value); - }; - }, - - stringEscapeRegex: /[^ a-zA-Z0-9]/g, - - stringEscapeFn: function(c) { - return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4); - }, - - escape: function(value) { - if (isString(value)) return '\'' + value.replace(this.stringEscapeRegex, this.stringEscapeFn) + '\''; - if (isNumber(value)) return value.toString(); - if (value === true) return 'true'; - if (value === false) return 'false'; - if (value === null) return 'null'; - if (typeof value === 'undefined') return 'undefined'; - - throw $parseMinErr('esc', 'IMPOSSIBLE'); - }, - - nextId: function(skip, init) { - var id = 'v' + (this.state.nextId++); - if (!skip) { - this.current().vars.push(id + (init ? '=' + init : '')); - } - return id; - }, - - current: function() { - return this.state[this.state.computing]; - } -}; - - -function ASTInterpreter($filter) { - this.$filter = $filter; -} - -ASTInterpreter.prototype = { - compile: function(ast) { - var self = this; - findConstantAndWatchExpressions(ast, self.$filter); - var assignable; - var assign; - if ((assignable = assignableAST(ast))) { - assign = this.recurse(assignable); - } - var toWatch = getInputs(ast.body); - var inputs; - if (toWatch) { - inputs = []; - forEach(toWatch, function(watch, key) { - var input = self.recurse(watch); - input.isPure = watch.isPure; - watch.input = input; - inputs.push(input); - watch.watchId = key; - }); - } - var expressions = []; - forEach(ast.body, function(expression) { - expressions.push(self.recurse(expression.expression)); - }); - var fn = ast.body.length === 0 ? noop : - ast.body.length === 1 ? expressions[0] : - function(scope, locals) { - var lastValue; - forEach(expressions, function(exp) { - lastValue = exp(scope, locals); - }); - return lastValue; - }; - if (assign) { - fn.assign = function(scope, value, locals) { - return assign(scope, locals, value); - }; - } - if (inputs) { - fn.inputs = inputs; - } - return fn; - }, - - recurse: function(ast, context, create) { - var left, right, self = this, args; - if (ast.input) { - return this.inputs(ast.input, ast.watchId); - } - switch (ast.type) { - case AST.Literal: - return this.value(ast.value, context); - case AST.UnaryExpression: - right = this.recurse(ast.argument); - return this['unary' + ast.operator](right, context); - case AST.BinaryExpression: - left = this.recurse(ast.left); - right = this.recurse(ast.right); - return this['binary' + ast.operator](left, right, context); - case AST.LogicalExpression: - left = this.recurse(ast.left); - right = this.recurse(ast.right); - return this['binary' + ast.operator](left, right, context); - case AST.ConditionalExpression: - return this['ternary?:']( - this.recurse(ast.test), - this.recurse(ast.alternate), - this.recurse(ast.consequent), - context - ); - case AST.Identifier: - return self.identifier(ast.name, context, create); - case AST.MemberExpression: - left = this.recurse(ast.object, false, !!create); - if (!ast.computed) { - right = ast.property.name; - } - if (ast.computed) right = this.recurse(ast.property); - return ast.computed ? - this.computedMember(left, right, context, create) : - this.nonComputedMember(left, right, context, create); - case AST.CallExpression: - args = []; - forEach(ast.arguments, function(expr) { - args.push(self.recurse(expr)); - }); - if (ast.filter) right = this.$filter(ast.callee.name); - if (!ast.filter) right = this.recurse(ast.callee, true); - return ast.filter ? - function(scope, locals, assign, inputs) { - var values = []; - for (var i = 0; i < args.length; ++i) { - values.push(args[i](scope, locals, assign, inputs)); - } - var value = right.apply(undefined, values, inputs); - return context ? {context: undefined, name: undefined, value: value} : value; - } : - function(scope, locals, assign, inputs) { - var rhs = right(scope, locals, assign, inputs); - var value; - if (rhs.value != null) { - var values = []; - for (var i = 0; i < args.length; ++i) { - values.push(args[i](scope, locals, assign, inputs)); - } - value = rhs.value.apply(rhs.context, values); - } - return context ? {value: value} : value; - }; - case AST.AssignmentExpression: - left = this.recurse(ast.left, true, 1); - right = this.recurse(ast.right); - return function(scope, locals, assign, inputs) { - var lhs = left(scope, locals, assign, inputs); - var rhs = right(scope, locals, assign, inputs); - lhs.context[lhs.name] = rhs; - return context ? {value: rhs} : rhs; - }; - case AST.ArrayExpression: - args = []; - forEach(ast.elements, function(expr) { - args.push(self.recurse(expr)); - }); - return function(scope, locals, assign, inputs) { - var value = []; - for (var i = 0; i < args.length; ++i) { - value.push(args[i](scope, locals, assign, inputs)); - } - return context ? {value: value} : value; - }; - case AST.ObjectExpression: - args = []; - forEach(ast.properties, function(property) { - if (property.computed) { - args.push({key: self.recurse(property.key), - computed: true, - value: self.recurse(property.value) - }); - } else { - args.push({key: property.key.type === AST.Identifier ? - property.key.name : - ('' + property.key.value), - computed: false, - value: self.recurse(property.value) - }); - } - }); - return function(scope, locals, assign, inputs) { - var value = {}; - for (var i = 0; i < args.length; ++i) { - if (args[i].computed) { - value[args[i].key(scope, locals, assign, inputs)] = args[i].value(scope, locals, assign, inputs); - } else { - value[args[i].key] = args[i].value(scope, locals, assign, inputs); - } - } - return context ? {value: value} : value; - }; - case AST.ThisExpression: - return function(scope) { - return context ? {value: scope} : scope; - }; - case AST.LocalsExpression: - return function(scope, locals) { - return context ? {value: locals} : locals; - }; - case AST.NGValueParameter: - return function(scope, locals, assign) { - return context ? {value: assign} : assign; - }; - } - }, - - 'unary+': function(argument, context) { - return function(scope, locals, assign, inputs) { - var arg = argument(scope, locals, assign, inputs); - if (isDefined(arg)) { - arg = +arg; - } else { - arg = 0; - } - return context ? {value: arg} : arg; - }; - }, - 'unary-': function(argument, context) { - return function(scope, locals, assign, inputs) { - var arg = argument(scope, locals, assign, inputs); - if (isDefined(arg)) { - arg = -arg; - } else { - arg = -0; - } - return context ? {value: arg} : arg; - }; - }, - 'unary!': function(argument, context) { - return function(scope, locals, assign, inputs) { - var arg = !argument(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary+': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var lhs = left(scope, locals, assign, inputs); - var rhs = right(scope, locals, assign, inputs); - var arg = plusFn(lhs, rhs); - return context ? {value: arg} : arg; - }; - }, - 'binary-': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var lhs = left(scope, locals, assign, inputs); - var rhs = right(scope, locals, assign, inputs); - var arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0); - return context ? {value: arg} : arg; - }; - }, - 'binary*': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) * right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary/': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) / right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary%': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) % right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary===': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) === right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary!==': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) !== right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary==': function(left, right, context) { - return function(scope, locals, assign, inputs) { - // eslint-disable-next-line eqeqeq - var arg = left(scope, locals, assign, inputs) == right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary!=': function(left, right, context) { - return function(scope, locals, assign, inputs) { - // eslint-disable-next-line eqeqeq - var arg = left(scope, locals, assign, inputs) != right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary<': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) < right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary>': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) > right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary<=': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) <= right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary>=': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) >= right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary&&': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) && right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'binary||': function(left, right, context) { - return function(scope, locals, assign, inputs) { - var arg = left(scope, locals, assign, inputs) || right(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - 'ternary?:': function(test, alternate, consequent, context) { - return function(scope, locals, assign, inputs) { - var arg = test(scope, locals, assign, inputs) ? alternate(scope, locals, assign, inputs) : consequent(scope, locals, assign, inputs); - return context ? {value: arg} : arg; - }; - }, - value: function(value, context) { - return function() { return context ? {context: undefined, name: undefined, value: value} : value; }; - }, - identifier: function(name, context, create) { - return function(scope, locals, assign, inputs) { - var base = locals && (name in locals) ? locals : scope; - if (create && create !== 1 && base && base[name] == null) { - base[name] = {}; - } - var value = base ? base[name] : undefined; - if (context) { - return {context: base, name: name, value: value}; - } else { - return value; - } - }; - }, - computedMember: function(left, right, context, create) { - return function(scope, locals, assign, inputs) { - var lhs = left(scope, locals, assign, inputs); - var rhs; - var value; - if (lhs != null) { - rhs = right(scope, locals, assign, inputs); - rhs = getStringValue(rhs); - if (create && create !== 1) { - if (lhs && !(lhs[rhs])) { - lhs[rhs] = {}; - } - } - value = lhs[rhs]; - } - if (context) { - return {context: lhs, name: rhs, value: value}; - } else { - return value; - } - }; - }, - nonComputedMember: function(left, right, context, create) { - return function(scope, locals, assign, inputs) { - var lhs = left(scope, locals, assign, inputs); - if (create && create !== 1) { - if (lhs && lhs[right] == null) { - lhs[right] = {}; - } - } - var value = lhs != null ? lhs[right] : undefined; - if (context) { - return {context: lhs, name: right, value: value}; - } else { - return value; - } - }; - }, - inputs: function(input, watchId) { - return function(scope, value, locals, inputs) { - if (inputs) return inputs[watchId]; - return input(scope, value, locals); - }; - } -}; - -/** - * @constructor - */ -function Parser(lexer, $filter, options) { - this.ast = new AST(lexer, options); - this.astCompiler = options.csp ? new ASTInterpreter($filter) : - new ASTCompiler($filter); -} - -Parser.prototype = { - constructor: Parser, - - parse: function(text) { - var ast = this.getAst(text); - var fn = this.astCompiler.compile(ast.ast); - fn.literal = isLiteral(ast.ast); - fn.constant = isConstant(ast.ast); - fn.oneTime = ast.oneTime; - return fn; - }, - - getAst: function(exp) { - var oneTime = false; - exp = exp.trim(); - - if (exp.charAt(0) === ':' && exp.charAt(1) === ':') { - oneTime = true; - exp = exp.substring(2); - } - return { - ast: this.ast.ast(exp), - oneTime: oneTime - }; - } -}; - -function getValueOf(value) { - return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value); -} - -/////////////////////////////////// - -/** - * @ngdoc service - * @name $parse - * @kind function - * - * @description - * - * Converts AngularJS {@link guide/expression expression} into a function. - * - * ```js - * var getter = $parse('user.name'); - * var setter = getter.assign; - * var context = {user:{name:'AngularJS'}}; - * var locals = {user:{name:'local'}}; - * - * expect(getter(context)).toEqual('AngularJS'); - * setter(context, 'newValue'); - * expect(context.user.name).toEqual('newValue'); - * expect(getter(context, locals)).toEqual('local'); - * ``` - * - * - * @param {string} expression String expression to compile. - * @returns {function(context, locals)} a function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the strings - * are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values in - * `context`. - * - * The returned function also has the following properties: - * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript - * literal. - * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript - * constant literals. - * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be - * set to a function to change its value on the given context. - * - */ - - -/** - * @ngdoc provider - * @name $parseProvider - * @this - * - * @description - * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse} - * service. - */ -function $ParseProvider() { - var cache = createMap(); - var literals = { - 'true': true, - 'false': false, - 'null': null, - 'undefined': undefined - }; - var identStart, identContinue; - - /** - * @ngdoc method - * @name $parseProvider#addLiteral - * @description - * - * Configure $parse service to add literal values that will be present as literal at expressions. - * - * @param {string} literalName Token for the literal value. The literal name value must be a valid literal name. - * @param {*} literalValue Value for this literal. All literal values must be primitives or `undefined`. - * - **/ - this.addLiteral = function(literalName, literalValue) { - literals[literalName] = literalValue; - }; - - /** - * @ngdoc method - * @name $parseProvider#setIdentifierFns - * - * @description - * - * Allows defining the set of characters that are allowed in AngularJS expressions. The function - * `identifierStart` will get called to know if a given character is a valid character to be the - * first character for an identifier. The function `identifierContinue` will get called to know if - * a given character is a valid character to be a follow-up identifier character. The functions - * `identifierStart` and `identifierContinue` will receive as arguments the single character to be - * identifier and the character code point. These arguments will be `string` and `numeric`. Keep in - * mind that the `string` parameter can be two characters long depending on the character - * representation. It is expected for the function to return `true` or `false`, whether that - * character is allowed or not. - * - * Since this function will be called extensively, keep the implementation of these functions fast, - * as the performance of these functions have a direct impact on the expressions parsing speed. - * - * @param {function=} identifierStart The function that will decide whether the given character is - * a valid identifier start character. - * @param {function=} identifierContinue The function that will decide whether the given character is - * a valid identifier continue character. - */ - this.setIdentifierFns = function(identifierStart, identifierContinue) { - identStart = identifierStart; - identContinue = identifierContinue; - return this; - }; - - this.$get = ['$filter', function($filter) { - var noUnsafeEval = csp().noUnsafeEval; - var $parseOptions = { - csp: noUnsafeEval, - literals: copy(literals), - isIdentifierStart: isFunction(identStart) && identStart, - isIdentifierContinue: isFunction(identContinue) && identContinue - }; - $parse.$$getAst = $$getAst; - return $parse; - - function $parse(exp, interceptorFn) { - var parsedExpression, cacheKey; - - switch (typeof exp) { - case 'string': - exp = exp.trim(); - cacheKey = exp; - - parsedExpression = cache[cacheKey]; - - if (!parsedExpression) { - var lexer = new Lexer($parseOptions); - var parser = new Parser(lexer, $filter, $parseOptions); - parsedExpression = parser.parse(exp); - - cache[cacheKey] = addWatchDelegate(parsedExpression); - } - return addInterceptor(parsedExpression, interceptorFn); - - case 'function': - return addInterceptor(exp, interceptorFn); - - default: - return addInterceptor(noop, interceptorFn); - } - } - - function $$getAst(exp) { - var lexer = new Lexer($parseOptions); - var parser = new Parser(lexer, $filter, $parseOptions); - return parser.getAst(exp).ast; - } - - function expressionInputDirtyCheck(newValue, oldValueOfValue, compareObjectIdentity) { - - if (newValue == null || oldValueOfValue == null) { // null/undefined - return newValue === oldValueOfValue; - } - - if (typeof newValue === 'object') { - - // attempt to convert the value to a primitive type - // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can - // be cheaply dirty-checked - newValue = getValueOf(newValue); - - if (typeof newValue === 'object' && !compareObjectIdentity) { - // objects/arrays are not supported - deep-watching them would be too expensive - return false; - } - - // fall-through to the primitive equality check - } - - //Primitive or NaN - // eslint-disable-next-line no-self-compare - return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue); - } - - function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) { - var inputExpressions = parsedExpression.inputs; - var lastResult; - - if (inputExpressions.length === 1) { - var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails - inputExpressions = inputExpressions[0]; - return scope.$watch(function expressionInputWatch(scope) { - var newInputValue = inputExpressions(scope); - if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf, inputExpressions.isPure)) { - lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]); - oldInputValueOf = newInputValue && getValueOf(newInputValue); - } - return lastResult; - }, listener, objectEquality, prettyPrintExpression); - } - - var oldInputValueOfValues = []; - var oldInputValues = []; - for (var i = 0, ii = inputExpressions.length; i < ii; i++) { - oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails - oldInputValues[i] = null; - } - - return scope.$watch(function expressionInputsWatch(scope) { - var changed = false; - - for (var i = 0, ii = inputExpressions.length; i < ii; i++) { - var newInputValue = inputExpressions[i](scope); - if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i], inputExpressions[i].isPure))) { - oldInputValues[i] = newInputValue; - oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue); - } - } - - if (changed) { - lastResult = parsedExpression(scope, undefined, undefined, oldInputValues); - } - - return lastResult; - }, listener, objectEquality, prettyPrintExpression); - } - - function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) { - var isDone = parsedExpression.literal ? isAllDefined : isDefined; - var unwatch, lastValue; - - var exp = parsedExpression.$$intercepted || parsedExpression; - var post = parsedExpression.$$interceptor || identity; - - var useInputs = parsedExpression.inputs && !exp.inputs; - - // Propogate the literal/inputs/constant attributes - // ... but not oneTime since we are handling it - oneTimeWatch.literal = parsedExpression.literal; - oneTimeWatch.constant = parsedExpression.constant; - oneTimeWatch.inputs = parsedExpression.inputs; - - // Allow other delegates to run on this wrapped expression - addWatchDelegate(oneTimeWatch); - - unwatch = scope.$watch(oneTimeWatch, listener, objectEquality, prettyPrintExpression); - - return unwatch; - - function unwatchIfDone() { - if (isDone(lastValue)) { - unwatch(); - } - } - - function oneTimeWatch(scope, locals, assign, inputs) { - lastValue = useInputs && inputs ? inputs[0] : exp(scope, locals, assign, inputs); - if (isDone(lastValue)) { - scope.$$postDigest(unwatchIfDone); - } - return post(lastValue); - } - } - - function isAllDefined(value) { - var allDefined = true; - forEach(value, function(val) { - if (!isDefined(val)) allDefined = false; - }); - return allDefined; - } - - function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) { - var unwatch = scope.$watch(function constantWatch(scope) { - unwatch(); - return parsedExpression(scope); - }, listener, objectEquality); - return unwatch; - } - - function addWatchDelegate(parsedExpression) { - if (parsedExpression.constant) { - parsedExpression.$$watchDelegate = constantWatchDelegate; - } else if (parsedExpression.oneTime) { - parsedExpression.$$watchDelegate = oneTimeWatchDelegate; - } else if (parsedExpression.inputs) { - parsedExpression.$$watchDelegate = inputsWatchDelegate; - } - - return parsedExpression; - } - - function chainInterceptors(first, second) { - function chainedInterceptor(value) { - return second(first(value)); - } - chainedInterceptor.$stateful = first.$stateful || second.$stateful; - chainedInterceptor.$$pure = first.$$pure && second.$$pure; - - return chainedInterceptor; - } - - function addInterceptor(parsedExpression, interceptorFn) { - if (!interceptorFn) return parsedExpression; - - // Extract any existing interceptors out of the parsedExpression - // to ensure the original parsedExpression is always the $$intercepted - if (parsedExpression.$$interceptor) { - interceptorFn = chainInterceptors(parsedExpression.$$interceptor, interceptorFn); - parsedExpression = parsedExpression.$$intercepted; - } - - var useInputs = false; - - var fn = function interceptedExpression(scope, locals, assign, inputs) { - var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs); - return interceptorFn(value); - }; - - // Maintain references to the interceptor/intercepted - fn.$$intercepted = parsedExpression; - fn.$$interceptor = interceptorFn; - - // Propogate the literal/oneTime/constant attributes - fn.literal = parsedExpression.literal; - fn.oneTime = parsedExpression.oneTime; - fn.constant = parsedExpression.constant; - - // Treat the interceptor like filters. - // If it is not $stateful then only watch its inputs. - // If the expression itself has no inputs then use the full expression as an input. - if (!interceptorFn.$stateful) { - useInputs = !parsedExpression.inputs; - fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression]; - - if (!interceptorFn.$$pure) { - fn.inputs = fn.inputs.map(function(e) { - // Remove the isPure flag of inputs when it is not absolute because they are now wrapped in a - // non-pure interceptor function. - if (e.isPure === PURITY_RELATIVE) { - return function depurifier(s) { return e(s); }; - } - return e; - }); - } - } - - return addWatchDelegate(fn); - } - }]; -} - -/** - * @ngdoc service - * @name $q - * @requires $rootScope - * - * @description - * A service that helps you run functions asynchronously, and use their return values (or exceptions) - * when they are done processing. - * - * This is a [Promises/A+](https://promisesaplus.com/)-compliant implementation of promises/deferred - * objects inspired by [Kris Kowal's Q](https://github.com/kriskowal/q). - * - * $q can be used in two fashions --- one which is more similar to Kris Kowal's Q or jQuery's Deferred - * implementations, and the other which resembles ES6 (ES2015) promises to some degree. - * - * ## $q constructor - * - * The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver` - * function as the first argument. This is similar to the native Promise implementation from ES6, - * see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). - * - * While the constructor-style use is supported, not all of the supporting methods from ES6 promises are - * available yet. - * - * It can be used like so: - * - * ```js - * // for the purpose of this example let's assume that variables `$q` and `okToGreet` - * // are available in the current lexical scope (they could have been injected or passed in). - * - * function asyncGreet(name) { - * // perform some asynchronous operation, resolve or reject the promise when appropriate. - * return $q(function(resolve, reject) { - * setTimeout(function() { - * if (okToGreet(name)) { - * resolve('Hello, ' + name + '!'); - * } else { - * reject('Greeting ' + name + ' is not allowed.'); - * } - * }, 1000); - * }); - * } - * - * var promise = asyncGreet('Robin Hood'); - * promise.then(function(greeting) { - * alert('Success: ' + greeting); - * }, function(reason) { - * alert('Failed: ' + reason); - * }); - * ``` - * - * Note: progress/notify callbacks are not currently supported via the ES6-style interface. - * - * Note: unlike ES6 behavior, an exception thrown in the constructor function will NOT implicitly reject the promise. - * - * However, the more traditional CommonJS-style usage is still available, and documented below. - * - * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an - * interface for interacting with an object that represents the result of an action that is - * performed asynchronously, and may or may not be finished at any given point in time. - * - * From the perspective of dealing with error handling, deferred and promise APIs are to - * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. - * - * ```js - * // for the purpose of this example let's assume that variables `$q` and `okToGreet` - * // are available in the current lexical scope (they could have been injected or passed in). - * - * function asyncGreet(name) { - * var deferred = $q.defer(); - * - * setTimeout(function() { - * deferred.notify('About to greet ' + name + '.'); - * - * if (okToGreet(name)) { - * deferred.resolve('Hello, ' + name + '!'); - * } else { - * deferred.reject('Greeting ' + name + ' is not allowed.'); - * } - * }, 1000); - * - * return deferred.promise; - * } - * - * var promise = asyncGreet('Robin Hood'); - * promise.then(function(greeting) { - * alert('Success: ' + greeting); - * }, function(reason) { - * alert('Failed: ' + reason); - * }, function(update) { - * alert('Got notification: ' + update); - * }); - * ``` - * - * At first it might not be obvious why this extra complexity is worth the trouble. The payoff - * comes in the way of guarantees that promise and deferred APIs make, see - * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md. - * - * Additionally the promise api allows for composition that is very hard to do with the - * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. - * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the - * section on serial or parallel joining of promises. - * - * ## The Deferred API - * - * A new instance of deferred is constructed by calling `$q.defer()`. - * - * The purpose of the deferred object is to expose the associated Promise instance as well as APIs - * that can be used for signaling the successful or unsuccessful completion, as well as the status - * of the task. - * - * **Methods** - * - * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection - * constructed via `$q.reject`, the promise will be rejected instead. - * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to - * resolving it with a rejection constructed via `$q.reject`. - * - `notify(value)` - provides updates on the status of the promise's execution. This may be called - * multiple times before the promise is either resolved or rejected. - * - * **Properties** - * - * - promise – `{Promise}` – promise object associated with this deferred. - * - * - * ## The Promise API - * - * A new promise instance is created when a deferred instance is created and can be retrieved by - * calling `deferred.promise`. - * - * The purpose of the promise object is to allow for interested parties to get access to the result - * of the deferred task when it completes. - * - * **Methods** - * - * - `then(successCallback, [errorCallback], [notifyCallback])` – regardless of when the promise was or - * will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously - * as soon as the result is available. The callbacks are called with a single argument: the result - * or rejection reason. Additionally, the notify callback may be called zero or more times to - * provide a progress indication, before the promise is resolved or rejected. - * - * This method *returns a new promise* which is resolved or rejected via the return value of the - * `successCallback`, `errorCallback` (unless that value is a promise, in which case it is resolved - * with the value which is resolved in that promise using - * [promise chaining](http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promises-queues)). - * It also notifies via the return value of the `notifyCallback` method. The promise cannot be - * resolved or rejected from the notifyCallback method. The errorCallback and notifyCallback - * arguments are optional. - * - * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)` - * - * - `finally(callback, notifyCallback)` – allows you to observe either the fulfillment or rejection of a promise, - * but to do so without modifying the final value. This is useful to release resources or do some - * clean-up that needs to be done whether the promise was rejected or resolved. See the [full - * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for - * more information. - * - * ## Chaining promises - * - * Because calling the `then` method of a promise returns a new derived promise, it is easily - * possible to create a chain of promises: - * - * ```js - * promiseB = promiseA.then(function(result) { - * return result + 1; - * }); - * - * // promiseB will be resolved immediately after promiseA is resolved and its value - * // will be the result of promiseA incremented by 1 - * ``` - * - * It is possible to create chains of any length and since a promise can be resolved with another - * promise (which will defer its resolution further), it is possible to pause/defer resolution of - * the promises at any point in the chain. This makes it possible to implement powerful APIs like - * $http's response interceptors. - * - * - * ## Differences between Kris Kowal's Q and $q - * - * There are two main differences: - * - * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation - * mechanism in AngularJS, which means faster propagation of resolution or rejection into your - * models and avoiding unnecessary browser repaints, which would result in flickering UI. - * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains - * all the important functionality needed for common async tasks. - * - * ## Testing - * - * ```js - * it('should simulate promise', inject(function($q, $rootScope) { - * var deferred = $q.defer(); - * var promise = deferred.promise; - * var resolvedValue; - * - * promise.then(function(value) { resolvedValue = value; }); - * expect(resolvedValue).toBeUndefined(); - * - * // Simulate resolving of promise - * deferred.resolve(123); - * // Note that the 'then' function does not get called synchronously. - * // This is because we want the promise API to always be async, whether or not - * // it got called synchronously or asynchronously. - * expect(resolvedValue).toBeUndefined(); - * - * // Propagate promise resolution to 'then' functions using $apply(). - * $rootScope.$apply(); - * expect(resolvedValue).toEqual(123); - * })); - * ``` - * - * @param {function(function, function)} resolver Function which is responsible for resolving or - * rejecting the newly created promise. The first parameter is a function which resolves the - * promise, the second parameter is a function which rejects the promise. - * - * @returns {Promise} The newly created promise. - */ -/** - * @ngdoc provider - * @name $qProvider - * @this - * - * @description - */ -function $QProvider() { - var errorOnUnhandledRejections = true; - this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { - return qFactory(function(callback) { - $rootScope.$evalAsync(callback); - }, $exceptionHandler, errorOnUnhandledRejections); - }]; - - /** - * @ngdoc method - * @name $qProvider#errorOnUnhandledRejections - * @kind function - * - * @description - * Retrieves or overrides whether to generate an error when a rejected promise is not handled. - * This feature is enabled by default. - * - * @param {boolean=} value Whether to generate an error when a rejected promise is not handled. - * @returns {boolean|ng.$qProvider} Current value when called without a new value or self for - * chaining otherwise. - */ - this.errorOnUnhandledRejections = function(value) { - if (isDefined(value)) { - errorOnUnhandledRejections = value; - return this; - } else { - return errorOnUnhandledRejections; - } - }; -} - -/** @this */ -function $$QProvider() { - var errorOnUnhandledRejections = true; - this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) { - return qFactory(function(callback) { - $browser.defer(callback); - }, $exceptionHandler, errorOnUnhandledRejections); - }]; - - this.errorOnUnhandledRejections = function(value) { - if (isDefined(value)) { - errorOnUnhandledRejections = value; - return this; - } else { - return errorOnUnhandledRejections; - } - }; -} - -/** - * Constructs a promise manager. - * - * @param {function(function)} nextTick Function for executing functions in the next turn. - * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for - * debugging purposes. - * @param {boolean=} errorOnUnhandledRejections Whether an error should be generated on unhandled - * promises rejections. - * @returns {object} Promise manager. - */ -function qFactory(nextTick, exceptionHandler, errorOnUnhandledRejections) { - var $qMinErr = minErr('$q', TypeError); - var queueSize = 0; - var checkQueue = []; - - /** - * @ngdoc method - * @name ng.$q#defer - * @kind function - * - * @description - * Creates a `Deferred` object which represents a task which will finish in the future. - * - * @returns {Deferred} Returns a new instance of deferred. - */ - function defer() { - return new Deferred(); - } - - function Deferred() { - var promise = this.promise = new Promise(); - //Non prototype methods necessary to support unbound execution :/ - this.resolve = function(val) { resolvePromise(promise, val); }; - this.reject = function(reason) { rejectPromise(promise, reason); }; - this.notify = function(progress) { notifyPromise(promise, progress); }; - } - - - function Promise() { - this.$$state = { status: 0 }; - } - - extend(Promise.prototype, { - then: function(onFulfilled, onRejected, progressBack) { - if (isUndefined(onFulfilled) && isUndefined(onRejected) && isUndefined(progressBack)) { - return this; - } - var result = new Promise(); - - this.$$state.pending = this.$$state.pending || []; - this.$$state.pending.push([result, onFulfilled, onRejected, progressBack]); - if (this.$$state.status > 0) scheduleProcessQueue(this.$$state); - - return result; - }, - - 'catch': function(callback) { - return this.then(null, callback); - }, - - 'finally': function(callback, progressBack) { - return this.then(function(value) { - return handleCallback(value, resolve, callback); - }, function(error) { - return handleCallback(error, reject, callback); - }, progressBack); - } - }); - - function processQueue(state) { - var fn, promise, pending; - - pending = state.pending; - state.processScheduled = false; - state.pending = undefined; - try { - for (var i = 0, ii = pending.length; i < ii; ++i) { - markQStateExceptionHandled(state); - promise = pending[i][0]; - fn = pending[i][state.status]; - try { - if (isFunction(fn)) { - resolvePromise(promise, fn(state.value)); - } else if (state.status === 1) { - resolvePromise(promise, state.value); - } else { - rejectPromise(promise, state.value); - } - } catch (e) { - rejectPromise(promise, e); - // This error is explicitly marked for being passed to the $exceptionHandler - if (e && e.$$passToExceptionHandler === true) { - exceptionHandler(e); - } - } - } - } finally { - --queueSize; - if (errorOnUnhandledRejections && queueSize === 0) { - nextTick(processChecks); - } - } - } - - function processChecks() { - // eslint-disable-next-line no-unmodified-loop-condition - while (!queueSize && checkQueue.length) { - var toCheck = checkQueue.shift(); - if (!isStateExceptionHandled(toCheck)) { - markQStateExceptionHandled(toCheck); - var errorMessage = 'Possibly unhandled rejection: ' + toDebugString(toCheck.value); - if (isError(toCheck.value)) { - exceptionHandler(toCheck.value, errorMessage); - } else { - exceptionHandler(errorMessage); - } - } - } - } - - function scheduleProcessQueue(state) { - if (errorOnUnhandledRejections && !state.pending && state.status === 2 && !isStateExceptionHandled(state)) { - if (queueSize === 0 && checkQueue.length === 0) { - nextTick(processChecks); - } - checkQueue.push(state); - } - if (state.processScheduled || !state.pending) return; - state.processScheduled = true; - ++queueSize; - nextTick(function() { processQueue(state); }); - } - - function resolvePromise(promise, val) { - if (promise.$$state.status) return; - if (val === promise) { - $$reject(promise, $qMinErr( - 'qcycle', - 'Expected promise to be resolved with value other than itself \'{0}\'', - val)); - } else { - $$resolve(promise, val); - } - - } - - function $$resolve(promise, val) { - var then; - var done = false; - try { - if (isObject(val) || isFunction(val)) then = val.then; - if (isFunction(then)) { - promise.$$state.status = -1; - then.call(val, doResolve, doReject, doNotify); - } else { - promise.$$state.value = val; - promise.$$state.status = 1; - scheduleProcessQueue(promise.$$state); - } - } catch (e) { - doReject(e); - } - - function doResolve(val) { - if (done) return; - done = true; - $$resolve(promise, val); - } - function doReject(val) { - if (done) return; - done = true; - $$reject(promise, val); - } - function doNotify(progress) { - notifyPromise(promise, progress); - } - } - - function rejectPromise(promise, reason) { - if (promise.$$state.status) return; - $$reject(promise, reason); - } - - function $$reject(promise, reason) { - promise.$$state.value = reason; - promise.$$state.status = 2; - scheduleProcessQueue(promise.$$state); - } - - function notifyPromise(promise, progress) { - var callbacks = promise.$$state.pending; - - if ((promise.$$state.status <= 0) && callbacks && callbacks.length) { - nextTick(function() { - var callback, result; - for (var i = 0, ii = callbacks.length; i < ii; i++) { - result = callbacks[i][0]; - callback = callbacks[i][3]; - try { - notifyPromise(result, isFunction(callback) ? callback(progress) : progress); - } catch (e) { - exceptionHandler(e); - } - } - }); - } - } - - /** - * @ngdoc method - * @name $q#reject - * @kind function - * - * @description - * Creates a promise that is resolved as rejected with the specified `reason`. This api should be - * used to forward rejection in a chain of promises. If you are dealing with the last promise in - * a promise chain, you don't need to worry about it. - * - * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of - * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via - * a promise error callback and you want to forward the error to the promise derived from the - * current promise, you have to "rethrow" the error by returning a rejection constructed via - * `reject`. - * - * ```js - * promiseB = promiseA.then(function(result) { - * // success: do something and resolve promiseB - * // with the old or a new result - * return result; - * }, function(reason) { - * // error: handle the error if possible and - * // resolve promiseB with newPromiseOrValue, - * // otherwise forward the rejection to promiseB - * if (canHandle(reason)) { - * // handle the error and recover - * return newPromiseOrValue; - * } - * return $q.reject(reason); - * }); - * ``` - * - * @param {*} reason Constant, message, exception or an object representing the rejection reason. - * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. - */ - function reject(reason) { - var result = new Promise(); - rejectPromise(result, reason); - return result; - } - - function handleCallback(value, resolver, callback) { - var callbackOutput = null; - try { - if (isFunction(callback)) callbackOutput = callback(); - } catch (e) { - return reject(e); - } - if (isPromiseLike(callbackOutput)) { - return callbackOutput.then(function() { - return resolver(value); - }, reject); - } else { - return resolver(value); - } - } - - /** - * @ngdoc method - * @name $q#when - * @kind function - * - * @description - * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. - * This is useful when you are dealing with an object that might or might not be a promise, or if - * the promise comes from a source that can't be trusted. - * - * @param {*} value Value or a promise - * @param {Function=} successCallback - * @param {Function=} errorCallback - * @param {Function=} progressCallback - * @returns {Promise} Returns a promise of the passed value or promise - */ - - - function when(value, callback, errback, progressBack) { - var result = new Promise(); - resolvePromise(result, value); - return result.then(callback, errback, progressBack); - } - - /** - * @ngdoc method - * @name $q#resolve - * @kind function - * - * @description - * Alias of {@link ng.$q#when when} to maintain naming consistency with ES6. - * - * @param {*} value Value or a promise - * @param {Function=} successCallback - * @param {Function=} errorCallback - * @param {Function=} progressCallback - * @returns {Promise} Returns a promise of the passed value or promise - */ - var resolve = when; - - /** - * @ngdoc method - * @name $q#all - * @kind function - * - * @description - * Combines multiple promises into a single promise that is resolved when all of the input - * promises are resolved. - * - * @param {Array.|Object.} promises An array or hash of promises. - * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values, - * each value corresponding to the promise at the same index/key in the `promises` array/hash. - * If any of the promises is resolved with a rejection, this resulting promise will be rejected - * with the same rejection value. - */ - - function all(promises) { - var result = new Promise(), - counter = 0, - results = isArray(promises) ? [] : {}; - - forEach(promises, function(promise, key) { - counter++; - when(promise).then(function(value) { - results[key] = value; - if (!(--counter)) resolvePromise(result, results); - }, function(reason) { - rejectPromise(result, reason); - }); - }); - - if (counter === 0) { - resolvePromise(result, results); - } - - return result; - } - - /** - * @ngdoc method - * @name $q#race - * @kind function - * - * @description - * Returns a promise that resolves or rejects as soon as one of those promises - * resolves or rejects, with the value or reason from that promise. - * - * @param {Array.|Object.} promises An array or hash of promises. - * @returns {Promise} a promise that resolves or rejects as soon as one of the `promises` - * resolves or rejects, with the value or reason from that promise. - */ - - function race(promises) { - var deferred = defer(); - - forEach(promises, function(promise) { - when(promise).then(deferred.resolve, deferred.reject); - }); - - return deferred.promise; - } - - function $Q(resolver) { - if (!isFunction(resolver)) { - throw $qMinErr('norslvr', 'Expected resolverFn, got \'{0}\'', resolver); - } - - var promise = new Promise(); - - function resolveFn(value) { - resolvePromise(promise, value); - } - - function rejectFn(reason) { - rejectPromise(promise, reason); - } - - resolver(resolveFn, rejectFn); - - return promise; - } - - // Let's make the instanceof operator work for promises, so that - // `new $q(fn) instanceof $q` would evaluate to true. - $Q.prototype = Promise.prototype; - - $Q.defer = defer; - $Q.reject = reject; - $Q.when = when; - $Q.resolve = resolve; - $Q.all = all; - $Q.race = race; - - return $Q; -} - -function isStateExceptionHandled(state) { - return !!state.pur; -} -function markQStateExceptionHandled(state) { - state.pur = true; -} -function markQExceptionHandled(q) { - // Built-in `$q` promises will always have a `$$state` property. This check is to allow - // overwriting `$q` with a different promise library (e.g. Bluebird + angular-bluebird-promises). - // (Currently, this is the only method that might be called with a promise, even if it is not - // created by the built-in `$q`.) - if (q.$$state) { - markQStateExceptionHandled(q.$$state); - } -} - -/** @this */ -function $$RAFProvider() { //rAF - this.$get = ['$window', '$timeout', function($window, $timeout) { - var requestAnimationFrame = $window.requestAnimationFrame || - $window.webkitRequestAnimationFrame; - - var cancelAnimationFrame = $window.cancelAnimationFrame || - $window.webkitCancelAnimationFrame || - $window.webkitCancelRequestAnimationFrame; - - var rafSupported = !!requestAnimationFrame; - var raf = rafSupported - ? function(fn) { - var id = requestAnimationFrame(fn); - return function() { - cancelAnimationFrame(id); - }; - } - : function(fn) { - var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666 - return function() { - $timeout.cancel(timer); - }; - }; - - raf.supported = rafSupported; - - return raf; - }]; -} - -/** - * DESIGN NOTES - * - * The design decisions behind the scope are heavily favored for speed and memory consumption. - * - * The typical use of scope is to watch the expressions, which most of the time return the same - * value as last time so we optimize the operation. - * - * Closures construction is expensive in terms of speed as well as memory: - * - No closures, instead use prototypical inheritance for API - * - Internal state needs to be stored on scope directly, which means that private state is - * exposed as $$____ properties - * - * Loop operations are optimized by using while(count--) { ... } - * - This means that in order to keep the same order of execution as addition we have to add - * items to the array at the beginning (unshift) instead of at the end (push) - * - * Child scopes are created and removed often - * - Using an array would be slow since inserts in the middle are expensive; so we use linked lists - * - * There are fewer watches than observers. This is why you don't want the observer to be implemented - * in the same way as watch. Watch requires return of the initialization function which is expensive - * to construct. - */ - - -/** - * @ngdoc provider - * @name $rootScopeProvider - * @description - * - * Provider for the $rootScope service. - */ - -/** - * @ngdoc method - * @name $rootScopeProvider#digestTtl - * @description - * - * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and - * assuming that the model is unstable. - * - * The current default is 10 iterations. - * - * In complex applications it's possible that the dependencies between `$watch`s will result in - * several digest iterations. However if an application needs more than the default 10 digest - * iterations for its model to stabilize then you should investigate what is causing the model to - * continuously change during the digest. - * - * Increasing the TTL could have performance implications, so you should not change it without - * proper justification. - * - * @param {number} limit The number of digest iterations. - */ - - -/** - * @ngdoc service - * @name $rootScope - * @this - * - * @description - * - * Every application has a single root {@link ng.$rootScope.Scope scope}. - * All other scopes are descendant scopes of the root scope. Scopes provide separation - * between the model and the view, via a mechanism for watching the model for changes. - * They also provide event emission/broadcast and subscription facility. See the - * {@link guide/scope developer guide on scopes}. - */ -function $RootScopeProvider() { - var TTL = 10; - var $rootScopeMinErr = minErr('$rootScope'); - var lastDirtyWatch = null; - var applyAsyncId = null; - - this.digestTtl = function(value) { - if (arguments.length) { - TTL = value; - } - return TTL; - }; - - function createChildScopeClass(parent) { - function ChildScope() { - this.$$watchers = this.$$nextSibling = - this.$$childHead = this.$$childTail = null; - this.$$listeners = {}; - this.$$listenerCount = {}; - this.$$watchersCount = 0; - this.$id = nextUid(); - this.$$ChildScope = null; - this.$$suspended = false; - } - ChildScope.prototype = parent; - return ChildScope; - } - - this.$get = ['$exceptionHandler', '$parse', '$browser', - function($exceptionHandler, $parse, $browser) { - - function destroyChildScope($event) { - $event.currentScope.$$destroyed = true; - } - - function cleanUpScope($scope) { - - // Support: IE 9 only - if (msie === 9) { - // There is a memory leak in IE9 if all child scopes are not disconnected - // completely when a scope is destroyed. So this code will recurse up through - // all this scopes children - // - // See issue https://github.com/angular/angular.js/issues/10706 - if ($scope.$$childHead) { - cleanUpScope($scope.$$childHead); - } - if ($scope.$$nextSibling) { - cleanUpScope($scope.$$nextSibling); - } - } - - // The code below works around IE9 and V8's memory leaks - // - // See: - // - https://code.google.com/p/v8/issues/detail?id=2073#c26 - // - https://github.com/angular/angular.js/issues/6794#issuecomment-38648909 - // - https://github.com/angular/angular.js/issues/1313#issuecomment-10378451 - - $scope.$parent = $scope.$$nextSibling = $scope.$$prevSibling = $scope.$$childHead = - $scope.$$childTail = $scope.$root = $scope.$$watchers = null; - } - - /** - * @ngdoc type - * @name $rootScope.Scope - * - * @description - * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the - * {@link auto.$injector $injector}. Child scopes are created using the - * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when - * compiled HTML template is executed.) See also the {@link guide/scope Scopes guide} for - * an in-depth introduction and usage examples. - * - * - * ## Inheritance - * A scope can inherit from a parent scope, as in this example: - * ```js - var parent = $rootScope; - var child = parent.$new(); - - parent.salutation = "Hello"; - expect(child.salutation).toEqual('Hello'); - - child.salutation = "Welcome"; - expect(child.salutation).toEqual('Welcome'); - expect(parent.salutation).toEqual('Hello'); - * ``` - * - * When interacting with `Scope` in tests, additional helper methods are available on the - * instances of `Scope` type. See {@link ngMock.$rootScope.Scope ngMock Scope} for additional - * details. - * - * - * @param {Object.=} providers Map of service factory which need to be - * provided for the current scope. Defaults to {@link ng}. - * @param {Object.=} instanceCache Provides pre-instantiated services which should - * append/override services provided by `providers`. This is handy - * when unit-testing and having the need to override a default - * service. - * @returns {Object} Newly created scope. - * - */ - function Scope() { - this.$id = nextUid(); - this.$$phase = this.$parent = this.$$watchers = - this.$$nextSibling = this.$$prevSibling = - this.$$childHead = this.$$childTail = null; - this.$root = this; - this.$$destroyed = false; - this.$$suspended = false; - this.$$listeners = {}; - this.$$listenerCount = {}; - this.$$watchersCount = 0; - this.$$isolateBindings = null; - } - - /** - * @ngdoc property - * @name $rootScope.Scope#$id - * - * @description - * Unique scope ID (monotonically increasing) useful for debugging. - */ - - /** - * @ngdoc property - * @name $rootScope.Scope#$parent - * - * @description - * Reference to the parent scope. - */ - - /** - * @ngdoc property - * @name $rootScope.Scope#$root - * - * @description - * Reference to the root scope. - */ - - Scope.prototype = { - constructor: Scope, - /** - * @ngdoc method - * @name $rootScope.Scope#$new - * @kind function - * - * @description - * Creates a new child {@link ng.$rootScope.Scope scope}. - * - * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} event. - * The scope can be removed from the scope hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}. - * - * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is - * desired for the scope and its child scopes to be permanently detached from the parent and - * thus stop participating in model change detection and listener notification by invoking. - * - * @param {boolean} isolate If true, then the scope does not prototypically inherit from the - * parent scope. The scope is isolated, as it can not see parent scope properties. - * When creating widgets, it is useful for the widget to not accidentally read parent - * state. - * - * @param {Scope} [parent=this] The {@link ng.$rootScope.Scope `Scope`} that will be the `$parent` - * of the newly created scope. Defaults to `this` scope if not provided. - * This is used when creating a transclude scope to correctly place it - * in the scope hierarchy while maintaining the correct prototypical - * inheritance. - * - * @returns {Object} The newly created child scope. - * - */ - $new: function(isolate, parent) { - var child; - - parent = parent || this; - - if (isolate) { - child = new Scope(); - child.$root = this.$root; - } else { - // Only create a child scope class if somebody asks for one, - // but cache it to allow the VM to optimize lookups. - if (!this.$$ChildScope) { - this.$$ChildScope = createChildScopeClass(this); - } - child = new this.$$ChildScope(); - } - child.$parent = parent; - child.$$prevSibling = parent.$$childTail; - if (parent.$$childHead) { - parent.$$childTail.$$nextSibling = child; - parent.$$childTail = child; - } else { - parent.$$childHead = parent.$$childTail = child; - } - - // When the new scope is not isolated or we inherit from `this`, and - // the parent scope is destroyed, the property `$$destroyed` is inherited - // prototypically. In all other cases, this property needs to be set - // when the parent scope is destroyed. - // The listener needs to be added after the parent is set - if (isolate || parent !== this) child.$on('$destroy', destroyChildScope); - - return child; - }, - - /** - * @ngdoc method - * @name $rootScope.Scope#$watch - * @kind function - * - * @description - * Registers a `listener` callback to be executed whenever the `watchExpression` changes. - * - * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest - * $digest()} and should return the value that will be watched. (`watchExpression` should not change - * its value when executed multiple times with the same input because it may be executed multiple - * times by {@link ng.$rootScope.Scope#$digest $digest()}. That is, `watchExpression` should be - * [idempotent](http://en.wikipedia.org/wiki/Idempotence).) - * - The `listener` is called only when the value from the current `watchExpression` and the - * previous call to `watchExpression` are not equal (with the exception of the initial run, - * see below). Inequality is determined according to reference inequality, - * [strict comparison](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators) - * via the `!==` Javascript operator, unless `objectEquality == true` - * (see next point) - * - When `objectEquality == true`, inequality of the `watchExpression` is determined - * according to the {@link angular.equals} function. To save the value of the object for - * later comparison, the {@link angular.copy} function is used. This therefore means that - * watching complex objects will have adverse memory and performance implications. - * - This should not be used to watch for changes in objects that are (or contain) - * [File](https://developer.mozilla.org/docs/Web/API/File) objects due to limitations with {@link angular.copy `angular.copy`}. - * - The watch `listener` may change the model, which may trigger other `listener`s to fire. - * This is achieved by rerunning the watchers until no changes are detected. The rerun - * iteration limit is 10 to prevent an infinite loop deadlock. - * - * - * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called, - * you can register a `watchExpression` function with no `listener`. (Be prepared for - * multiple calls to your `watchExpression` because it will execute multiple times in a - * single {@link ng.$rootScope.Scope#$digest $digest} cycle if a change is detected.) - * - * After a watcher is registered with the scope, the `listener` fn is called asynchronously - * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the - * watcher. In rare cases, this is undesirable because the listener is called when the result - * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you - * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the - * listener was called due to initialization. - * - * - * - * @example - * ```js - // let's assume that scope was dependency injected as the $rootScope - var scope = $rootScope; - scope.name = 'misko'; - scope.counter = 0; - - expect(scope.counter).toEqual(0); - scope.$watch('name', function(newValue, oldValue) { - scope.counter = scope.counter + 1; - }); - expect(scope.counter).toEqual(0); - - scope.$digest(); - // the listener is always called during the first $digest loop after it was registered - expect(scope.counter).toEqual(1); - - scope.$digest(); - // but now it will not be called unless the value changes - expect(scope.counter).toEqual(1); - - scope.name = 'adam'; - scope.$digest(); - expect(scope.counter).toEqual(2); - - - - // Using a function as a watchExpression - var food; - scope.foodCounter = 0; - expect(scope.foodCounter).toEqual(0); - scope.$watch( - // This function returns the value being watched. It is called for each turn of the $digest loop - function() { return food; }, - // This is the change listener, called when the value returned from the above function changes - function(newValue, oldValue) { - if ( newValue !== oldValue ) { - // Only increment the counter if the value changed - scope.foodCounter = scope.foodCounter + 1; - } - } - ); - // No digest has been run so the counter will be zero - expect(scope.foodCounter).toEqual(0); - - // Run the digest but since food has not changed count will still be zero - scope.$digest(); - expect(scope.foodCounter).toEqual(0); - - // Update food and run digest. Now the counter will increment - food = 'cheeseburger'; - scope.$digest(); - expect(scope.foodCounter).toEqual(1); - - * ``` - * - * - * - * @param {(function()|string)} watchExpression Expression that is evaluated on each - * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers - * a call to the `listener`. - * - * - `string`: Evaluated as {@link guide/expression expression} - * - `function(scope)`: called with current `scope` as a parameter. - * @param {function(newVal, oldVal, scope)} listener Callback called whenever the value - * of `watchExpression` changes. - * - * - `newVal` contains the current value of the `watchExpression` - * - `oldVal` contains the previous value of the `watchExpression` - * - `scope` refers to the current scope - * @param {boolean=} [objectEquality=false] Compare for object equality using {@link angular.equals} instead of - * comparing for reference equality. - * @returns {function()} Returns a deregistration function for this listener. - */ - $watch: function(watchExp, listener, objectEquality, prettyPrintExpression) { - var get = $parse(watchExp); - var fn = isFunction(listener) ? listener : noop; - - if (get.$$watchDelegate) { - return get.$$watchDelegate(this, fn, objectEquality, get, watchExp); - } - var scope = this, - array = scope.$$watchers, - watcher = { - fn: fn, - last: initWatchVal, - get: get, - exp: prettyPrintExpression || watchExp, - eq: !!objectEquality - }; - - lastDirtyWatch = null; - - if (!array) { - array = scope.$$watchers = []; - array.$$digestWatchIndex = -1; - } - // we use unshift since we use a while loop in $digest for speed. - // the while loop reads in reverse order. - array.unshift(watcher); - array.$$digestWatchIndex++; - incrementWatchersCount(this, 1); - - return function deregisterWatch() { - var index = arrayRemove(array, watcher); - if (index >= 0) { - incrementWatchersCount(scope, -1); - if (index < array.$$digestWatchIndex) { - array.$$digestWatchIndex--; - } - } - lastDirtyWatch = null; - }; - }, - - /** - * @ngdoc method - * @name $rootScope.Scope#$watchGroup - * @kind function - * - * @description - * A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`. - * If any one expression in the collection changes the `listener` is executed. - * - * - The items in the `watchExpressions` array are observed via the standard `$watch` operation. Their return - * values are examined for changes on every call to `$digest`. - * - The `listener` is called whenever any expression in the `watchExpressions` array changes. - * - * @param {Array.} watchExpressions Array of expressions that will be individually - * watched using {@link ng.$rootScope.Scope#$watch $watch()} - * - * @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any - * expression in `watchExpressions` changes - * The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching - * those of `watchExpression` - * and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching - * those of `watchExpression` - * The `scope` refers to the current scope. - * @returns {function()} Returns a de-registration function for all listeners. - */ - $watchGroup: function(watchExpressions, listener) { - var oldValues = new Array(watchExpressions.length); - var newValues = new Array(watchExpressions.length); - var deregisterFns = []; - var self = this; - var changeReactionScheduled = false; - var firstRun = true; - - if (!watchExpressions.length) { - // No expressions means we call the listener ASAP - var shouldCall = true; - self.$evalAsync(function() { - if (shouldCall) listener(newValues, newValues, self); - }); - return function deregisterWatchGroup() { - shouldCall = false; - }; - } - - if (watchExpressions.length === 1) { - // Special case size of one - return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) { - newValues[0] = value; - oldValues[0] = oldValue; - listener(newValues, (value === oldValue) ? newValues : oldValues, scope); - }); - } - - forEach(watchExpressions, function(expr, i) { - var unwatchFn = self.$watch(expr, function watchGroupSubAction(value) { - newValues[i] = value; - if (!changeReactionScheduled) { - changeReactionScheduled = true; - self.$evalAsync(watchGroupAction); - } - }); - deregisterFns.push(unwatchFn); - }); - - function watchGroupAction() { - changeReactionScheduled = false; - - try { - if (firstRun) { - firstRun = false; - listener(newValues, newValues, self); - } else { - listener(newValues, oldValues, self); - } - } finally { - for (var i = 0; i < watchExpressions.length; i++) { - oldValues[i] = newValues[i]; - } - } - } - - return function deregisterWatchGroup() { - while (deregisterFns.length) { - deregisterFns.shift()(); - } - }; - }, - - - /** - * @ngdoc method - * @name $rootScope.Scope#$watchCollection - * @kind function - * - * @description - * Shallow watches the properties of an object and fires whenever any of the properties change - * (for arrays, this implies watching the array items; for object maps, this implies watching - * the properties). If a change is detected, the `listener` callback is fired. - * - * - The `obj` collection is observed via standard $watch operation and is examined on every - * call to $digest() to see if any items have been added, removed, or moved. - * - The `listener` is called whenever anything within the `obj` has changed. Examples include - * adding, removing, and moving items belonging to an object or array. - * - * - * @example - * ```js - $scope.names = ['igor', 'matias', 'misko', 'james']; - $scope.dataCount = 4; - - $scope.$watchCollection('names', function(newNames, oldNames) { - $scope.dataCount = newNames.length; - }); - - expect($scope.dataCount).toEqual(4); - $scope.$digest(); - - //still at 4 ... no changes - expect($scope.dataCount).toEqual(4); - - $scope.names.pop(); - $scope.$digest(); - - //now there's been a change - expect($scope.dataCount).toEqual(3); - * ``` - * - * - * @param {string|function(scope)} obj Evaluated as {@link guide/expression expression}. The - * expression value should evaluate to an object or an array which is observed on each - * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the - * collection will trigger a call to the `listener`. - * - * @param {function(newCollection, oldCollection, scope)} listener a callback function called - * when a change is detected. - * - The `newCollection` object is the newly modified data obtained from the `obj` expression - * - The `oldCollection` object is a copy of the former collection data. - * Due to performance considerations, the`oldCollection` value is computed only if the - * `listener` function declares two or more arguments. - * - The `scope` argument refers to the current scope. - * - * @returns {function()} Returns a de-registration function for this listener. When the - * de-registration function is executed, the internal watch operation is terminated. - */ - $watchCollection: function(obj, listener) { - // Mark the interceptor as - // ... $$pure when literal since the instance will change when any input changes - $watchCollectionInterceptor.$$pure = $parse(obj).literal; - // ... $stateful when non-literal since we must read the state of the collection - $watchCollectionInterceptor.$stateful = !$watchCollectionInterceptor.$$pure; - - var self = this; - // the current value, updated on each dirty-check run - var newValue; - // a shallow copy of the newValue from the last dirty-check run, - // updated to match newValue during dirty-check run - var oldValue; - // a shallow copy of the newValue from when the last change happened - var veryOldValue; - // only track veryOldValue if the listener is asking for it - var trackVeryOldValue = (listener.length > 1); - var changeDetected = 0; - var changeDetector = $parse(obj, $watchCollectionInterceptor); - var internalArray = []; - var internalObject = {}; - var initRun = true; - var oldLength = 0; - - function $watchCollectionInterceptor(_value) { - newValue = _value; - var newLength, key, bothNaN, newItem, oldItem; - - // If the new value is undefined, then return undefined as the watch may be a one-time watch - if (isUndefined(newValue)) return; - - if (!isObject(newValue)) { // if primitive - if (oldValue !== newValue) { - oldValue = newValue; - changeDetected++; - } - } else if (isArrayLike(newValue)) { - if (oldValue !== internalArray) { - // we are transitioning from something which was not an array into array. - oldValue = internalArray; - oldLength = oldValue.length = 0; - changeDetected++; - } - - newLength = newValue.length; - - if (oldLength !== newLength) { - // if lengths do not match we need to trigger change notification - changeDetected++; - oldValue.length = oldLength = newLength; - } - // copy the items to oldValue and look for changes. - for (var i = 0; i < newLength; i++) { - oldItem = oldValue[i]; - newItem = newValue[i]; - - // eslint-disable-next-line no-self-compare - bothNaN = (oldItem !== oldItem) && (newItem !== newItem); - if (!bothNaN && (oldItem !== newItem)) { - changeDetected++; - oldValue[i] = newItem; - } - } - } else { - if (oldValue !== internalObject) { - // we are transitioning from something which was not an object into object. - oldValue = internalObject = {}; - oldLength = 0; - changeDetected++; - } - // copy the items to oldValue and look for changes. - newLength = 0; - for (key in newValue) { - if (hasOwnProperty.call(newValue, key)) { - newLength++; - newItem = newValue[key]; - oldItem = oldValue[key]; - - if (key in oldValue) { - // eslint-disable-next-line no-self-compare - bothNaN = (oldItem !== oldItem) && (newItem !== newItem); - if (!bothNaN && (oldItem !== newItem)) { - changeDetected++; - oldValue[key] = newItem; - } - } else { - oldLength++; - oldValue[key] = newItem; - changeDetected++; - } - } - } - if (oldLength > newLength) { - // we used to have more keys, need to find them and destroy them. - changeDetected++; - for (key in oldValue) { - if (!hasOwnProperty.call(newValue, key)) { - oldLength--; - delete oldValue[key]; - } - } - } - } - return changeDetected; - } - - function $watchCollectionAction() { - if (initRun) { - initRun = false; - listener(newValue, newValue, self); - } else { - listener(newValue, veryOldValue, self); - } - - // make a copy for the next time a collection is changed - if (trackVeryOldValue) { - if (!isObject(newValue)) { - //primitive - veryOldValue = newValue; - } else if (isArrayLike(newValue)) { - veryOldValue = new Array(newValue.length); - for (var i = 0; i < newValue.length; i++) { - veryOldValue[i] = newValue[i]; - } - } else { // if object - veryOldValue = {}; - for (var key in newValue) { - if (hasOwnProperty.call(newValue, key)) { - veryOldValue[key] = newValue[key]; - } - } - } - } - } - - return this.$watch(changeDetector, $watchCollectionAction); - }, - - /** - * @ngdoc method - * @name $rootScope.Scope#$digest - * @kind function - * - * @description - * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and - * its children. Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change - * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} - * until no more listeners are firing. This means that it is possible to get into an infinite - * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of - * iterations exceeds 10. - * - * Usually, you don't call `$digest()` directly in - * {@link ng.directive:ngController controllers} or in - * {@link ng.$compileProvider#directive directives}. - * Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within - * a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`. - * - * If you want to be notified whenever `$digest()` is called, - * you can register a `watchExpression` function with - * {@link ng.$rootScope.Scope#$watch $watch()} with no `listener`. - * - * In unit tests, you may need to call `$digest()` to simulate the scope life cycle. - * - * @example - * ```js - var scope = ...; - scope.name = 'misko'; - scope.counter = 0; - - expect(scope.counter).toEqual(0); - scope.$watch('name', function(newValue, oldValue) { - scope.counter = scope.counter + 1; - }); - expect(scope.counter).toEqual(0); - - scope.$digest(); - // the listener is always called during the first $digest loop after it was registered - expect(scope.counter).toEqual(1); - - scope.$digest(); - // but now it will not be called unless the value changes - expect(scope.counter).toEqual(1); - - scope.name = 'adam'; - scope.$digest(); - expect(scope.counter).toEqual(2); - * ``` - * - */ - $digest: function() { - var watch, value, last, fn, get, - watchers, - dirty, ttl = TTL, - next, current, target = asyncQueue.length ? $rootScope : this, - watchLog = [], - logIdx, asyncTask; - - beginPhase('$digest'); - // Check for changes to browser url that happened in sync before the call to $digest - $browser.$$checkUrlChange(); - - if (this === $rootScope && applyAsyncId !== null) { - // If this is the root scope, and $applyAsync has scheduled a deferred $apply(), then - // cancel the scheduled $apply and flush the queue of expressions to be evaluated. - $browser.defer.cancel(applyAsyncId); - flushApplyAsync(); - } - - lastDirtyWatch = null; - - do { // "while dirty" loop - dirty = false; - current = target; - - // It's safe for asyncQueuePosition to be a local variable here because this loop can't - // be reentered recursively. Calling $digest from a function passed to $evalAsync would - // lead to a '$digest already in progress' error. - for (var asyncQueuePosition = 0; asyncQueuePosition < asyncQueue.length; asyncQueuePosition++) { - try { - asyncTask = asyncQueue[asyncQueuePosition]; - fn = asyncTask.fn; - fn(asyncTask.scope, asyncTask.locals); - } catch (e) { - $exceptionHandler(e); - } - lastDirtyWatch = null; - } - asyncQueue.length = 0; - - traverseScopesLoop: - do { // "traverse the scopes" loop - if ((watchers = !current.$$suspended && current.$$watchers)) { - // process our watches - watchers.$$digestWatchIndex = watchers.length; - while (watchers.$$digestWatchIndex--) { - try { - watch = watchers[watchers.$$digestWatchIndex]; - // Most common watches are on primitives, in which case we can short - // circuit it with === operator, only when === fails do we use .equals - if (watch) { - get = watch.get; - if ((value = get(current)) !== (last = watch.last) && - !(watch.eq - ? equals(value, last) - : (isNumberNaN(value) && isNumberNaN(last)))) { - dirty = true; - lastDirtyWatch = watch; - watch.last = watch.eq ? copy(value, null) : value; - fn = watch.fn; - fn(value, ((last === initWatchVal) ? value : last), current); - if (ttl < 5) { - logIdx = 4 - ttl; - if (!watchLog[logIdx]) watchLog[logIdx] = []; - watchLog[logIdx].push({ - msg: isFunction(watch.exp) ? 'fn: ' + (watch.exp.name || watch.exp.toString()) : watch.exp, - newVal: value, - oldVal: last - }); - } - } else if (watch === lastDirtyWatch) { - // If the most recently dirty watcher is now clean, short circuit since the remaining watchers - // have already been tested. - dirty = false; - break traverseScopesLoop; - } - } - } catch (e) { - $exceptionHandler(e); - } - } - } - - // Insanity Warning: scope depth-first traversal - // yes, this code is a bit crazy, but it works and we have tests to prove it! - // this piece should be kept in sync with the traversal in $broadcast - // (though it differs due to having the extra check for $$suspended and does not - // check $$listenerCount) - if (!(next = ((!current.$$suspended && current.$$watchersCount && current.$$childHead) || - (current !== target && current.$$nextSibling)))) { - while (current !== target && !(next = current.$$nextSibling)) { - current = current.$parent; - } - } - } while ((current = next)); - - // `break traverseScopesLoop;` takes us to here - - if ((dirty || asyncQueue.length) && !(ttl--)) { - clearPhase(); - throw $rootScopeMinErr('infdig', - '{0} $digest() iterations reached. Aborting!\n' + - 'Watchers fired in the last 5 iterations: {1}', - TTL, watchLog); - } - - } while (dirty || asyncQueue.length); - - clearPhase(); - - // postDigestQueuePosition isn't local here because this loop can be reentered recursively. - while (postDigestQueuePosition < postDigestQueue.length) { - try { - postDigestQueue[postDigestQueuePosition++](); - } catch (e) { - $exceptionHandler(e); - } - } - postDigestQueue.length = postDigestQueuePosition = 0; - - // Check for changes to browser url that happened during the $digest - // (for which no event is fired; e.g. via `history.pushState()`) - $browser.$$checkUrlChange(); - }, - - /** - * @ngdoc method - * @name $rootScope.Scope#$suspend - * @kind function - * - * @description - * Suspend watchers of this scope subtree so that they will not be invoked during digest. - * - * This can be used to optimize your application when you know that running those watchers - * is redundant. - * - * **Warning** - * - * Suspending scopes from the digest cycle can have unwanted and difficult to debug results. - * Only use this approach if you are confident that you know what you are doing and have - * ample tests to ensure that bindings get updated as you expect. - * - * Some of the things to consider are: - * - * * Any external event on a directive/component will not trigger a digest while the hosting - * scope is suspended - even if the event handler calls `$apply()` or `$rootScope.$digest()`. - * * Transcluded content exists on a scope that inherits from outside a directive but exists - * as a child of the directive's containing scope. If the containing scope is suspended the - * transcluded scope will also be suspended, even if the scope from which the transcluded - * scope inherits is not suspended. - * * Multiple directives trying to manage the suspended status of a scope can confuse each other: - * * A call to `$suspend()` on an already suspended scope is a no-op. - * * A call to `$resume()` on a non-suspended scope is a no-op. - * * If two directives suspend a scope, then one of them resumes the scope, the scope will no - * longer be suspended. This could result in the other directive believing a scope to be - * suspended when it is not. - * * If a parent scope is suspended then all its descendants will be also excluded from future - * digests whether or not they have been suspended themselves. Note that this also applies to - * isolate child scopes. - * * Calling `$digest()` directly on a descendant of a suspended scope will still run the watchers - * for that scope and its descendants. When digesting we only check whether the current scope is - * locally suspended, rather than checking whether it has a suspended ancestor. - * * Calling `$resume()` on a scope that has a suspended ancestor will not cause the scope to be - * included in future digests until all its ancestors have been resumed. - * * Resolved promises, e.g. from explicit `$q` deferreds and `$http` calls, trigger `$apply()` - * against the `$rootScope` and so will still trigger a global digest even if the promise was - * initiated by a component that lives on a suspended scope. - */ - $suspend: function() { - this.$$suspended = true; - }, - - /** - * @ngdoc method - * @name $rootScope.Scope#$isSuspended - * @kind function - * - * @description - * Call this method to determine if this scope has been explicitly suspended. It will not - * tell you whether an ancestor has been suspended. - * To determine if this scope will be excluded from a digest triggered at the $rootScope, - * for example, you must check all its ancestors: - * - * ``` - * function isExcludedFromDigest(scope) { - * while(scope) { - * if (scope.$isSuspended()) return true; - * scope = scope.$parent; - * } - * return false; - * ``` - * - * Be aware that a scope may not be included in digests if it has a suspended ancestor, - * even if `$isSuspended()` returns false. - * - * @returns true if the current scope has been suspended. - */ - $isSuspended: function() { - return this.$$suspended; - }, - - /** - * @ngdoc method - * @name $rootScope.Scope#$resume - * @kind function - * - * @description - * Resume watchers of this scope subtree in case it was suspended. - * - * See {@link $rootScope.Scope#$suspend} for information about the dangers of using this approach. - */ - $resume: function() { - this.$$suspended = false; - }, - - /** - * @ngdoc event - * @name $rootScope.Scope#$destroy - * @eventType broadcast on scope being destroyed - * - * @description - * Broadcasted when a scope and its children are being destroyed. - * - * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to - * clean up DOM bindings before an element is removed from the DOM. - */ - - /** - * @ngdoc method - * @name $rootScope.Scope#$destroy - * @kind function - * - * @description - * Removes the current scope (and all of its children) from the parent scope. Removal implies - * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer - * propagate to the current scope and its children. Removal also implies that the current - * scope is eligible for garbage collection. - * - * The `$destroy()` is usually used by directives such as - * {@link ng.directive:ngRepeat ngRepeat} for managing the - * unrolling of the loop. - * - * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope. - * Application code can register a `$destroy` event handler that will give it a chance to - * perform any necessary cleanup. - * - * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to - * clean up DOM bindings before an element is removed from the DOM. - */ - $destroy: function() { - // We can't destroy a scope that has been already destroyed. - if (this.$$destroyed) return; - var parent = this.$parent; - - this.$broadcast('$destroy'); - this.$$destroyed = true; - - if (this === $rootScope) { - //Remove handlers attached to window when $rootScope is removed - $browser.$$applicationDestroyed(); - } - - incrementWatchersCount(this, -this.$$watchersCount); - for (var eventName in this.$$listenerCount) { - decrementListenerCount(this, this.$$listenerCount[eventName], eventName); - } - - // sever all the references to parent scopes (after this cleanup, the current scope should - // not be retained by any of our references and should be eligible for garbage collection) - if (parent && parent.$$childHead === this) parent.$$childHead = this.$$nextSibling; - if (parent && parent.$$childTail === this) parent.$$childTail = this.$$prevSibling; - if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; - if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; - - // Disable listeners, watchers and apply/digest methods - this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop; - this.$on = this.$watch = this.$watchGroup = function() { return noop; }; - this.$$listeners = {}; - - // Disconnect the next sibling to prevent `cleanUpScope` destroying those too - this.$$nextSibling = null; - cleanUpScope(this); - }, - - /** - * @ngdoc method - * @name $rootScope.Scope#$eval - * @kind function - * - * @description - * Executes the `expression` on the current scope and returns the result. Any exceptions in - * the expression are propagated (uncaught). This is useful when evaluating AngularJS - * expressions. - * - * @example - * ```js - var scope = ng.$rootScope.Scope(); - scope.a = 1; - scope.b = 2; - - expect(scope.$eval('a+b')).toEqual(3); - expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3); - * ``` - * - * @param {(string|function())=} expression An AngularJS expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with the current `scope` parameter. - * - * @param {(object)=} locals Local variables object, useful for overriding values in scope. - * @returns {*} The result of evaluating the expression. - */ - $eval: function(expr, locals) { - return $parse(expr)(this, locals); - }, - - /** - * @ngdoc method - * @name $rootScope.Scope#$evalAsync - * @kind function - * - * @description - * Executes the expression on the current scope at a later point in time. - * - * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only - * that: - * - * - it will execute after the function that scheduled the evaluation (preferably before DOM - * rendering). - * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after - * `expression` execution. - * - * Any exceptions from the execution of the expression are forwarded to the - * {@link ng.$exceptionHandler $exceptionHandler} service. - * - * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle - * will be scheduled. However, it is encouraged to always call code that changes the model - * from within an `$apply` call. That includes code evaluated via `$evalAsync`. - * - * @param {(string|function())=} expression An AngularJS expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with the current `scope` parameter. - * - * @param {(object)=} locals Local variables object, useful for overriding values in scope. - */ - $evalAsync: function(expr, locals) { - // if we are outside of an $digest loop and this is the first time we are scheduling async - // task also schedule async auto-flush - if (!$rootScope.$$phase && !asyncQueue.length) { - $browser.defer(function() { - if (asyncQueue.length) { - $rootScope.$digest(); - } - }, null, '$evalAsync'); - } - - asyncQueue.push({scope: this, fn: $parse(expr), locals: locals}); - }, - - $$postDigest: function(fn) { - postDigestQueue.push(fn); - }, - - /** - * @ngdoc method - * @name $rootScope.Scope#$apply - * @kind function - * - * @description - * `$apply()` is used to execute an expression in AngularJS from outside of the AngularJS - * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). - * Because we are calling into the AngularJS framework we need to perform proper scope life - * cycle of {@link ng.$exceptionHandler exception handling}, - * {@link ng.$rootScope.Scope#$digest executing watches}. - * - * **Life cycle: Pseudo-Code of `$apply()`** - * - * ```js - function $apply(expr) { - try { - return $eval(expr); - } catch (e) { - $exceptionHandler(e); - } finally { - $root.$digest(); - } - } - * ``` - * - * - * Scope's `$apply()` method transitions through the following stages: - * - * 1. The {@link guide/expression expression} is executed using the - * {@link ng.$rootScope.Scope#$eval $eval()} method. - * 2. Any exceptions from the execution of the expression are forwarded to the - * {@link ng.$exceptionHandler $exceptionHandler} service. - * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the - * expression was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method. - * - * - * @param {(string|function())=} exp An AngularJS expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with current `scope` parameter. - * - * @returns {*} The result of evaluating the expression. - */ - $apply: function(expr) { - try { - beginPhase('$apply'); - try { - return this.$eval(expr); - } finally { - clearPhase(); - } - } catch (e) { - $exceptionHandler(e); - } finally { - try { - $rootScope.$digest(); - } catch (e) { - $exceptionHandler(e); - // eslint-disable-next-line no-unsafe-finally - throw e; - } - } - }, - - /** - * @ngdoc method - * @name $rootScope.Scope#$applyAsync - * @kind function - * - * @description - * Schedule the invocation of $apply to occur at a later time. The actual time difference - * varies across browsers, but is typically around ~10 milliseconds. - * - * This can be used to queue up multiple expressions which need to be evaluated in the same - * digest. - * - * @param {(string|function())=} exp An AngularJS expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with current `scope` parameter. - */ - $applyAsync: function(expr) { - var scope = this; - if (expr) { - applyAsyncQueue.push($applyAsyncExpression); - } - expr = $parse(expr); - scheduleApplyAsync(); - - function $applyAsyncExpression() { - scope.$eval(expr); - } - }, - - /** - * @ngdoc method - * @name $rootScope.Scope#$on - * @kind function - * - * @description - * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for - * discussion of event life cycle. - * - * The event listener function format is: `function(event, args...)`. The `event` object - * passed into the listener has the following attributes: - * - * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or - * `$broadcast`-ed. - * - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the - * event propagates through the scope hierarchy, this property is set to null. - * - `name` - `{string}`: name of the event. - * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel - * further event propagation (available only for events that were `$emit`-ed). - * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag - * to true. - * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called. - * - * @param {string} name Event name to listen on. - * @param {function(event, ...args)} listener Function to call when the event is emitted. - * @returns {function()} Returns a deregistration function for this listener. - */ - $on: function(name, listener) { - var namedListeners = this.$$listeners[name]; - if (!namedListeners) { - this.$$listeners[name] = namedListeners = []; - } - namedListeners.push(listener); - - var current = this; - do { - if (!current.$$listenerCount[name]) { - current.$$listenerCount[name] = 0; - } - current.$$listenerCount[name]++; - } while ((current = current.$parent)); - - var self = this; - return function() { - var indexOfListener = namedListeners.indexOf(listener); - if (indexOfListener !== -1) { - // Use delete in the hope of the browser deallocating the memory for the array entry, - // while not shifting the array indexes of other listeners. - // See issue https://github.com/angular/angular.js/issues/16135 - delete namedListeners[indexOfListener]; - decrementListenerCount(self, 1, name); - } - }; - }, - - - /** - * @ngdoc method - * @name $rootScope.Scope#$emit - * @kind function - * - * @description - * Dispatches an event `name` upwards through the scope hierarchy notifying the - * registered {@link ng.$rootScope.Scope#$on} listeners. - * - * The event life cycle starts at the scope on which `$emit` was called. All - * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get - * notified. Afterwards, the event traverses upwards toward the root scope and calls all - * registered listeners along the way. The event will stop propagating if one of the listeners - * cancels it. - * - * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed - * onto the {@link ng.$exceptionHandler $exceptionHandler} service. - * - * @param {string} name Event name to emit. - * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. - * @return {Object} Event object (see {@link ng.$rootScope.Scope#$on}). - */ - $emit: function(name, args) { - var empty = [], - namedListeners, - scope = this, - stopPropagation = false, - event = { - name: name, - targetScope: scope, - stopPropagation: function() {stopPropagation = true;}, - preventDefault: function() { - event.defaultPrevented = true; - }, - defaultPrevented: false - }, - listenerArgs = concat([event], arguments, 1), - i, length; - - do { - namedListeners = scope.$$listeners[name] || empty; - event.currentScope = scope; - for (i = 0, length = namedListeners.length; i < length; i++) { - - // if listeners were deregistered, defragment the array - if (!namedListeners[i]) { - namedListeners.splice(i, 1); - i--; - length--; - continue; - } - try { - //allow all listeners attached to the current scope to run - namedListeners[i].apply(null, listenerArgs); - } catch (e) { - $exceptionHandler(e); - } - } - //if any listener on the current scope stops propagation, prevent bubbling - if (stopPropagation) { - break; - } - //traverse upwards - scope = scope.$parent; - } while (scope); - - event.currentScope = null; - - return event; - }, - - - /** - * @ngdoc method - * @name $rootScope.Scope#$broadcast - * @kind function - * - * @description - * Dispatches an event `name` downwards to all child scopes (and their children) notifying the - * registered {@link ng.$rootScope.Scope#$on} listeners. - * - * The event life cycle starts at the scope on which `$broadcast` was called. All - * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get - * notified. Afterwards, the event propagates to all direct and indirect scopes of the current - * scope and calls all registered listeners along the way. The event cannot be canceled. - * - * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed - * onto the {@link ng.$exceptionHandler $exceptionHandler} service. - * - * @param {string} name Event name to broadcast. - * @param {...*} args Optional one or more arguments which will be passed onto the event listeners. - * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on} - */ - $broadcast: function(name, args) { - var target = this, - current = target, - next = target, - event = { - name: name, - targetScope: target, - preventDefault: function() { - event.defaultPrevented = true; - }, - defaultPrevented: false - }; - - if (!target.$$listenerCount[name]) return event; - - var listenerArgs = concat([event], arguments, 1), - listeners, i, length; - - //down while you can, then up and next sibling or up and next sibling until back at root - while ((current = next)) { - event.currentScope = current; - listeners = current.$$listeners[name] || []; - for (i = 0, length = listeners.length; i < length; i++) { - // if listeners were deregistered, defragment the array - if (!listeners[i]) { - listeners.splice(i, 1); - i--; - length--; - continue; - } - - try { - listeners[i].apply(null, listenerArgs); - } catch (e) { - $exceptionHandler(e); - } - } - - // Insanity Warning: scope depth-first traversal - // yes, this code is a bit crazy, but it works and we have tests to prove it! - // this piece should be kept in sync with the traversal in $digest - // (though it differs due to having the extra check for $$listenerCount and - // does not check $$suspended) - if (!(next = ((current.$$listenerCount[name] && current.$$childHead) || - (current !== target && current.$$nextSibling)))) { - while (current !== target && !(next = current.$$nextSibling)) { - current = current.$parent; - } - } - } - - event.currentScope = null; - return event; - } - }; - - var $rootScope = new Scope(); - - //The internal queues. Expose them on the $rootScope for debugging/testing purposes. - var asyncQueue = $rootScope.$$asyncQueue = []; - var postDigestQueue = $rootScope.$$postDigestQueue = []; - var applyAsyncQueue = $rootScope.$$applyAsyncQueue = []; - - var postDigestQueuePosition = 0; - - return $rootScope; - - - function beginPhase(phase) { - if ($rootScope.$$phase) { - throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase); - } - - $rootScope.$$phase = phase; - } - - function clearPhase() { - $rootScope.$$phase = null; - } - - function incrementWatchersCount(current, count) { - do { - current.$$watchersCount += count; - } while ((current = current.$parent)); - } - - function decrementListenerCount(current, count, name) { - do { - current.$$listenerCount[name] -= count; - - if (current.$$listenerCount[name] === 0) { - delete current.$$listenerCount[name]; - } - } while ((current = current.$parent)); - } - - /** - * function used as an initial value for watchers. - * because it's unique we can easily tell it apart from other values - */ - function initWatchVal() {} - - function flushApplyAsync() { - while (applyAsyncQueue.length) { - try { - applyAsyncQueue.shift()(); - } catch (e) { - $exceptionHandler(e); - } - } - applyAsyncId = null; - } - - function scheduleApplyAsync() { - if (applyAsyncId === null) { - applyAsyncId = $browser.defer(function() { - $rootScope.$apply(flushApplyAsync); - }, null, '$applyAsync'); - } - } - }]; -} - -/** - * @ngdoc service - * @name $rootElement - * - * @description - * The root element of AngularJS application. This is either the element where {@link - * ng.directive:ngApp ngApp} was declared or the element passed into - * {@link angular.bootstrap}. The element represents the root element of application. It is also the - * location where the application's {@link auto.$injector $injector} service gets - * published, and can be retrieved using `$rootElement.injector()`. - */ - - -// the implementation is in angular.bootstrap - -/** - * @this - * @description - * Private service to sanitize uris for links and images. Used by $compile and $sanitize. - */ -function $$SanitizeUriProvider() { - - var aHrefSanitizationWhitelist = /^\s*(https?|s?ftp|mailto|tel|file):/, - imgSrcSanitizationWhitelist = /^\s*((https?|ftp|file|blob):|data:image\/)/; - - /** - * @description - * Retrieves or overrides the default regular expression that is used for whitelisting of safe - * urls during a[href] sanitization. - * - * The sanitization is a security measure aimed at prevent XSS attacks via HTML anchor links. - * - * Any url due to be assigned to an `a[href]` attribute via interpolation is marked as requiring - * the $sce.URL security context. When interpolation occurs a call is made to `$sce.trustAsUrl(url)` - * which in turn may call `$$sanitizeUri(url, isMedia)` to sanitize the potentially malicious URL. - * - * If the URL matches the `aHrefSanitizationWhitelist` regular expression, it is returned unchanged. - * - * If there is no match the URL is returned prefixed with `'unsafe:'` to ensure that when it is written - * to the DOM it is inactive and potentially malicious code will not be executed. - * - * @param {RegExp=} regexp New regexp to whitelist urls with. - * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for - * chaining otherwise. - */ - this.aHrefSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - aHrefSanitizationWhitelist = regexp; - return this; - } - return aHrefSanitizationWhitelist; - }; - - - /** - * @description - * Retrieves or overrides the default regular expression that is used for whitelisting of safe - * urls during img[src] sanitization. - * - * The sanitization is a security measure aimed at prevent XSS attacks via HTML image src links. - * - * Any URL due to be assigned to an `img[src]` attribute via interpolation is marked as requiring - * the $sce.MEDIA_URL security context. When interpolation occurs a call is made to - * `$sce.trustAsMediaUrl(url)` which in turn may call `$$sanitizeUri(url, isMedia)` to sanitize - * the potentially malicious URL. - * - * If the URL matches the `aImgSanitizationWhitelist` regular expression, it is returned unchanged. - * - * If there is no match the URL is returned prefixed with `'unsafe:'` to ensure that when it is written - * to the DOM it is inactive and potentially malicious code will not be executed. - * - * @param {RegExp=} regexp New regexp to whitelist urls with. - * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for - * chaining otherwise. - */ - this.imgSrcSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - imgSrcSanitizationWhitelist = regexp; - return this; - } - return imgSrcSanitizationWhitelist; - }; - - this.$get = function() { - return function sanitizeUri(uri, isMediaUrl) { - // if (!uri) return uri; - var regex = isMediaUrl ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist; - var normalizedVal = urlResolve(uri && uri.trim()).href; - if (normalizedVal !== '' && !normalizedVal.match(regex)) { - return 'unsafe:' + normalizedVal; - } - return uri; - }; - }; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Any commits to this file should be reviewed with security in mind. * - * Changes to this file can potentially create security vulnerabilities. * - * An approval from 2 Core members with history of modifying * - * this file is required. * - * * - * Does the change somehow allow for arbitrary javascript to be executed? * - * Or allows for someone to change the prototype of built-in objects? * - * Or gives undesired access to variables likes document or window? * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* exported $SceProvider, $SceDelegateProvider */ - -var $sceMinErr = minErr('$sce'); - -var SCE_CONTEXTS = { - // HTML is used when there's HTML rendered (e.g. ng-bind-html, iframe srcdoc binding). - HTML: 'html', - - // Style statements or stylesheets. Currently unused in AngularJS. - CSS: 'css', - - // An URL used in a context where it refers to the source of media, which are not expected to be run - // as scripts, such as an image, audio, video, etc. - MEDIA_URL: 'mediaUrl', - - // An URL used in a context where it does not refer to a resource that loads code. - // A value that can be trusted as a URL can also trusted as a MEDIA_URL. - URL: 'url', - - // RESOURCE_URL is a subtype of URL used where the referred-to resource could be interpreted as - // code. (e.g. ng-include, script src binding, templateUrl) - // A value that can be trusted as a RESOURCE_URL, can also trusted as a URL and a MEDIA_URL. - RESOURCE_URL: 'resourceUrl', - - // Script. Currently unused in AngularJS. - JS: 'js' -}; - -// Helper functions follow. - -var UNDERSCORE_LOWERCASE_REGEXP = /_([a-z])/g; - -function snakeToCamel(name) { - return name - .replace(UNDERSCORE_LOWERCASE_REGEXP, fnCamelCaseReplace); -} - -function adjustMatcher(matcher) { - if (matcher === 'self') { - return matcher; - } else if (isString(matcher)) { - // Strings match exactly except for 2 wildcards - '*' and '**'. - // '*' matches any character except those from the set ':/.?&'. - // '**' matches any character (like .* in a RegExp). - // More than 2 *'s raises an error as it's ill defined. - if (matcher.indexOf('***') > -1) { - throw $sceMinErr('iwcard', - 'Illegal sequence *** in string matcher. String: {0}', matcher); - } - matcher = escapeForRegexp(matcher). - replace(/\\\*\\\*/g, '.*'). - replace(/\\\*/g, '[^:/.?&;]*'); - return new RegExp('^' + matcher + '$'); - } else if (isRegExp(matcher)) { - // The only other type of matcher allowed is a Regexp. - // Match entire URL / disallow partial matches. - // Flags are reset (i.e. no global, ignoreCase or multiline) - return new RegExp('^' + matcher.source + '$'); - } else { - throw $sceMinErr('imatcher', - 'Matchers may only be "self", string patterns or RegExp objects'); - } -} - - -function adjustMatchers(matchers) { - var adjustedMatchers = []; - if (isDefined(matchers)) { - forEach(matchers, function(matcher) { - adjustedMatchers.push(adjustMatcher(matcher)); - }); - } - return adjustedMatchers; -} - - -/** - * @ngdoc service - * @name $sceDelegate - * @kind function - * - * @description - * - * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict - * Contextual Escaping (SCE)} services to AngularJS. - * - * For an overview of this service and the functionnality it provides in AngularJS, see the main - * page for {@link ng.$sce SCE}. The current page is targeted for developers who need to alter how - * SCE works in their application, which shouldn't be needed in most cases. - * - *
    - * AngularJS strongly relies on contextual escaping for the security of bindings: disabling or - * modifying this might cause cross site scripting (XSS) vulnerabilities. For libraries owners, - * changes to this service will also influence users, so be extra careful and document your changes. - *
    - * - * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of - * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS. This is - * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to - * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things - * work because `$sce` delegates to `$sceDelegate` for these operations. - * - * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service. - * - * The default instance of `$sceDelegate` should work out of the box with little pain. While you - * can override it completely to change the behavior of `$sce`, the common case would - * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting - * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as - * templates. Refer {@link ng.$sceDelegateProvider#resourceUrlWhitelist - * $sceDelegateProvider.resourceUrlWhitelist} and {@link - * ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist} - */ - -/** - * @ngdoc provider - * @name $sceDelegateProvider - * @this - * - * @description - * - * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate - * $sceDelegate service}, used as a delegate for {@link ng.$sce Strict Contextual Escaping (SCE)}. - * - * The `$sceDelegateProvider` allows one to get/set the whitelists and blacklists used to ensure - * that the URLs used for sourcing AngularJS templates and other script-running URLs are safe (all - * places that use the `$sce.RESOURCE_URL` context). See - * {@link ng.$sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} - * and - * {@link ng.$sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}, - * - * For the general details about this service in AngularJS, read the main page for {@link ng.$sce - * Strict Contextual Escaping (SCE)}. - * - * **Example**: Consider the following case.
    - * - * - your app is hosted at url `http://myapp.example.com/` - * - but some of your templates are hosted on other domains you control such as - * `http://srv01.assets.example.com/`, `http://srv02.assets.example.com/`, etc. - * - and you have an open redirect at `http://myapp.example.com/clickThru?...`. - * - * Here is what a secure configuration for this scenario might look like: - * - * ``` - * angular.module('myApp', []).config(function($sceDelegateProvider) { - * $sceDelegateProvider.resourceUrlWhitelist([ - * // Allow same origin resource loads. - * 'self', - * // Allow loading from our assets domain. Notice the difference between * and **. - * 'http://srv*.assets.example.com/**' - * ]); - * - * // The blacklist overrides the whitelist so the open redirect here is blocked. - * $sceDelegateProvider.resourceUrlBlacklist([ - * 'http://myapp.example.com/clickThru**' - * ]); - * }); - * ``` - * Note that an empty whitelist will block every resource URL from being loaded, and will require - * you to manually mark each one as trusted with `$sce.trustAsResourceUrl`. However, templates - * requested by {@link ng.$templateRequest $templateRequest} that are present in - * {@link ng.$templateCache $templateCache} will not go through this check. If you have a mechanism - * to populate your templates in that cache at config time, then it is a good idea to remove 'self' - * from that whitelist. This helps to mitigate the security impact of certain types of issues, like - * for instance attacker-controlled `ng-includes`. - */ - -function $SceDelegateProvider() { - this.SCE_CONTEXTS = SCE_CONTEXTS; - - // Resource URLs can also be trusted by policy. - var resourceUrlWhitelist = ['self'], - resourceUrlBlacklist = []; - - /** - * @ngdoc method - * @name $sceDelegateProvider#resourceUrlWhitelist - * @kind function - * - * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value - * provided. This must be an array or null. A snapshot of this array is used so further - * changes to the array are ignored. - * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items - * allowed in this array. - * - * @return {Array} The currently set whitelist array. - * - * @description - * Sets/Gets the whitelist of trusted resource URLs. - * - * The **default value** when no whitelist has been explicitly set is `['self']` allowing only - * same origin resource requests. - * - *
    - * **Note:** the default whitelist of 'self' is not recommended if your app shares its origin - * with other apps! It is a good idea to limit it to only your application's directory. - *
    - */ - this.resourceUrlWhitelist = function(value) { - if (arguments.length) { - resourceUrlWhitelist = adjustMatchers(value); - } - return resourceUrlWhitelist; - }; - - /** - * @ngdoc method - * @name $sceDelegateProvider#resourceUrlBlacklist - * @kind function - * - * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value - * provided. This must be an array or null. A snapshot of this array is used so further - * changes to the array are ignored.

    - * Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items - * allowed in this array.

    - * The typical usage for the blacklist is to **block - * [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as - * these would otherwise be trusted but actually return content from the redirected domain. - *

    - * Finally, **the blacklist overrides the whitelist** and has the final say. - * - * @return {Array} The currently set blacklist array. - * - * @description - * Sets/Gets the blacklist of trusted resource URLs. - * - * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there - * is no blacklist.) - */ - - this.resourceUrlBlacklist = function(value) { - if (arguments.length) { - resourceUrlBlacklist = adjustMatchers(value); - } - return resourceUrlBlacklist; - }; - - this.$get = ['$injector', '$$sanitizeUri', function($injector, $$sanitizeUri) { - - var htmlSanitizer = function htmlSanitizer(html) { - throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); - }; - - if ($injector.has('$sanitize')) { - htmlSanitizer = $injector.get('$sanitize'); - } - - - function matchUrl(matcher, parsedUrl) { - if (matcher === 'self') { - return urlIsSameOrigin(parsedUrl) || urlIsSameOriginAsBaseUrl(parsedUrl); - } else { - // definitely a regex. See adjustMatchers() - return !!matcher.exec(parsedUrl.href); - } - } - - function isResourceUrlAllowedByPolicy(url) { - var parsedUrl = urlResolve(url.toString()); - var i, n, allowed = false; - // Ensure that at least one item from the whitelist allows this url. - for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) { - if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) { - allowed = true; - break; - } - } - if (allowed) { - // Ensure that no item from the blacklist blocked this url. - for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) { - if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) { - allowed = false; - break; - } - } - } - return allowed; - } - - function generateHolderType(Base) { - var holderType = function TrustedValueHolderType(trustedValue) { - this.$$unwrapTrustedValue = function() { - return trustedValue; - }; - }; - if (Base) { - holderType.prototype = new Base(); - } - holderType.prototype.valueOf = function sceValueOf() { - return this.$$unwrapTrustedValue(); - }; - holderType.prototype.toString = function sceToString() { - return this.$$unwrapTrustedValue().toString(); - }; - return holderType; - } - - var trustedValueHolderBase = generateHolderType(), - byType = {}; - - byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.MEDIA_URL] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.URL] = generateHolderType(byType[SCE_CONTEXTS.MEDIA_URL]); - byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]); - - /** - * @ngdoc method - * @name $sceDelegate#trustAs - * - * @description - * Returns a trusted representation of the parameter for the specified context. This trusted - * object will later on be used as-is, without any security check, by bindings or directives - * that require this security context. - * For instance, marking a string as trusted for the `$sce.HTML` context will entirely bypass - * the potential `$sanitize` call in corresponding `$sce.HTML` bindings or directives, such as - * `ng-bind-html`. Note that in most cases you won't need to call this function: if you have the - * sanitizer loaded, passing the value itself will render all the HTML that does not pose a - * security risk. - * - * See {@link ng.$sceDelegate#getTrusted getTrusted} for the function that will consume those - * trusted values, and {@link ng.$sce $sce} for general documentation about strict contextual - * escaping. - * - * @param {string} type The context in which this value is safe for use, e.g. `$sce.URL`, - * `$sce.RESOURCE_URL`, `$sce.HTML`, `$sce.JS` or `$sce.CSS`. - * - * @param {*} value The value that should be considered trusted. - * @return {*} A trusted representation of value, that can be used in the given context. - */ - function trustAs(type, trustedValue) { - var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null); - if (!Constructor) { - throw $sceMinErr('icontext', - 'Attempted to trust a value in invalid context. Context: {0}; Value: {1}', - type, trustedValue); - } - if (trustedValue === null || isUndefined(trustedValue) || trustedValue === '') { - return trustedValue; - } - // All the current contexts in SCE_CONTEXTS happen to be strings. In order to avoid trusting - // mutable objects, we ensure here that the value passed in is actually a string. - if (typeof trustedValue !== 'string') { - throw $sceMinErr('itype', - 'Attempted to trust a non-string value in a content requiring a string: Context: {0}', - type); - } - return new Constructor(trustedValue); - } - - /** - * @ngdoc method - * @name $sceDelegate#valueOf - * - * @description - * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#trustAs - * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link - * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. - * - * If the passed parameter is not a value that had been returned by {@link - * ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}, it must be returned as-is. - * - * @param {*} value The result of a prior {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`} - * call or anything else. - * @return {*} The `value` that was originally provided to {@link ng.$sceDelegate#trustAs - * `$sceDelegate.trustAs`} if `value` is the result of such a call. Otherwise, returns - * `value` unchanged. - */ - function valueOf(maybeTrusted) { - if (maybeTrusted instanceof trustedValueHolderBase) { - return maybeTrusted.$$unwrapTrustedValue(); - } else { - return maybeTrusted; - } - } - - /** - * @ngdoc method - * @name $sceDelegate#getTrusted - * - * @description - * Given an object and a security context in which to assign it, returns a value that's safe to - * use in this context, which was represented by the parameter. To do so, this function either - * unwraps the safe type it has been given (for instance, a {@link ng.$sceDelegate#trustAs - * `$sceDelegate.trustAs`} result), or it might try to sanitize the value given, depending on - * the context and sanitizer availablility. - * - * The contexts that can be sanitized are $sce.MEDIA_URL, $sce.URL and $sce.HTML. The first two are available - * by default, and the third one relies on the `$sanitize` service (which may be loaded through - * the `ngSanitize` module). Furthermore, for $sce.RESOURCE_URL context, a plain string may be - * accepted if the resource url policy defined by {@link ng.$sceDelegateProvider#resourceUrlWhitelist - * `$sceDelegateProvider.resourceUrlWhitelist`} and {@link ng.$sceDelegateProvider#resourceUrlBlacklist - * `$sceDelegateProvider.resourceUrlBlacklist`} accepts that resource. - * - * This function will throw if the safe type isn't appropriate for this context, or if the - * value given cannot be accepted in the context (which might be caused by sanitization not - * being available, or the value not being recognized as safe). - * - *

    - * Disabling auto-escaping is extremely dangerous, it usually creates a Cross Site Scripting - * (XSS) vulnerability in your application. - *
    - * - * @param {string} type The context in which this value is to be used (such as `$sce.HTML`). - * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#trustAs - * `$sceDelegate.trustAs`} call, or anything else (which will not be considered trusted.) - * @return {*} A version of the value that's safe to use in the given context, or throws an - * exception if this is impossible. - */ - function getTrusted(type, maybeTrusted) { - if (maybeTrusted === null || isUndefined(maybeTrusted) || maybeTrusted === '') { - return maybeTrusted; - } - var constructor = (byType.hasOwnProperty(type) ? byType[type] : null); - // If maybeTrusted is a trusted class instance or subclass instance, then unwrap and return - // as-is. - if (constructor && maybeTrusted instanceof constructor) { - return maybeTrusted.$$unwrapTrustedValue(); - } - - // If maybeTrusted is a trusted class instance but not of the correct trusted type - // then unwrap it and allow it to pass through to the rest of the checks - if (isFunction(maybeTrusted.$$unwrapTrustedValue)) { - maybeTrusted = maybeTrusted.$$unwrapTrustedValue(); - } - - // If we get here, then we will either sanitize the value or throw an exception. - if (type === SCE_CONTEXTS.MEDIA_URL || type === SCE_CONTEXTS.URL) { - // we attempt to sanitize non-resource URLs - return $$sanitizeUri(maybeTrusted.toString(), type === SCE_CONTEXTS.MEDIA_URL); - } else if (type === SCE_CONTEXTS.RESOURCE_URL) { - if (isResourceUrlAllowedByPolicy(maybeTrusted)) { - return maybeTrusted; - } else { - throw $sceMinErr('insecurl', - 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: {0}', - maybeTrusted.toString()); - } - } else if (type === SCE_CONTEXTS.HTML) { - // htmlSanitizer throws its own error when no sanitizer is available. - return htmlSanitizer(maybeTrusted); - } - // Default error when the $sce service has no way to make the input safe. - throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); - } - - return { trustAs: trustAs, - getTrusted: getTrusted, - valueOf: valueOf }; - }]; -} - - -/** - * @ngdoc provider - * @name $sceProvider - * @this - * - * @description - * - * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service. - * - enable/disable Strict Contextual Escaping (SCE) in a module - * - override the default implementation with a custom delegate - * - * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}. - */ - -/** - * @ngdoc service - * @name $sce - * @kind function - * - * @description - * - * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS. - * - * ## Strict Contextual Escaping - * - * Strict Contextual Escaping (SCE) is a mode in which AngularJS constrains bindings to only render - * trusted values. Its goal is to assist in writing code in a way that (a) is secure by default, and - * (b) makes auditing for security vulnerabilities such as XSS, clickjacking, etc. a lot easier. - * - * ### Overview - * - * To systematically block XSS security bugs, AngularJS treats all values as untrusted by default in - * HTML or sensitive URL bindings. When binding untrusted values, AngularJS will automatically - * run security checks on them (sanitizations, whitelists, depending on context), or throw when it - * cannot guarantee the security of the result. That behavior depends strongly on contexts: HTML - * can be sanitized, but template URLs cannot, for instance. - * - * To illustrate this, consider the `ng-bind-html` directive. It renders its value directly as HTML: - * we call that the *context*. When given an untrusted input, AngularJS will attempt to sanitize it - * before rendering if a sanitizer is available, and throw otherwise. To bypass sanitization and - * render the input as-is, you will need to mark it as trusted for that context before attempting - * to bind it. - * - * As of version 1.2, AngularJS ships with SCE enabled by default. - * - * ### In practice - * - * Here's an example of a binding in a privileged context: - * - * ``` - * - *
    - * ``` - * - * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE - * disabled, this application allows the user to render arbitrary HTML into the DIV, which would - * be an XSS security bug. In a more realistic example, one may be rendering user comments, blog - * articles, etc. via bindings. (HTML is just one example of a context where rendering user - * controlled input creates security vulnerabilities.) - * - * For the case of HTML, you might use a library, either on the client side, or on the server side, - * to sanitize unsafe HTML before binding to the value and rendering it in the document. - * - * How would you ensure that every place that used these types of bindings was bound to a value that - * was sanitized by your library (or returned as safe for rendering by your server?) How can you - * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some - * properties/fields and forgot to update the binding to the sanitized value? - * - * To be secure by default, AngularJS makes sure bindings go through that sanitization, or - * any similar validation process, unless there's a good reason to trust the given value in this - * context. That trust is formalized with a function call. This means that as a developer, you - * can assume all untrusted bindings are safe. Then, to audit your code for binding security issues, - * you just need to ensure the values you mark as trusted indeed are safe - because they were - * received from your server, sanitized by your library, etc. You can organize your codebase to - * help with this - perhaps allowing only the files in a specific directory to do this. - * Ensuring that the internal API exposed by that code doesn't markup arbitrary values as safe then - * becomes a more manageable task. - * - * In the case of AngularJS' SCE service, one uses {@link ng.$sce#trustAs $sce.trustAs} - * (and shorthand methods such as {@link ng.$sce#trustAsHtml $sce.trustAsHtml}, etc.) to - * build the trusted versions of your values. - * - * ### How does it work? - * - * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#getTrusted - * $sce.getTrusted(context, value)} rather than to the value directly. Think of this function as - * a way to enforce the required security context in your data sink. Directives use {@link - * ng.$sce#parseAs $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs - * the {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals. Also, - * when binding without directives, AngularJS will understand the context of your bindings - * automatically. - * - * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link - * ng.$sce#parseAsHtml $sce.parseAsHtml(binding expression)}. Here's the actual code (slightly - * simplified): - * - * ``` - * var ngBindHtmlDirective = ['$sce', function($sce) { - * return function(scope, element, attr) { - * scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) { - * element.html(value || ''); - * }); - * }; - * }]; - * ``` - * - * ### Impact on loading templates - * - * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as - * `templateUrl`'s specified by {@link guide/directive directives}. - * - * By default, AngularJS only loads templates from the same domain and protocol as the application - * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl - * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or - * protocols, you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist - * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value. - * - * *Please note*: - * The browser's - * [Same Origin Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest) - * and [Cross-Origin Resource Sharing (CORS)](http://www.w3.org/TR/cors/) - * policy apply in addition to this and may further restrict whether the template is successfully - * loaded. This means that without the right CORS policy, loading templates from a different domain - * won't work on all browsers. Also, loading templates from `file://` URL does not work on some - * browsers. - * - * ### This feels like too much overhead - * - * It's important to remember that SCE only applies to interpolation expressions. - * - * If your expressions are constant literals, they're automatically trusted and you don't need to - * call `$sce.trustAs` on them (e.g. - * `
    `) just works (remember to include the - * `ngSanitize` module). The `$sceDelegate` will also use the `$sanitize` service if it is available - * when binding untrusted values to `$sce.HTML` context. - * AngularJS provides an implementation in `angular-sanitize.js`, and if you - * wish to use it, you will also need to depend on the {@link ngSanitize `ngSanitize`} module in - * your application. - * - * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load - * templates in `ng-include` from your application's domain without having to even know about SCE. - * It blocks loading templates from other domains or loading templates over http from an https - * served document. You can change these by setting your own custom {@link - * ng.$sceDelegateProvider#resourceUrlWhitelist whitelists} and {@link - * ng.$sceDelegateProvider#resourceUrlBlacklist blacklists} for matching such URLs. - * - * This significantly reduces the overhead. It is far easier to pay the small overhead and have an - * application that's secure and can be audited to verify that with much more ease than bolting - * security onto an application later. - * - * - * ### What trusted context types are supported? - * - * | Context | Notes | - * |---------------------|----------------| - * | `$sce.HTML` | For HTML that's safe to source into the application. The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. If an unsafe value is encountered and the {@link ngSanitize $sanitize} module is present this will sanitize the value instead of throwing an error. | - * | `$sce.CSS` | For CSS that's safe to source into the application. Currently unused. Feel free to use it in your own directives. | - * | `$sce.MEDIA_URL` | For URLs that are safe to render as media. Is automatically converted from string by sanitizing when needed. | - * | `$sce.URL` | For URLs that are safe to follow as links. Is automatically converted from string by sanitizing when needed. Note that `$sce.URL` makes a stronger statement about the URL than `$sce.MEDIA_URL` does and therefore contexts requiring values trusted for `$sce.URL` can be used anywhere that values trusted for `$sce.MEDIA_URL` are required.| - * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contents are also safe to include in your application. Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)

    Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` or `$sce.MEDIA_URL` do and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` or `$sce.MEDIA_URL` are required.

    The {@link $sceDelegateProvider#resourceUrlWhitelist $sceDelegateProvider#resourceUrlWhitelist()} and {@link $sceDelegateProvider#resourceUrlBlacklist $sceDelegateProvider#resourceUrlBlacklist()} can be used to restrict trusted origins for `RESOURCE_URL` | - * | `$sce.JS` | For JavaScript that is safe to execute in your application's context. Currently unused. Feel free to use it in your own directives. | - * - * - *
    - * Be aware that, before AngularJS 1.7.0, `a[href]` and `img[src]` used to sanitize their - * interpolated values directly rather than rely upon {@link ng.$sce#getTrusted `$sce.getTrusted`}. - * - * **As of 1.7.0, this is no longer the case.** - * - * Now such interpolations are marked as requiring `$sce.URL` (for `a[href]`) or `$sce.MEDIA_URL` - * (for `img[src]`), so that the sanitization happens (via `$sce.getTrusted...`) when the `$interpolate` - * service evaluates the expressions. - *
    - * - * There are no CSS or JS context bindings in AngularJS currently, so their corresponding `$sce.trustAs` - * functions aren't useful yet. This might evolve. - * - * ### Format of items in {@link ng.$sceDelegateProvider#resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#resourceUrlBlacklist Blacklist} - * - * Each element in these arrays must be one of the following: - * - * - **'self'** - * - The special **string**, `'self'`, can be used to match against all URLs of the **same - * domain** as the application document using the **same protocol**. - * - **String** (except the special value `'self'`) - * - The string is matched against the full *normalized / absolute URL* of the resource - * being tested (substring matches are not good enough.) - * - There are exactly **two wildcard sequences** - `*` and `**`. All other characters - * match themselves. - * - `*`: matches zero or more occurrences of any character other than one of the following 6 - * characters: '`:`', '`/`', '`.`', '`?`', '`&`' and '`;`'. It's a useful wildcard for use - * in a whitelist. - * - `**`: matches zero or more occurrences of *any* character. As such, it's not - * appropriate for use in a scheme, domain, etc. as it would match too much. (e.g. - * http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might - * not have been the intention.) Its usage at the very end of the path is ok. (e.g. - * http://foo.example.com/templates/**). - * - **RegExp** (*see caveat below*) - * - *Caveat*: While regular expressions are powerful and offer great flexibility, their syntax - * (and all the inevitable escaping) makes them *harder to maintain*. It's easy to - * accidentally introduce a bug when one updates a complex expression (imho, all regexes should - * have good test coverage). For instance, the use of `.` in the regex is correct only in a - * small number of cases. A `.` character in the regex used when matching the scheme or a - * subdomain could be matched against a `:` or literal `.` that was likely not intended. It - * is highly recommended to use the string patterns and only fall back to regular expressions - * as a last resort. - * - The regular expression must be an instance of RegExp (i.e. not a string.) It is - * matched against the **entire** *normalized / absolute URL* of the resource being tested - * (even when the RegExp did not have the `^` and `$` codes.) In addition, any flags - * present on the RegExp (such as multiline, global, ignoreCase) are ignored. - * - If you are generating your JavaScript from some other templating engine (not - * recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)), - * remember to escape your regular expression (and be aware that you might need more than - * one level of escaping depending on your templating engine and the way you interpolated - * the value.) Do make use of your platform's escaping mechanism as it might be good - * enough before coding your own. E.g. Ruby has - * [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape) - * and Python has [re.escape](http://docs.python.org/library/re.html#re.escape). - * Javascript lacks a similar built in function for escaping. Take a look at Google - * Closure library's [goog.string.regExpEscape(s)]( - * http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962). - * - * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example. - * - * ### Show me an example using SCE. - * - * - * - *
    - *

    - * User comments
    - * By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when - * $sanitize is available. If $sanitize isn't available, this results in an error instead of an - * exploit. - *
    - *
    - * {{userComment.name}}: - * - *
    - *
    - *
    - *
    - *
    - * - * - * angular.module('mySceApp', ['ngSanitize']) - * .controller('AppController', ['$http', '$templateCache', '$sce', - * function AppController($http, $templateCache, $sce) { - * var self = this; - * $http.get('test_data.json', {cache: $templateCache}).then(function(response) { - * self.userComments = response.data; - * }); - * self.explicitlyTrustedHtml = $sce.trustAsHtml( - * 'Hover over this text.'); - * }]); - * - * - * - * [ - * { "name": "Alice", - * "htmlComment": - * "Is anyone reading this?" - * }, - * { "name": "Bob", - * "htmlComment": "Yes! Am I the only other one?" - * } - * ] - * - * - * - * describe('SCE doc demo', function() { - * it('should sanitize untrusted values', function() { - * expect(element.all(by.css('.htmlComment')).first().getAttribute('innerHTML')) - * .toBe('Is anyone reading this?'); - * }); - * - * it('should NOT sanitize explicitly trusted values', function() { - * expect(element(by.id('explicitlyTrustedHtml')).getAttribute('innerHTML')).toBe( - * 'Hover over this text.'); - * }); - * }); - * - *
    - * - * - * - * ## Can I disable SCE completely? - * - * Yes, you can. However, this is strongly discouraged. SCE gives you a lot of security benefits - * for little coding overhead. It will be much harder to take an SCE disabled application and - * either secure it on your own or enable SCE at a later stage. It might make sense to disable SCE - * for cases where you have a lot of existing code that was written before SCE was introduced and - * you're migrating them a module at a time. Also do note that this is an app-wide setting, so if - * you are writing a library, you will cause security bugs applications using it. - * - * That said, here's how you can completely disable SCE: - * - * ``` - * angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) { - * // Completely disable SCE. For demonstration purposes only! - * // Do not use in new projects or libraries. - * $sceProvider.enabled(false); - * }); - * ``` - * - */ - -function $SceProvider() { - var enabled = true; - - /** - * @ngdoc method - * @name $sceProvider#enabled - * @kind function - * - * @param {boolean=} value If provided, then enables/disables SCE application-wide. - * @return {boolean} True if SCE is enabled, false otherwise. - * - * @description - * Enables/disables SCE and returns the current value. - */ - this.enabled = function(value) { - if (arguments.length) { - enabled = !!value; - } - return enabled; - }; - - - /* Design notes on the default implementation for SCE. - * - * The API contract for the SCE delegate - * ------------------------------------- - * The SCE delegate object must provide the following 3 methods: - * - * - trustAs(contextEnum, value) - * This method is used to tell the SCE service that the provided value is OK to use in the - * contexts specified by contextEnum. It must return an object that will be accepted by - * getTrusted() for a compatible contextEnum and return this value. - * - * - valueOf(value) - * For values that were not produced by trustAs(), return them as is. For values that were - * produced by trustAs(), return the corresponding input value to trustAs. Basically, if - * trustAs is wrapping the given values into some type, this operation unwraps it when given - * such a value. - * - * - getTrusted(contextEnum, value) - * This function should return the value that is safe to use in the context specified by - * contextEnum or throw and exception otherwise. - * - * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be - * opaque or wrapped in some holder object. That happens to be an implementation detail. For - * instance, an implementation could maintain a registry of all trusted objects by context. In - * such a case, trustAs() would return the same object that was passed in. getTrusted() would - * return the same object passed in if it was found in the registry under a compatible context or - * throw an exception otherwise. An implementation might only wrap values some of the time based - * on some criteria. getTrusted() might return a value and not throw an exception for special - * constants or objects even if not wrapped. All such implementations fulfill this contract. - * - * - * A note on the inheritance model for SCE contexts - * ------------------------------------------------ - * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types. This - * is purely an implementation details. - * - * The contract is simply this: - * - * getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value) - * will also succeed. - * - * Inheritance happens to capture this in a natural way. In some future, we may not use - * inheritance anymore. That is OK because no code outside of sce.js and sceSpecs.js would need to - * be aware of this detail. - */ - - this.$get = ['$parse', '$sceDelegate', function( - $parse, $sceDelegate) { - // Support: IE 9-11 only - // Prereq: Ensure that we're not running in IE<11 quirks mode. In that mode, IE < 11 allow - // the "expression(javascript expression)" syntax which is insecure. - if (enabled && msie < 8) { - throw $sceMinErr('iequirks', - 'Strict Contextual Escaping does not support Internet Explorer version < 11 in quirks ' + - 'mode. You can fix this by adding the text to the top of your HTML ' + - 'document. See http://docs.angularjs.org/api/ng.$sce for more information.'); - } - - var sce = shallowCopy(SCE_CONTEXTS); - - /** - * @ngdoc method - * @name $sce#isEnabled - * @kind function - * - * @return {Boolean} True if SCE is enabled, false otherwise. If you want to set the value, you - * have to do it at module config time on {@link ng.$sceProvider $sceProvider}. - * - * @description - * Returns a boolean indicating if SCE is enabled. - */ - sce.isEnabled = function() { - return enabled; - }; - sce.trustAs = $sceDelegate.trustAs; - sce.getTrusted = $sceDelegate.getTrusted; - sce.valueOf = $sceDelegate.valueOf; - - if (!enabled) { - sce.trustAs = sce.getTrusted = function(type, value) { return value; }; - sce.valueOf = identity; - } - - /** - * @ngdoc method - * @name $sce#parseAs - * - * @description - * Converts AngularJS {@link guide/expression expression} into a function. This is like {@link - * ng.$parse $parse} and is identical when the expression is a literal constant. Otherwise, it - * wraps the expression in a call to {@link ng.$sce#getTrusted $sce.getTrusted(*type*, - * *result*)} - * - * @param {string} type The SCE context in which this result will be used. - * @param {string} expression String expression to compile. - * @return {function(context, locals)} A function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the - * strings are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values - * in `context`. - */ - sce.parseAs = function sceParseAs(type, expr) { - var parsed = $parse(expr); - if (parsed.literal && parsed.constant) { - return parsed; - } else { - return $parse(expr, function(value) { - return sce.getTrusted(type, value); - }); - } - }; - - /** - * @ngdoc method - * @name $sce#trustAs - * - * @description - * Delegates to {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs`}. As such, returns a - * wrapped object that represents your value, and the trust you have in its safety for the given - * context. AngularJS can then use that value as-is in bindings of the specified secure context. - * This is used in bindings for `ng-bind-html`, `ng-include`, and most `src` attribute - * interpolations. See {@link ng.$sce $sce} for strict contextual escaping. - * - * @param {string} type The context in which this value is safe for use, e.g. `$sce.URL`, - * `$sce.RESOURCE_URL`, `$sce.HTML`, `$sce.JS` or `$sce.CSS`. - * - * @param {*} value The value that that should be considered trusted. - * @return {*} A wrapped version of value that can be used as a trusted variant of your `value` - * in the context you specified. - */ - - /** - * @ngdoc method - * @name $sce#trustAsHtml - * - * @description - * Shorthand method. `$sce.trustAsHtml(value)` → - * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.HTML, value)`} - * - * @param {*} value The value to mark as trusted for `$sce.HTML` context. - * @return {*} A wrapped version of value that can be used as a trusted variant of your `value` - * in `$sce.HTML` context (like `ng-bind-html`). - */ - - /** - * @ngdoc method - * @name $sce#trustAsCss - * - * @description - * Shorthand method. `$sce.trustAsCss(value)` → - * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.CSS, value)`} - * - * @param {*} value The value to mark as trusted for `$sce.CSS` context. - * @return {*} A wrapped version of value that can be used as a trusted variant - * of your `value` in `$sce.CSS` context. This context is currently unused, so there are - * almost no reasons to use this function so far. - */ - - /** - * @ngdoc method - * @name $sce#trustAsUrl - * - * @description - * Shorthand method. `$sce.trustAsUrl(value)` → - * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.URL, value)`} - * - * @param {*} value The value to mark as trusted for `$sce.URL` context. - * @return {*} A wrapped version of value that can be used as a trusted variant of your `value` - * in `$sce.URL` context. That context is currently unused, so there are almost no reasons - * to use this function so far. - */ - - /** - * @ngdoc method - * @name $sce#trustAsResourceUrl - * - * @description - * Shorthand method. `$sce.trustAsResourceUrl(value)` → - * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`} - * - * @param {*} value The value to mark as trusted for `$sce.RESOURCE_URL` context. - * @return {*} A wrapped version of value that can be used as a trusted variant of your `value` - * in `$sce.RESOURCE_URL` context (template URLs in `ng-include`, most `src` attribute - * bindings, ...) - */ - - /** - * @ngdoc method - * @name $sce#trustAsJs - * - * @description - * Shorthand method. `$sce.trustAsJs(value)` → - * {@link ng.$sceDelegate#trustAs `$sceDelegate.trustAs($sce.JS, value)`} - * - * @param {*} value The value to mark as trusted for `$sce.JS` context. - * @return {*} A wrapped version of value that can be used as a trusted variant of your `value` - * in `$sce.JS` context. That context is currently unused, so there are almost no reasons to - * use this function so far. - */ - - /** - * @ngdoc method - * @name $sce#getTrusted - * - * @description - * Delegates to {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted`}. As such, - * takes any input, and either returns a value that's safe to use in the specified context, - * or throws an exception. This function is aware of trusted values created by the `trustAs` - * function and its shorthands, and when contexts are appropriate, returns the unwrapped value - * as-is. Finally, this function can also throw when there is no way to turn `maybeTrusted` in a - * safe value (e.g., no sanitization is available or possible.) - * - * @param {string} type The context in which this value is to be used. - * @param {*} maybeTrusted The result of a prior {@link ng.$sce#trustAs - * `$sce.trustAs`} call, or anything else (which will not be considered trusted.) - * @return {*} A version of the value that's safe to use in the given context, or throws an - * exception if this is impossible. - */ - - /** - * @ngdoc method - * @name $sce#getTrustedHtml - * - * @description - * Shorthand method. `$sce.getTrustedHtml(value)` → - * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`} - * - * @param {*} value The value to pass to `$sce.getTrusted`. - * @return {*} The return value of `$sce.getTrusted($sce.HTML, value)` - */ - - /** - * @ngdoc method - * @name $sce#getTrustedCss - * - * @description - * Shorthand method. `$sce.getTrustedCss(value)` → - * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`} - * - * @param {*} value The value to pass to `$sce.getTrusted`. - * @return {*} The return value of `$sce.getTrusted($sce.CSS, value)` - */ - - /** - * @ngdoc method - * @name $sce#getTrustedUrl - * - * @description - * Shorthand method. `$sce.getTrustedUrl(value)` → - * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.URL, value)`} - * - * @param {*} value The value to pass to `$sce.getTrusted`. - * @return {*} The return value of `$sce.getTrusted($sce.URL, value)` - */ - - /** - * @ngdoc method - * @name $sce#getTrustedResourceUrl - * - * @description - * Shorthand method. `$sce.getTrustedResourceUrl(value)` → - * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`} - * - * @param {*} value The value to pass to `$sceDelegate.getTrusted`. - * @return {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)` - */ - - /** - * @ngdoc method - * @name $sce#getTrustedJs - * - * @description - * Shorthand method. `$sce.getTrustedJs(value)` → - * {@link ng.$sceDelegate#getTrusted `$sceDelegate.getTrusted($sce.JS, value)`} - * - * @param {*} value The value to pass to `$sce.getTrusted`. - * @return {*} The return value of `$sce.getTrusted($sce.JS, value)` - */ - - /** - * @ngdoc method - * @name $sce#parseAsHtml - * - * @description - * Shorthand method. `$sce.parseAsHtml(expression string)` → - * {@link ng.$sce#parseAs `$sce.parseAs($sce.HTML, value)`} - * - * @param {string} expression String expression to compile. - * @return {function(context, locals)} A function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the - * strings are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values - * in `context`. - */ - - /** - * @ngdoc method - * @name $sce#parseAsCss - * - * @description - * Shorthand method. `$sce.parseAsCss(value)` → - * {@link ng.$sce#parseAs `$sce.parseAs($sce.CSS, value)`} - * - * @param {string} expression String expression to compile. - * @return {function(context, locals)} A function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the - * strings are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values - * in `context`. - */ - - /** - * @ngdoc method - * @name $sce#parseAsUrl - * - * @description - * Shorthand method. `$sce.parseAsUrl(value)` → - * {@link ng.$sce#parseAs `$sce.parseAs($sce.URL, value)`} - * - * @param {string} expression String expression to compile. - * @return {function(context, locals)} A function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the - * strings are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values - * in `context`. - */ - - /** - * @ngdoc method - * @name $sce#parseAsResourceUrl - * - * @description - * Shorthand method. `$sce.parseAsResourceUrl(value)` → - * {@link ng.$sce#parseAs `$sce.parseAs($sce.RESOURCE_URL, value)`} - * - * @param {string} expression String expression to compile. - * @return {function(context, locals)} A function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the - * strings are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values - * in `context`. - */ - - /** - * @ngdoc method - * @name $sce#parseAsJs - * - * @description - * Shorthand method. `$sce.parseAsJs(value)` → - * {@link ng.$sce#parseAs `$sce.parseAs($sce.JS, value)`} - * - * @param {string} expression String expression to compile. - * @return {function(context, locals)} A function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the - * strings are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values - * in `context`. - */ - - // Shorthand delegations. - var parse = sce.parseAs, - getTrusted = sce.getTrusted, - trustAs = sce.trustAs; - - forEach(SCE_CONTEXTS, function(enumValue, name) { - var lName = lowercase(name); - sce[snakeToCamel('parse_as_' + lName)] = function(expr) { - return parse(enumValue, expr); - }; - sce[snakeToCamel('get_trusted_' + lName)] = function(value) { - return getTrusted(enumValue, value); - }; - sce[snakeToCamel('trust_as_' + lName)] = function(value) { - return trustAs(enumValue, value); - }; - }); - - return sce; - }]; -} - -/* exported $SnifferProvider */ - -/** - * !!! This is an undocumented "private" service !!! - * - * @name $sniffer - * @requires $window - * @requires $document - * @this - * - * @property {boolean} history Does the browser support html5 history api ? - * @property {boolean} transitions Does the browser support CSS transition events ? - * @property {boolean} animations Does the browser support CSS animation events ? - * - * @description - * This is very simple implementation of testing browser's features. - */ -function $SnifferProvider() { - this.$get = ['$window', '$document', function($window, $document) { - var eventSupport = {}, - // Chrome Packaged Apps are not allowed to access `history.pushState`. - // If not sandboxed, they can be detected by the presence of `chrome.app.runtime` - // (see https://developer.chrome.com/apps/api_index). If sandboxed, they can be detected by - // the presence of an extension runtime ID and the absence of other Chrome runtime APIs - // (see https://developer.chrome.com/apps/manifest/sandbox). - // (NW.js apps have access to Chrome APIs, but do support `history`.) - isNw = $window.nw && $window.nw.process, - isChromePackagedApp = - !isNw && - $window.chrome && - ($window.chrome.app && $window.chrome.app.runtime || - !$window.chrome.app && $window.chrome.runtime && $window.chrome.runtime.id), - hasHistoryPushState = !isChromePackagedApp && $window.history && $window.history.pushState, - android = - toInt((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]), - boxee = /Boxee/i.test(($window.navigator || {}).userAgent), - document = $document[0] || {}, - bodyStyle = document.body && document.body.style, - transitions = false, - animations = false; - - if (bodyStyle) { - // Support: Android <5, Blackberry Browser 10, default Chrome in Android 4.4.x - // Mentioned browsers need a -webkit- prefix for transitions & animations. - transitions = !!('transition' in bodyStyle || 'webkitTransition' in bodyStyle); - animations = !!('animation' in bodyStyle || 'webkitAnimation' in bodyStyle); - } - - - return { - // Android has history.pushState, but it does not update location correctly - // so let's not use the history API at all. - // http://code.google.com/p/android/issues/detail?id=17471 - // https://github.com/angular/angular.js/issues/904 - - // older webkit browser (533.9) on Boxee box has exactly the same problem as Android has - // so let's not use the history API also - // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined - history: !!(hasHistoryPushState && !(android < 4) && !boxee), - hasEvent: function(event) { - // Support: IE 9-11 only - // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have - // it. In particular the event is not fired when backspace or delete key are pressed or - // when cut operation is performed. - // IE10+ implements 'input' event but it erroneously fires under various situations, - // e.g. when placeholder changes, or a form is focused. - if (event === 'input' && msie) return false; - - if (isUndefined(eventSupport[event])) { - var divElm = document.createElement('div'); - eventSupport[event] = 'on' + event in divElm; - } - - return eventSupport[event]; - }, - csp: csp(), - transitions: transitions, - animations: animations, - android: android - }; - }]; -} - -/** - * ! This is a private undocumented service ! - * - * @name $$taskTrackerFactory - * @description - * A function to create `TaskTracker` instances. - * - * A `TaskTracker` can keep track of pending tasks (grouped by type) and can notify interested - * parties when all pending tasks (or tasks of a specific type) have been completed. - * - * @param {$log} log - A logger instance (such as `$log`). Used to log error during callback - * execution. - * - * @this - */ -function $$TaskTrackerFactoryProvider() { - this.$get = valueFn(function(log) { return new TaskTracker(log); }); -} - -function TaskTracker(log) { - var self = this; - var taskCounts = {}; - var taskCallbacks = []; - - var ALL_TASKS_TYPE = self.ALL_TASKS_TYPE = '$$all$$'; - var DEFAULT_TASK_TYPE = self.DEFAULT_TASK_TYPE = '$$default$$'; - - /** - * Execute the specified function and decrement the appropriate `taskCounts` counter. - * If the counter reaches 0, all corresponding `taskCallbacks` are executed. - * - * @param {Function} fn - The function to execute. - * @param {string=} [taskType=DEFAULT_TASK_TYPE] - The type of task that is being completed. - */ - self.completeTask = completeTask; - - /** - * Increase the task count for the specified task type (or the default task type if non is - * specified). - * - * @param {string=} [taskType=DEFAULT_TASK_TYPE] - The type of task whose count will be increased. - */ - self.incTaskCount = incTaskCount; - - /** - * Execute the specified callback when all pending tasks have been completed. - * - * If there are no pending tasks, the callback is executed immediately. You can optionally limit - * the tasks that will be waited for to a specific type, by passing a `taskType`. - * - * @param {function} callback - The function to call when there are no pending tasks. - * @param {string=} [taskType=ALL_TASKS_TYPE] - The type of tasks that will be waited for. - */ - self.notifyWhenNoPendingTasks = notifyWhenNoPendingTasks; - - function completeTask(fn, taskType) { - taskType = taskType || DEFAULT_TASK_TYPE; - - try { - fn(); - } finally { - decTaskCount(taskType); - - var countForType = taskCounts[taskType]; - var countForAll = taskCounts[ALL_TASKS_TYPE]; - - // If at least one of the queues (`ALL_TASKS_TYPE` or `taskType`) is empty, run callbacks. - if (!countForAll || !countForType) { - var getNextCallback = !countForAll ? getLastCallback : getLastCallbackForType; - var nextCb; - - while ((nextCb = getNextCallback(taskType))) { - try { - nextCb(); - } catch (e) { - log.error(e); - } - } - } - } - } - - function decTaskCount(taskType) { - taskType = taskType || DEFAULT_TASK_TYPE; - if (taskCounts[taskType]) { - taskCounts[taskType]--; - taskCounts[ALL_TASKS_TYPE]--; - } - } - - function getLastCallback() { - var cbInfo = taskCallbacks.pop(); - return cbInfo && cbInfo.cb; - } - - function getLastCallbackForType(taskType) { - for (var i = taskCallbacks.length - 1; i >= 0; --i) { - var cbInfo = taskCallbacks[i]; - if (cbInfo.type === taskType) { - taskCallbacks.splice(i, 1); - return cbInfo.cb; - } - } - } - - function incTaskCount(taskType) { - taskType = taskType || DEFAULT_TASK_TYPE; - taskCounts[taskType] = (taskCounts[taskType] || 0) + 1; - taskCounts[ALL_TASKS_TYPE] = (taskCounts[ALL_TASKS_TYPE] || 0) + 1; - } - - function notifyWhenNoPendingTasks(callback, taskType) { - taskType = taskType || ALL_TASKS_TYPE; - if (!taskCounts[taskType]) { - callback(); - } else { - taskCallbacks.push({type: taskType, cb: callback}); - } - } -} - -var $templateRequestMinErr = minErr('$templateRequest'); - -/** - * @ngdoc provider - * @name $templateRequestProvider - * @this - * - * @description - * Used to configure the options passed to the {@link $http} service when making a template request. - * - * For example, it can be used for specifying the "Accept" header that is sent to the server, when - * requesting a template. - */ -function $TemplateRequestProvider() { - - var httpOptions; - - /** - * @ngdoc method - * @name $templateRequestProvider#httpOptions - * @description - * The options to be passed to the {@link $http} service when making the request. - * You can use this to override options such as the "Accept" header for template requests. - * - * The {@link $templateRequest} will set the `cache` and the `transformResponse` properties of the - * options if not overridden here. - * - * @param {string=} value new value for the {@link $http} options. - * @returns {string|self} Returns the {@link $http} options when used as getter and self if used as setter. - */ - this.httpOptions = function(val) { - if (val) { - httpOptions = val; - return this; - } - return httpOptions; - }; - - /** - * @ngdoc service - * @name $templateRequest - * - * @description - * The `$templateRequest` service runs security checks then downloads the provided template using - * `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request - * fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the - * exception can be thwarted by setting the 2nd parameter of the function to true). Note that the - * contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted - * when `tpl` is of type string and `$templateCache` has the matching entry. - * - * If you want to pass custom options to the `$http` service, such as setting the Accept header you - * can configure this via {@link $templateRequestProvider#httpOptions}. - * - * `$templateRequest` is used internally by {@link $compile}, {@link ngRoute.$route}, and directives such - * as {@link ngInclude} to download and cache templates. - * - * 3rd party modules should use `$templateRequest` if their services or directives are loading - * templates. - * - * @param {string|TrustedResourceUrl} tpl The HTTP request template URL - * @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty - * - * @return {Promise} a promise for the HTTP response data of the given URL. - * - * @property {number} totalPendingRequests total amount of pending template requests being downloaded. - */ - this.$get = ['$exceptionHandler', '$templateCache', '$http', '$q', '$sce', - function($exceptionHandler, $templateCache, $http, $q, $sce) { - - function handleRequestFn(tpl, ignoreRequestError) { - handleRequestFn.totalPendingRequests++; - - // We consider the template cache holds only trusted templates, so - // there's no need to go through whitelisting again for keys that already - // are included in there. This also makes AngularJS accept any script - // directive, no matter its name. However, we still need to unwrap trusted - // types. - if (!isString(tpl) || isUndefined($templateCache.get(tpl))) { - tpl = $sce.getTrustedResourceUrl(tpl); - } - - var transformResponse = $http.defaults && $http.defaults.transformResponse; - - if (isArray(transformResponse)) { - transformResponse = transformResponse.filter(function(transformer) { - return transformer !== defaultHttpResponseTransform; - }); - } else if (transformResponse === defaultHttpResponseTransform) { - transformResponse = null; - } - - return $http.get(tpl, extend({ - cache: $templateCache, - transformResponse: transformResponse - }, httpOptions)) - .finally(function() { - handleRequestFn.totalPendingRequests--; - }) - .then(function(response) { - return $templateCache.put(tpl, response.data); - }, handleError); - - function handleError(resp) { - if (!ignoreRequestError) { - resp = $templateRequestMinErr('tpload', - 'Failed to load template: {0} (HTTP status: {1} {2})', - tpl, resp.status, resp.statusText); - - $exceptionHandler(resp); - } - - return $q.reject(resp); - } - } - - handleRequestFn.totalPendingRequests = 0; - - return handleRequestFn; - } - ]; -} - -/** @this */ -function $$TestabilityProvider() { - this.$get = ['$rootScope', '$browser', '$location', - function($rootScope, $browser, $location) { - - /** - * @name $testability - * - * @description - * The private $$testability service provides a collection of methods for use when debugging - * or by automated test and debugging tools. - */ - var testability = {}; - - /** - * @name $$testability#findBindings - * - * @description - * Returns an array of elements that are bound (via ng-bind or {{}}) - * to expressions matching the input. - * - * @param {Element} element The element root to search from. - * @param {string} expression The binding expression to match. - * @param {boolean} opt_exactMatch If true, only returns exact matches - * for the expression. Filters and whitespace are ignored. - */ - testability.findBindings = function(element, expression, opt_exactMatch) { - var bindings = element.getElementsByClassName('ng-binding'); - var matches = []; - forEach(bindings, function(binding) { - var dataBinding = angular.element(binding).data('$binding'); - if (dataBinding) { - forEach(dataBinding, function(bindingName) { - if (opt_exactMatch) { - var matcher = new RegExp('(^|\\s)' + escapeForRegexp(expression) + '(\\s|\\||$)'); - if (matcher.test(bindingName)) { - matches.push(binding); - } - } else { - if (bindingName.indexOf(expression) !== -1) { - matches.push(binding); - } - } - }); - } - }); - return matches; - }; - - /** - * @name $$testability#findModels - * - * @description - * Returns an array of elements that are two-way found via ng-model to - * expressions matching the input. - * - * @param {Element} element The element root to search from. - * @param {string} expression The model expression to match. - * @param {boolean} opt_exactMatch If true, only returns exact matches - * for the expression. - */ - testability.findModels = function(element, expression, opt_exactMatch) { - var prefixes = ['ng-', 'data-ng-', 'ng\\:']; - for (var p = 0; p < prefixes.length; ++p) { - var attributeEquals = opt_exactMatch ? '=' : '*='; - var selector = '[' + prefixes[p] + 'model' + attributeEquals + '"' + expression + '"]'; - var elements = element.querySelectorAll(selector); - if (elements.length) { - return elements; - } - } - }; - - /** - * @name $$testability#getLocation - * - * @description - * Shortcut for getting the location in a browser agnostic way. Returns - * the path, search, and hash. (e.g. /path?a=b#hash) - */ - testability.getLocation = function() { - return $location.url(); - }; - - /** - * @name $$testability#setLocation - * - * @description - * Shortcut for navigating to a location without doing a full page reload. - * - * @param {string} url The location url (path, search and hash, - * e.g. /path?a=b#hash) to go to. - */ - testability.setLocation = function(url) { - if (url !== $location.url()) { - $location.url(url); - $rootScope.$digest(); - } - }; - - /** - * @name $$testability#whenStable - * - * @description - * Calls the callback when all pending tasks are completed. - * - * Types of tasks waited for include: - * - Pending timeouts (via {@link $timeout}). - * - Pending HTTP requests (via {@link $http}). - * - In-progress route transitions (via {@link $route}). - * - Pending tasks scheduled via {@link $rootScope#$applyAsync}. - * - Pending tasks scheduled via {@link $rootScope#$evalAsync}. - * These include tasks scheduled via `$evalAsync()` indirectly (such as {@link $q} promises). - * - * @param {function} callback - */ - testability.whenStable = function(callback) { - $browser.notifyWhenNoOutstandingRequests(callback); - }; - - return testability; - }]; -} - -var $timeoutMinErr = minErr('$timeout'); - -/** @this */ -function $TimeoutProvider() { - this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler', - function($rootScope, $browser, $q, $$q, $exceptionHandler) { - - var deferreds = {}; - - - /** - * @ngdoc service - * @name $timeout - * - * @description - * AngularJS's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch - * block and delegates any exceptions to - * {@link ng.$exceptionHandler $exceptionHandler} service. - * - * The return value of calling `$timeout` is a promise, which will be resolved when - * the delay has passed and the timeout function, if provided, is executed. - * - * To cancel a timeout request, call `$timeout.cancel(promise)`. - * - * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to - * synchronously flush the queue of deferred functions. - * - * If you only want a promise that will be resolved after some specified delay - * then you can call `$timeout` without the `fn` function. - * - * @param {function()=} fn A function, whose execution should be delayed. - * @param {number=} [delay=0] Delay in milliseconds. - * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise - * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. - * @param {...*=} Pass additional parameters to the executed function. - * @returns {Promise} Promise that will be resolved when the timeout is reached. The promise - * will be resolved with the return value of the `fn` function. - * - */ - function timeout(fn, delay, invokeApply) { - if (!isFunction(fn)) { - invokeApply = delay; - delay = fn; - fn = noop; - } - - var args = sliceArgs(arguments, 3), - skipApply = (isDefined(invokeApply) && !invokeApply), - deferred = (skipApply ? $$q : $q).defer(), - promise = deferred.promise, - timeoutId; - - timeoutId = $browser.defer(function() { - try { - deferred.resolve(fn.apply(null, args)); - } catch (e) { - deferred.reject(e); - $exceptionHandler(e); - } finally { - delete deferreds[promise.$$timeoutId]; - } - - if (!skipApply) $rootScope.$apply(); - }, delay, '$timeout'); - - promise.$$timeoutId = timeoutId; - deferreds[timeoutId] = deferred; - - return promise; - } - - - /** - * @ngdoc method - * @name $timeout#cancel - * - * @description - * Cancels a task associated with the `promise`. As a result of this, the promise will be - * resolved with a rejection. - * - * @param {Promise=} promise Promise returned by the `$timeout` function. - * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully - * canceled. - */ - timeout.cancel = function(promise) { - if (!promise) return false; - - if (!promise.hasOwnProperty('$$timeoutId')) { - throw $timeoutMinErr('badprom', - '`$timeout.cancel()` called with a promise that was not generated by `$timeout()`.'); - } - - if (!deferreds.hasOwnProperty(promise.$$timeoutId)) return false; - - var id = promise.$$timeoutId; - var deferred = deferreds[id]; - - // Timeout cancels should not report an unhandled promise. - markQExceptionHandled(deferred.promise); - deferred.reject('canceled'); - delete deferreds[id]; - - return $browser.defer.cancel(id); - }; - - return timeout; - }]; -} - -// NOTE: The usage of window and document instead of $window and $document here is -// deliberate. This service depends on the specific behavior of anchor nodes created by the -// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and -// cause us to break tests. In addition, when the browser resolves a URL for XHR, it -// doesn't know about mocked locations and resolves URLs to the real document - which is -// exactly the behavior needed here. There is little value is mocking these out for this -// service. -var urlParsingNode = window.document.createElement('a'); -var originUrl = urlResolve(window.location.href); -var baseUrlParsingNode; - -urlParsingNode.href = 'http://[::1]'; - -// Support: IE 9-11 only, Edge 16-17 only (fixed in 18 Preview) -// IE/Edge don't wrap IPv6 addresses' hostnames in square brackets -// when parsed out of an anchor element. -var ipv6InBrackets = urlParsingNode.hostname === '[::1]'; - -/** - * - * Implementation Notes for non-IE browsers - * ---------------------------------------- - * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM, - * results both in the normalizing and parsing of the URL. Normalizing means that a relative - * URL will be resolved into an absolute URL in the context of the application document. - * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related - * properties are all populated to reflect the normalized URL. This approach has wide - * compatibility - Safari 1+, Mozilla 1+ etc. See - * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html - * - * Implementation Notes for IE - * --------------------------- - * IE <= 10 normalizes the URL when assigned to the anchor node similar to the other - * browsers. However, the parsed components will not be set if the URL assigned did not specify - * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We - * work around that by performing the parsing in a 2nd step by taking a previously normalized - * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the - * properties such as protocol, hostname, port, etc. - * - * References: - * http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement - * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html - * http://url.spec.whatwg.org/#urlutils - * https://github.com/angular/angular.js/pull/2902 - * http://james.padolsey.com/javascript/parsing-urls-with-the-dom/ - * - * @kind function - * @param {string|object} url The URL to be parsed. If `url` is not a string, it will be returned - * unchanged. - * @description Normalizes and parses a URL. - * @returns {object} Returns the normalized URL as a dictionary. - * - * | member name | Description | - * |---------------|------------------------------------------------------------------------| - * | href | A normalized version of the provided URL if it was not an absolute URL | - * | protocol | The protocol without the trailing colon | - * | host | The host and port (if the port is non-default) of the normalizedUrl | - * | search | The search params, minus the question mark | - * | hash | The hash string, minus the hash symbol | - * | hostname | The hostname | - * | port | The port, without ":" | - * | pathname | The pathname, beginning with "/" | - * - */ -function urlResolve(url) { - if (!isString(url)) return url; - - var href = url; - - // Support: IE 9-11 only - if (msie) { - // Normalize before parse. Refer Implementation Notes on why this is - // done in two steps on IE. - urlParsingNode.setAttribute('href', href); - href = urlParsingNode.href; - } - - urlParsingNode.setAttribute('href', href); - - var hostname = urlParsingNode.hostname; - - if (!ipv6InBrackets && hostname.indexOf(':') > -1) { - hostname = '[' + hostname + ']'; - } - - return { - href: urlParsingNode.href, - protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', - host: urlParsingNode.host, - search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', - hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', - hostname: hostname, - port: urlParsingNode.port, - pathname: (urlParsingNode.pathname.charAt(0) === '/') - ? urlParsingNode.pathname - : '/' + urlParsingNode.pathname - }; -} - -/** - * Parse a request URL and determine whether this is a same-origin request as the application - * document. - * - * @param {string|object} requestUrl The url of the request as a string that will be resolved - * or a parsed URL object. - * @returns {boolean} Whether the request is for the same origin as the application document. - */ -function urlIsSameOrigin(requestUrl) { - return urlsAreSameOrigin(requestUrl, originUrl); -} - -/** - * Parse a request URL and determine whether it is same-origin as the current document base URL. - * - * Note: The base URL is usually the same as the document location (`location.href`) but can - * be overriden by using the `` tag. - * - * @param {string|object} requestUrl The url of the request as a string that will be resolved - * or a parsed URL object. - * @returns {boolean} Whether the URL is same-origin as the document base URL. - */ -function urlIsSameOriginAsBaseUrl(requestUrl) { - return urlsAreSameOrigin(requestUrl, getBaseUrl()); -} - -/** - * Create a function that can check a URL's origin against a list of allowed/whitelisted origins. - * The current location's origin is implicitly trusted. - * - * @param {string[]} whitelistedOriginUrls - A list of URLs (strings), whose origins are trusted. - * - * @returns {Function} - A function that receives a URL (string or parsed URL object) and returns - * whether it is of an allowed origin. - */ -function urlIsAllowedOriginFactory(whitelistedOriginUrls) { - var parsedAllowedOriginUrls = [originUrl].concat(whitelistedOriginUrls.map(urlResolve)); - - /** - * Check whether the specified URL (string or parsed URL object) has an origin that is allowed - * based on a list of whitelisted-origin URLs. The current location's origin is implicitly - * trusted. - * - * @param {string|Object} requestUrl - The URL to be checked (provided as a string that will be - * resolved or a parsed URL object). - * - * @returns {boolean} - Whether the specified URL is of an allowed origin. - */ - return function urlIsAllowedOrigin(requestUrl) { - var parsedUrl = urlResolve(requestUrl); - return parsedAllowedOriginUrls.some(urlsAreSameOrigin.bind(null, parsedUrl)); - }; -} - -/** - * Determine if two URLs share the same origin. - * - * @param {string|Object} url1 - First URL to compare as a string or a normalized URL in the form of - * a dictionary object returned by `urlResolve()`. - * @param {string|object} url2 - Second URL to compare as a string or a normalized URL in the form - * of a dictionary object returned by `urlResolve()`. - * - * @returns {boolean} - True if both URLs have the same origin, and false otherwise. - */ -function urlsAreSameOrigin(url1, url2) { - url1 = urlResolve(url1); - url2 = urlResolve(url2); - - return (url1.protocol === url2.protocol && - url1.host === url2.host); -} - -/** - * Returns the current document base URL. - * @returns {string} - */ -function getBaseUrl() { - if (window.document.baseURI) { - return window.document.baseURI; - } - - // `document.baseURI` is available everywhere except IE - if (!baseUrlParsingNode) { - baseUrlParsingNode = window.document.createElement('a'); - baseUrlParsingNode.href = '.'; - - // Work-around for IE bug described in Implementation Notes. The fix in `urlResolve()` is not - // suitable here because we need to track changes to the base URL. - baseUrlParsingNode = baseUrlParsingNode.cloneNode(false); - } - return baseUrlParsingNode.href; -} - -/** - * @ngdoc service - * @name $window - * @this - * - * @description - * A reference to the browser's `window` object. While `window` - * is globally available in JavaScript, it causes testability problems, because - * it is a global variable. In AngularJS we always refer to it through the - * `$window` service, so it may be overridden, removed or mocked for testing. - * - * Expressions, like the one defined for the `ngClick` directive in the example - * below, are evaluated with respect to the current scope. Therefore, there is - * no risk of inadvertently coding in a dependency on a global value in such an - * expression. - * - * @example - - - -
    - - -
    -
    - - it('should display the greeting in the input box', function() { - element(by.model('greeting')).sendKeys('Hello, E2E Tests'); - // If we click the button it will block the test runner - // element(':button').click(); - }); - -
    - */ -function $WindowProvider() { - this.$get = valueFn(window); -} - -/** - * @name $$cookieReader - * @requires $document - * - * @description - * This is a private service for reading cookies used by $http and ngCookies - * - * @return {Object} a key/value map of the current cookies - */ -function $$CookieReader($document) { - var rawDocument = $document[0] || {}; - var lastCookies = {}; - var lastCookieString = ''; - - function safeGetCookie(rawDocument) { - try { - return rawDocument.cookie || ''; - } catch (e) { - return ''; - } - } - - function safeDecodeURIComponent(str) { - try { - return decodeURIComponent(str); - } catch (e) { - return str; - } - } - - return function() { - var cookieArray, cookie, i, index, name; - var currentCookieString = safeGetCookie(rawDocument); - - if (currentCookieString !== lastCookieString) { - lastCookieString = currentCookieString; - cookieArray = lastCookieString.split('; '); - lastCookies = {}; - - for (i = 0; i < cookieArray.length; i++) { - cookie = cookieArray[i]; - index = cookie.indexOf('='); - if (index > 0) { //ignore nameless cookies - name = safeDecodeURIComponent(cookie.substring(0, index)); - // the first value that is seen for a cookie is the most - // specific one. values for the same cookie name that - // follow are for less specific paths. - if (isUndefined(lastCookies[name])) { - lastCookies[name] = safeDecodeURIComponent(cookie.substring(index + 1)); - } - } - } - } - return lastCookies; - }; -} - -$$CookieReader.$inject = ['$document']; - -/** @this */ -function $$CookieReaderProvider() { - this.$get = $$CookieReader; -} - -/* global currencyFilter: true, - dateFilter: true, - filterFilter: true, - jsonFilter: true, - limitToFilter: true, - lowercaseFilter: true, - numberFilter: true, - orderByFilter: true, - uppercaseFilter: true, - */ - -/** - * @ngdoc provider - * @name $filterProvider - * @description - * - * Filters are just functions which transform input to an output. However filters need to be - * Dependency Injected. To achieve this a filter definition consists of a factory function which is - * annotated with dependencies and is responsible for creating a filter function. - * - *
    - * **Note:** Filter names must be valid AngularJS {@link expression} identifiers, such as `uppercase` or `orderBy`. - * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace - * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores - * (`myapp_subsection_filterx`). - *
    - * - * ```js - * // Filter registration - * function MyModule($provide, $filterProvider) { - * // create a service to demonstrate injection (not always needed) - * $provide.value('greet', function(name){ - * return 'Hello ' + name + '!'; - * }); - * - * // register a filter factory which uses the - * // greet service to demonstrate DI. - * $filterProvider.register('greet', function(greet){ - * // return the filter function which uses the greet service - * // to generate salutation - * return function(text) { - * // filters need to be forgiving so check input validity - * return text && greet(text) || text; - * }; - * }); - * } - * ``` - * - * The filter function is registered with the `$injector` under the filter name suffix with - * `Filter`. - * - * ```js - * it('should be the same instance', inject( - * function($filterProvider) { - * $filterProvider.register('reverse', function(){ - * return ...; - * }); - * }, - * function($filter, reverseFilter) { - * expect($filter('reverse')).toBe(reverseFilter); - * }); - * ``` - * - * - * For more information about how AngularJS filters work, and how to create your own filters, see - * {@link guide/filter Filters} in the AngularJS Developer Guide. - */ - -/** - * @ngdoc service - * @name $filter - * @kind function - * @description - * Filters are used for formatting data displayed to the user. - * - * They can be used in view templates, controllers or services. AngularJS comes - * with a collection of [built-in filters](api/ng/filter), but it is easy to - * define your own as well. - * - * The general syntax in templates is as follows: - * - * ```html - * {{ expression [| filter_name[:parameter_value] ... ] }} - * ``` - * - * @param {String} name Name of the filter function to retrieve - * @return {Function} the filter function - * @example - - -
    -

    {{ originalText }}

    -

    {{ filteredText }}

    -
    -
    - - - angular.module('filterExample', []) - .controller('MainCtrl', function($scope, $filter) { - $scope.originalText = 'hello'; - $scope.filteredText = $filter('uppercase')($scope.originalText); - }); - -
    - */ -$FilterProvider.$inject = ['$provide']; -/** @this */ -function $FilterProvider($provide) { - var suffix = 'Filter'; - - /** - * @ngdoc method - * @name $filterProvider#register - * @param {string|Object} name Name of the filter function, or an object map of filters where - * the keys are the filter names and the values are the filter factories. - * - *
    - * **Note:** Filter names must be valid AngularJS {@link expression} identifiers, such as `uppercase` or `orderBy`. - * Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace - * your filters, then you can use capitalization (`myappSubsectionFilterx`) or underscores - * (`myapp_subsection_filterx`). - *
    - * @param {Function} factory If the first argument was a string, a factory function for the filter to be registered. - * @returns {Object} Registered filter instance, or if a map of filters was provided then a map - * of the registered filter instances. - */ - function register(name, factory) { - if (isObject(name)) { - var filters = {}; - forEach(name, function(filter, key) { - filters[key] = register(key, filter); - }); - return filters; - } else { - return $provide.factory(name + suffix, factory); - } - } - this.register = register; - - this.$get = ['$injector', function($injector) { - return function(name) { - return $injector.get(name + suffix); - }; - }]; - - //////////////////////////////////////// - - /* global - currencyFilter: false, - dateFilter: false, - filterFilter: false, - jsonFilter: false, - limitToFilter: false, - lowercaseFilter: false, - numberFilter: false, - orderByFilter: false, - uppercaseFilter: false - */ - - register('currency', currencyFilter); - register('date', dateFilter); - register('filter', filterFilter); - register('json', jsonFilter); - register('limitTo', limitToFilter); - register('lowercase', lowercaseFilter); - register('number', numberFilter); - register('orderBy', orderByFilter); - register('uppercase', uppercaseFilter); -} - -/** - * @ngdoc filter - * @name filter - * @kind function - * - * @description - * Selects a subset of items from `array` and returns it as a new array. - * - * @param {Array} array The source array. - *
    - * **Note**: If the array contains objects that reference themselves, filtering is not possible. - *
    - * @param {string|Object|function()} expression The predicate to be used for selecting items from - * `array`. - * - * Can be one of: - * - * - `string`: The string is used for matching against the contents of the `array`. All strings or - * objects with string properties in `array` that match this string will be returned. This also - * applies to nested object properties. - * The predicate can be negated by prefixing the string with `!`. - * - * - `Object`: A pattern object can be used to filter specific properties on objects contained - * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items - * which have property `name` containing "M" and property `phone` containing "1". A special - * property name (`$` by default) can be used (e.g. as in `{$: "text"}`) to accept a match - * against any property of the object or its nested object properties. That's equivalent to the - * simple substring match with a `string` as described above. The special property name can be - * overwritten, using the `anyPropertyKey` parameter. - * The predicate can be negated by prefixing the string with `!`. - * For example `{name: "!M"}` predicate will return an array of items which have property `name` - * not containing "M". - * - * Note that a named property will match properties on the same level only, while the special - * `$` property will match properties on the same level or deeper. E.g. an array item like - * `{name: {first: 'John', last: 'Doe'}}` will **not** be matched by `{name: 'John'}`, but - * **will** be matched by `{$: 'John'}`. - * - * - `function(value, index, array)`: A predicate function can be used to write arbitrary filters. - * The function is called for each element of the array, with the element, its index, and - * the entire array itself as arguments. - * - * The final result is an array of those elements that the predicate returned true for. - * - * @param {function(actual, expected)|true|false} [comparator] Comparator which is used in - * determining if values retrieved using `expression` (when it is not a function) should be - * considered a match based on the expected value (from the filter expression) and actual - * value (from the object in the array). - * - * Can be one of: - * - * - `function(actual, expected)`: - * The function will be given the object value and the predicate value to compare and - * should return true if both values should be considered equal. - * - * - `true`: A shorthand for `function(actual, expected) { return angular.equals(actual, expected)}`. - * This is essentially strict comparison of expected and actual. - * - * - `false`: A short hand for a function which will look for a substring match in a case - * insensitive way. Primitive values are converted to strings. Objects are not compared against - * primitives, unless they have a custom `toString` method (e.g. `Date` objects). - * - * - * Defaults to `false`. - * - * @param {string} [anyPropertyKey] The special property name that matches against any property. - * By default `$`. - * - * @example - - -
    - - - - - - - - -
    NamePhone
    {{friend.name}}{{friend.phone}}
    -
    -
    -
    -
    -
    - - - - - - -
    NamePhone
    {{friendObj.name}}{{friendObj.phone}}
    -
    - - var expectFriendNames = function(expectedNames, key) { - element.all(by.repeater(key + ' in friends').column(key + '.name')).then(function(arr) { - arr.forEach(function(wd, i) { - expect(wd.getText()).toMatch(expectedNames[i]); - }); - }); - }; - - it('should search across all fields when filtering with a string', function() { - var searchText = element(by.model('searchText')); - searchText.clear(); - searchText.sendKeys('m'); - expectFriendNames(['Mary', 'Mike', 'Adam'], 'friend'); - - searchText.clear(); - searchText.sendKeys('76'); - expectFriendNames(['John', 'Julie'], 'friend'); - }); - - it('should search in specific fields when filtering with a predicate object', function() { - var searchAny = element(by.model('search.$')); - searchAny.clear(); - searchAny.sendKeys('i'); - expectFriendNames(['Mary', 'Mike', 'Julie', 'Juliette'], 'friendObj'); - }); - it('should use a equal comparison when comparator is true', function() { - var searchName = element(by.model('search.name')); - var strict = element(by.model('strict')); - searchName.clear(); - searchName.sendKeys('Julie'); - strict.click(); - expectFriendNames(['Julie'], 'friendObj'); - }); - -
    - */ - -function filterFilter() { - return function(array, expression, comparator, anyPropertyKey) { - if (!isArrayLike(array)) { - if (array == null) { - return array; - } else { - throw minErr('filter')('notarray', 'Expected array but received: {0}', array); - } - } - - anyPropertyKey = anyPropertyKey || '$'; - var expressionType = getTypeForFilter(expression); - var predicateFn; - var matchAgainstAnyProp; - - switch (expressionType) { - case 'function': - predicateFn = expression; - break; - case 'boolean': - case 'null': - case 'number': - case 'string': - matchAgainstAnyProp = true; - // falls through - case 'object': - predicateFn = createPredicateFn(expression, comparator, anyPropertyKey, matchAgainstAnyProp); - break; - default: - return array; - } - - return Array.prototype.filter.call(array, predicateFn); - }; -} - -// Helper functions for `filterFilter` -function createPredicateFn(expression, comparator, anyPropertyKey, matchAgainstAnyProp) { - var shouldMatchPrimitives = isObject(expression) && (anyPropertyKey in expression); - var predicateFn; - - if (comparator === true) { - comparator = equals; - } else if (!isFunction(comparator)) { - comparator = function(actual, expected) { - if (isUndefined(actual)) { - // No substring matching against `undefined` - return false; - } - if ((actual === null) || (expected === null)) { - // No substring matching against `null`; only match against `null` - return actual === expected; - } - if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) { - // Should not compare primitives against objects, unless they have custom `toString` method - return false; - } - - actual = lowercase('' + actual); - expected = lowercase('' + expected); - return actual.indexOf(expected) !== -1; - }; - } - - predicateFn = function(item) { - if (shouldMatchPrimitives && !isObject(item)) { - return deepCompare(item, expression[anyPropertyKey], comparator, anyPropertyKey, false); - } - return deepCompare(item, expression, comparator, anyPropertyKey, matchAgainstAnyProp); - }; - - return predicateFn; -} - -function deepCompare(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject) { - var actualType = getTypeForFilter(actual); - var expectedType = getTypeForFilter(expected); - - if ((expectedType === 'string') && (expected.charAt(0) === '!')) { - return !deepCompare(actual, expected.substring(1), comparator, anyPropertyKey, matchAgainstAnyProp); - } else if (isArray(actual)) { - // In case `actual` is an array, consider it a match - // if ANY of it's items matches `expected` - return actual.some(function(item) { - return deepCompare(item, expected, comparator, anyPropertyKey, matchAgainstAnyProp); - }); - } - - switch (actualType) { - case 'object': - var key; - if (matchAgainstAnyProp) { - for (key in actual) { - // Under certain, rare, circumstances, key may not be a string and `charAt` will be undefined - // See: https://github.com/angular/angular.js/issues/15644 - if (key.charAt && (key.charAt(0) !== '$') && - deepCompare(actual[key], expected, comparator, anyPropertyKey, true)) { - return true; - } - } - return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, anyPropertyKey, false); - } else if (expectedType === 'object') { - for (key in expected) { - var expectedVal = expected[key]; - if (isFunction(expectedVal) || isUndefined(expectedVal)) { - continue; - } - - var matchAnyProperty = key === anyPropertyKey; - var actualVal = matchAnyProperty ? actual : actual[key]; - if (!deepCompare(actualVal, expectedVal, comparator, anyPropertyKey, matchAnyProperty, matchAnyProperty)) { - return false; - } - } - return true; - } else { - return comparator(actual, expected); - } - case 'function': - return false; - default: - return comparator(actual, expected); - } -} - -// Used for easily differentiating between `null` and actual `object` -function getTypeForFilter(val) { - return (val === null) ? 'null' : typeof val; -} - -var MAX_DIGITS = 22; -var DECIMAL_SEP = '.'; -var ZERO_CHAR = '0'; - -/** - * @ngdoc filter - * @name currency - * @kind function - * - * @description - * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default - * symbol for current locale is used. - * - * @param {number} amount Input to filter. - * @param {string=} symbol Currency symbol or identifier to be displayed. - * @param {number=} fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale - * @returns {string} Formatted number. - * - * - * @example - - - -
    -
    - default currency symbol ($): {{amount | currency}}
    - custom currency identifier (USD$): {{amount | currency:"USD$"}}
    - no fractions (0): {{amount | currency:"USD$":0}} -
    -
    - - it('should init with 1234.56', function() { - expect(element(by.id('currency-default')).getText()).toBe('$1,234.56'); - expect(element(by.id('currency-custom')).getText()).toBe('USD$1,234.56'); - expect(element(by.id('currency-no-fractions')).getText()).toBe('USD$1,235'); - }); - it('should update', function() { - if (browser.params.browser === 'safari') { - // Safari does not understand the minus key. See - // https://github.com/angular/protractor/issues/481 - return; - } - element(by.model('amount')).clear(); - element(by.model('amount')).sendKeys('-1234'); - expect(element(by.id('currency-default')).getText()).toBe('-$1,234.00'); - expect(element(by.id('currency-custom')).getText()).toBe('-USD$1,234.00'); - expect(element(by.id('currency-no-fractions')).getText()).toBe('-USD$1,234'); - }); - -
    - */ -currencyFilter.$inject = ['$locale']; -function currencyFilter($locale) { - var formats = $locale.NUMBER_FORMATS; - return function(amount, currencySymbol, fractionSize) { - if (isUndefined(currencySymbol)) { - currencySymbol = formats.CURRENCY_SYM; - } - - if (isUndefined(fractionSize)) { - fractionSize = formats.PATTERNS[1].maxFrac; - } - - // If the currency symbol is empty, trim whitespace around the symbol - var currencySymbolRe = !currencySymbol ? /\s*\u00A4\s*/g : /\u00A4/g; - - // if null or undefined pass it through - return (amount == null) - ? amount - : formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, fractionSize). - replace(currencySymbolRe, currencySymbol); - }; -} - -/** - * @ngdoc filter - * @name number - * @kind function - * - * @description - * Formats a number as text. - * - * If the input is null or undefined, it will just be returned. - * If the input is infinite (Infinity or -Infinity), the Infinity symbol '∞' or '-∞' is returned, respectively. - * If the input is not a number an empty string is returned. - * - * - * @param {number|string} number Number to format. - * @param {(number|string)=} fractionSize Number of decimal places to round the number to. - * If this is not provided then the fraction size is computed from the current locale's number - * formatting pattern. In the case of the default locale, it will be 3. - * @returns {string} Number rounded to `fractionSize` appropriately formatted based on the current - * locale (e.g., in the en_US locale it will have "." as the decimal separator and - * include "," group separators after each third digit). - * - * @example - - - -
    -
    - Default formatting: {{val | number}}
    - No fractions: {{val | number:0}}
    - Negative number: {{-val | number:4}} -
    -
    - - it('should format numbers', function() { - expect(element(by.id('number-default')).getText()).toBe('1,234.568'); - expect(element(by.binding('val | number:0')).getText()).toBe('1,235'); - expect(element(by.binding('-val | number:4')).getText()).toBe('-1,234.5679'); - }); - - it('should update', function() { - element(by.model('val')).clear(); - element(by.model('val')).sendKeys('3374.333'); - expect(element(by.id('number-default')).getText()).toBe('3,374.333'); - expect(element(by.binding('val | number:0')).getText()).toBe('3,374'); - expect(element(by.binding('-val | number:4')).getText()).toBe('-3,374.3330'); - }); - -
    - */ -numberFilter.$inject = ['$locale']; -function numberFilter($locale) { - var formats = $locale.NUMBER_FORMATS; - return function(number, fractionSize) { - - // if null or undefined pass it through - return (number == null) - ? number - : formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, - fractionSize); - }; -} - -/** - * Parse a number (as a string) into three components that can be used - * for formatting the number. - * - * (Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/) - * - * @param {string} numStr The number to parse - * @return {object} An object describing this number, containing the following keys: - * - d : an array of digits containing leading zeros as necessary - * - i : the number of the digits in `d` that are to the left of the decimal point - * - e : the exponent for numbers that would need more than `MAX_DIGITS` digits in `d` - * - */ -function parse(numStr) { - var exponent = 0, digits, numberOfIntegerDigits; - var i, j, zeros; - - // Decimal point? - if ((numberOfIntegerDigits = numStr.indexOf(DECIMAL_SEP)) > -1) { - numStr = numStr.replace(DECIMAL_SEP, ''); - } - - // Exponential form? - if ((i = numStr.search(/e/i)) > 0) { - // Work out the exponent. - if (numberOfIntegerDigits < 0) numberOfIntegerDigits = i; - numberOfIntegerDigits += +numStr.slice(i + 1); - numStr = numStr.substring(0, i); - } else if (numberOfIntegerDigits < 0) { - // There was no decimal point or exponent so it is an integer. - numberOfIntegerDigits = numStr.length; - } - - // Count the number of leading zeros. - for (i = 0; numStr.charAt(i) === ZERO_CHAR; i++) { /* empty */ } - - if (i === (zeros = numStr.length)) { - // The digits are all zero. - digits = [0]; - numberOfIntegerDigits = 1; - } else { - // Count the number of trailing zeros - zeros--; - while (numStr.charAt(zeros) === ZERO_CHAR) zeros--; - - // Trailing zeros are insignificant so ignore them - numberOfIntegerDigits -= i; - digits = []; - // Convert string to array of digits without leading/trailing zeros. - for (j = 0; i <= zeros; i++, j++) { - digits[j] = +numStr.charAt(i); - } - } - - // If the number overflows the maximum allowed digits then use an exponent. - if (numberOfIntegerDigits > MAX_DIGITS) { - digits = digits.splice(0, MAX_DIGITS - 1); - exponent = numberOfIntegerDigits - 1; - numberOfIntegerDigits = 1; - } - - return { d: digits, e: exponent, i: numberOfIntegerDigits }; -} - -/** - * Round the parsed number to the specified number of decimal places - * This function changed the parsedNumber in-place - */ -function roundNumber(parsedNumber, fractionSize, minFrac, maxFrac) { - var digits = parsedNumber.d; - var fractionLen = digits.length - parsedNumber.i; - - // determine fractionSize if it is not specified; `+fractionSize` converts it to a number - fractionSize = (isUndefined(fractionSize)) ? Math.min(Math.max(minFrac, fractionLen), maxFrac) : +fractionSize; - - // The index of the digit to where rounding is to occur - var roundAt = fractionSize + parsedNumber.i; - var digit = digits[roundAt]; - - if (roundAt > 0) { - // Drop fractional digits beyond `roundAt` - digits.splice(Math.max(parsedNumber.i, roundAt)); - - // Set non-fractional digits beyond `roundAt` to 0 - for (var j = roundAt; j < digits.length; j++) { - digits[j] = 0; - } - } else { - // We rounded to zero so reset the parsedNumber - fractionLen = Math.max(0, fractionLen); - parsedNumber.i = 1; - digits.length = Math.max(1, roundAt = fractionSize + 1); - digits[0] = 0; - for (var i = 1; i < roundAt; i++) digits[i] = 0; - } - - if (digit >= 5) { - if (roundAt - 1 < 0) { - for (var k = 0; k > roundAt; k--) { - digits.unshift(0); - parsedNumber.i++; - } - digits.unshift(1); - parsedNumber.i++; - } else { - digits[roundAt - 1]++; - } - } - - // Pad out with zeros to get the required fraction length - for (; fractionLen < Math.max(0, fractionSize); fractionLen++) digits.push(0); - - - // Do any carrying, e.g. a digit was rounded up to 10 - var carry = digits.reduceRight(function(carry, d, i, digits) { - d = d + carry; - digits[i] = d % 10; - return Math.floor(d / 10); - }, 0); - if (carry) { - digits.unshift(carry); - parsedNumber.i++; - } -} - -/** - * Format a number into a string - * @param {number} number The number to format - * @param {{ - * minFrac, // the minimum number of digits required in the fraction part of the number - * maxFrac, // the maximum number of digits required in the fraction part of the number - * gSize, // number of digits in each group of separated digits - * lgSize, // number of digits in the last group of digits before the decimal separator - * negPre, // the string to go in front of a negative number (e.g. `-` or `(`)) - * posPre, // the string to go in front of a positive number - * negSuf, // the string to go after a negative number (e.g. `)`) - * posSuf // the string to go after a positive number - * }} pattern - * @param {string} groupSep The string to separate groups of number (e.g. `,`) - * @param {string} decimalSep The string to act as the decimal separator (e.g. `.`) - * @param {[type]} fractionSize The size of the fractional part of the number - * @return {string} The number formatted as a string - */ -function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { - - if (!(isString(number) || isNumber(number)) || isNaN(number)) return ''; - - var isInfinity = !isFinite(number); - var isZero = false; - var numStr = Math.abs(number) + '', - formattedText = '', - parsedNumber; - - if (isInfinity) { - formattedText = '\u221e'; - } else { - parsedNumber = parse(numStr); - - roundNumber(parsedNumber, fractionSize, pattern.minFrac, pattern.maxFrac); - - var digits = parsedNumber.d; - var integerLen = parsedNumber.i; - var exponent = parsedNumber.e; - var decimals = []; - isZero = digits.reduce(function(isZero, d) { return isZero && !d; }, true); - - // pad zeros for small numbers - while (integerLen < 0) { - digits.unshift(0); - integerLen++; - } - - // extract decimals digits - if (integerLen > 0) { - decimals = digits.splice(integerLen, digits.length); - } else { - decimals = digits; - digits = [0]; - } - - // format the integer digits with grouping separators - var groups = []; - if (digits.length >= pattern.lgSize) { - groups.unshift(digits.splice(-pattern.lgSize, digits.length).join('')); - } - while (digits.length > pattern.gSize) { - groups.unshift(digits.splice(-pattern.gSize, digits.length).join('')); - } - if (digits.length) { - groups.unshift(digits.join('')); - } - formattedText = groups.join(groupSep); - - // append the decimal digits - if (decimals.length) { - formattedText += decimalSep + decimals.join(''); - } - - if (exponent) { - formattedText += 'e+' + exponent; - } - } - if (number < 0 && !isZero) { - return pattern.negPre + formattedText + pattern.negSuf; - } else { - return pattern.posPre + formattedText + pattern.posSuf; - } -} - -function padNumber(num, digits, trim, negWrap) { - var neg = ''; - if (num < 0 || (negWrap && num <= 0)) { - if (negWrap) { - num = -num + 1; - } else { - num = -num; - neg = '-'; - } - } - num = '' + num; - while (num.length < digits) num = ZERO_CHAR + num; - if (trim) { - num = num.substr(num.length - digits); - } - return neg + num; -} - - -function dateGetter(name, size, offset, trim, negWrap) { - offset = offset || 0; - return function(date) { - var value = date['get' + name](); - if (offset > 0 || value > -offset) { - value += offset; - } - if (value === 0 && offset === -12) value = 12; - return padNumber(value, size, trim, negWrap); - }; -} - -function dateStrGetter(name, shortForm, standAlone) { - return function(date, formats) { - var value = date['get' + name](); - var propPrefix = (standAlone ? 'STANDALONE' : '') + (shortForm ? 'SHORT' : ''); - var get = uppercase(propPrefix + name); - - return formats[get][value]; - }; -} - -function timeZoneGetter(date, formats, offset) { - var zone = -1 * offset; - var paddedZone = (zone >= 0) ? '+' : ''; - - paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) + - padNumber(Math.abs(zone % 60), 2); - - return paddedZone; -} - -function getFirstThursdayOfYear(year) { - // 0 = index of January - var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay(); - // 4 = index of Thursday (+1 to account for 1st = 5) - // 11 = index of *next* Thursday (+1 account for 1st = 12) - return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst); -} - -function getThursdayThisWeek(datetime) { - return new Date(datetime.getFullYear(), datetime.getMonth(), - // 4 = index of Thursday - datetime.getDate() + (4 - datetime.getDay())); -} - -function weekGetter(size) { - return function(date) { - var firstThurs = getFirstThursdayOfYear(date.getFullYear()), - thisThurs = getThursdayThisWeek(date); - - var diff = +thisThurs - +firstThurs, - result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week - - return padNumber(result, size); - }; -} - -function ampmGetter(date, formats) { - return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; -} - -function eraGetter(date, formats) { - return date.getFullYear() <= 0 ? formats.ERAS[0] : formats.ERAS[1]; -} - -function longEraGetter(date, formats) { - return date.getFullYear() <= 0 ? formats.ERANAMES[0] : formats.ERANAMES[1]; -} - -var DATE_FORMATS = { - yyyy: dateGetter('FullYear', 4, 0, false, true), - yy: dateGetter('FullYear', 2, 0, true, true), - y: dateGetter('FullYear', 1, 0, false, true), - MMMM: dateStrGetter('Month'), - MMM: dateStrGetter('Month', true), - MM: dateGetter('Month', 2, 1), - M: dateGetter('Month', 1, 1), - LLLL: dateStrGetter('Month', false, true), - dd: dateGetter('Date', 2), - d: dateGetter('Date', 1), - HH: dateGetter('Hours', 2), - H: dateGetter('Hours', 1), - hh: dateGetter('Hours', 2, -12), - h: dateGetter('Hours', 1, -12), - mm: dateGetter('Minutes', 2), - m: dateGetter('Minutes', 1), - ss: dateGetter('Seconds', 2), - s: dateGetter('Seconds', 1), - // while ISO 8601 requires fractions to be prefixed with `.` or `,` - // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions - sss: dateGetter('Milliseconds', 3), - EEEE: dateStrGetter('Day'), - EEE: dateStrGetter('Day', true), - a: ampmGetter, - Z: timeZoneGetter, - ww: weekGetter(2), - w: weekGetter(1), - G: eraGetter, - GG: eraGetter, - GGG: eraGetter, - GGGG: longEraGetter -}; - -var DATE_FORMATS_SPLIT = /((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))([\s\S]*)/, - NUMBER_STRING = /^-?\d+$/; - -/** - * @ngdoc filter - * @name date - * @kind function - * - * @description - * Formats `date` to a string based on the requested `format`. - * - * `format` string can be composed of the following elements: - * - * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010) - * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) - * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199) - * * `'MMMM'`: Month in year (January-December) - * * `'MMM'`: Month in year (Jan-Dec) - * * `'MM'`: Month in year, padded (01-12) - * * `'M'`: Month in year (1-12) - * * `'LLLL'`: Stand-alone month in year (January-December) - * * `'dd'`: Day in month, padded (01-31) - * * `'d'`: Day in month (1-31) - * * `'EEEE'`: Day in Week,(Sunday-Saturday) - * * `'EEE'`: Day in Week, (Sun-Sat) - * * `'HH'`: Hour in day, padded (00-23) - * * `'H'`: Hour in day (0-23) - * * `'hh'`: Hour in AM/PM, padded (01-12) - * * `'h'`: Hour in AM/PM, (1-12) - * * `'mm'`: Minute in hour, padded (00-59) - * * `'m'`: Minute in hour (0-59) - * * `'ss'`: Second in minute, padded (00-59) - * * `'s'`: Second in minute (0-59) - * * `'sss'`: Millisecond in second, padded (000-999) - * * `'a'`: AM/PM marker - * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200) - * * `'ww'`: Week of year, padded (00-53). Week 01 is the week with the first Thursday of the year - * * `'w'`: Week of year (0-53). Week 1 is the week with the first Thursday of the year - * * `'G'`, `'GG'`, `'GGG'`: The abbreviated form of the era string (e.g. 'AD') - * * `'GGGG'`: The long form of the era string (e.g. 'Anno Domini') - * - * `format` string can also be one of the following predefined - * {@link guide/i18n localizable formats}: - * - * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale - * (e.g. Sep 3, 2010 12:05:08 PM) - * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 PM) - * * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale - * (e.g. Friday, September 3, 2010) - * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010) - * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010) - * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10) - * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 PM) - * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 PM) - * - * `format` string can contain literal values. These need to be escaped by surrounding with single quotes (e.g. - * `"h 'in the morning'"`). In order to output a single quote, escape it - i.e., two single quotes in a sequence - * (e.g. `"h 'o''clock'"`). - * - * Any other characters in the `format` string will be output as-is. - * - * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or - * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its - * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is - * specified in the string input, the time is considered to be in the local timezone. - * @param {string=} format Formatting rules (see Description). If not specified, - * `mediumDate` is used. - * @param {string=} timezone Timezone to be used for formatting. It understands UTC/GMT and the - * continental US time zone abbreviations, but for general use, use a time zone offset, for - * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian) - * If not specified, the timezone of the browser will be used. - * @returns {string} Formatted string or the input if input is not recognized as date/millis. - * - * @example - - - {{1288323623006 | date:'medium'}}: - {{1288323623006 | date:'medium'}}
    - {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: - {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
    - {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: - {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
    - {{1288323623006 | date:"MM/dd/yyyy 'at' h:mma"}}: - {{'1288323623006' | date:"MM/dd/yyyy 'at' h:mma"}}
    -
    - - it('should format date', function() { - expect(element(by.binding("1288323623006 | date:'medium'")).getText()). - toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/); - expect(element(by.binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).getText()). - toMatch(/2010-10-2\d \d{2}:\d{2}:\d{2} (-|\+)?\d{4}/); - expect(element(by.binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).getText()). - toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/); - expect(element(by.binding("'1288323623006' | date:\"MM/dd/yyyy 'at' h:mma\"")).getText()). - toMatch(/10\/2\d\/2010 at \d{1,2}:\d{2}(AM|PM)/); - }); - -
    - */ -dateFilter.$inject = ['$locale']; -function dateFilter($locale) { - - - var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; - // 1 2 3 4 5 6 7 8 9 10 11 - function jsonStringToDate(string) { - var match; - if ((match = string.match(R_ISO8601_STR))) { - var date = new Date(0), - tzHour = 0, - tzMin = 0, - dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear, - timeSetter = match[8] ? date.setUTCHours : date.setHours; - - if (match[9]) { - tzHour = toInt(match[9] + match[10]); - tzMin = toInt(match[9] + match[11]); - } - dateSetter.call(date, toInt(match[1]), toInt(match[2]) - 1, toInt(match[3])); - var h = toInt(match[4] || 0) - tzHour; - var m = toInt(match[5] || 0) - tzMin; - var s = toInt(match[6] || 0); - var ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000); - timeSetter.call(date, h, m, s, ms); - return date; - } - return string; - } - - - return function(date, format, timezone) { - var text = '', - parts = [], - fn, match; - - format = format || 'mediumDate'; - format = $locale.DATETIME_FORMATS[format] || format; - if (isString(date)) { - date = NUMBER_STRING.test(date) ? toInt(date) : jsonStringToDate(date); - } - - if (isNumber(date)) { - date = new Date(date); - } - - if (!isDate(date) || !isFinite(date.getTime())) { - return date; - } - - while (format) { - match = DATE_FORMATS_SPLIT.exec(format); - if (match) { - parts = concat(parts, match, 1); - format = parts.pop(); - } else { - parts.push(format); - format = null; - } - } - - var dateTimezoneOffset = date.getTimezoneOffset(); - if (timezone) { - dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset); - date = convertTimezoneToLocal(date, timezone, true); - } - forEach(parts, function(value) { - fn = DATE_FORMATS[value]; - text += fn ? fn(date, $locale.DATETIME_FORMATS, dateTimezoneOffset) - : value === '\'\'' ? '\'' : value.replace(/(^'|'$)/g, '').replace(/''/g, '\''); - }); - - return text; - }; -} - - -/** - * @ngdoc filter - * @name json - * @kind function - * - * @description - * Allows you to convert a JavaScript object into JSON string. - * - * This filter is mostly useful for debugging. When using the double curly {{value}} notation - * the binding is automatically converted to JSON. - * - * @param {*} object Any JavaScript object (including arrays and primitive types) to filter. - * @param {number=} spacing The number of spaces to use per indentation, defaults to 2. - * @returns {string} JSON string. - * - * - * @example - - -
    {{ {'name':'value'} | json }}
    -
    {{ {'name':'value'} | json:4 }}
    -
    - - it('should jsonify filtered objects', function() { - expect(element(by.id('default-spacing')).getText()).toMatch(/\{\n {2}"name": ?"value"\n}/); - expect(element(by.id('custom-spacing')).getText()).toMatch(/\{\n {4}"name": ?"value"\n}/); - }); - -
    - * - */ -function jsonFilter() { - return function(object, spacing) { - if (isUndefined(spacing)) { - spacing = 2; - } - return toJson(object, spacing); - }; -} - - -/** - * @ngdoc filter - * @name lowercase - * @kind function - * @description - * Converts string to lowercase. - * - * See the {@link ng.uppercase uppercase filter documentation} for a functionally identical example. - * - * @see angular.lowercase - */ -var lowercaseFilter = valueFn(lowercase); - - -/** - * @ngdoc filter - * @name uppercase - * @kind function - * @description - * Converts string to uppercase. - * @example - - - -
    - -

    {{title}}

    - -

    {{title | uppercase}}

    -
    -
    -
    - */ -var uppercaseFilter = valueFn(uppercase); - -/** - * @ngdoc filter - * @name limitTo - * @kind function - * - * @description - * Creates a new array or string containing only a specified number of elements. The elements are - * taken from either the beginning or the end of the source array, string or number, as specified by - * the value and sign (positive or negative) of `limit`. Other array-like objects are also supported - * (e.g. array subclasses, NodeLists, jqLite/jQuery collections etc). If a number is used as input, - * it is converted to a string. - * - * @param {Array|ArrayLike|string|number} input - Array/array-like, string or number to be limited. - * @param {string|number} limit - The length of the returned array or string. If the `limit` number - * is positive, `limit` number of items from the beginning of the source array/string are copied. - * If the number is negative, `limit` number of items from the end of the source array/string - * are copied. The `limit` will be trimmed if it exceeds `array.length`. If `limit` is undefined, - * the input will be returned unchanged. - * @param {(string|number)=} begin - Index at which to begin limitation. As a negative index, - * `begin` indicates an offset from the end of `input`. Defaults to `0`. - * @returns {Array|string} A new sub-array or substring of length `limit` or less if the input had - * less than `limit` elements. - * - * @example - - - -
    - -

    Output numbers: {{ numbers | limitTo:numLimit }}

    - -

    Output letters: {{ letters | limitTo:letterLimit }}

    - -

    Output long number: {{ longNumber | limitTo:longNumberLimit }}

    -
    -
    - - var numLimitInput = element(by.model('numLimit')); - var letterLimitInput = element(by.model('letterLimit')); - var longNumberLimitInput = element(by.model('longNumberLimit')); - var limitedNumbers = element(by.binding('numbers | limitTo:numLimit')); - var limitedLetters = element(by.binding('letters | limitTo:letterLimit')); - var limitedLongNumber = element(by.binding('longNumber | limitTo:longNumberLimit')); - - it('should limit the number array to first three items', function() { - expect(numLimitInput.getAttribute('value')).toBe('3'); - expect(letterLimitInput.getAttribute('value')).toBe('3'); - expect(longNumberLimitInput.getAttribute('value')).toBe('3'); - expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3]'); - expect(limitedLetters.getText()).toEqual('Output letters: abc'); - expect(limitedLongNumber.getText()).toEqual('Output long number: 234'); - }); - - // There is a bug in safari and protractor that doesn't like the minus key - // it('should update the output when -3 is entered', function() { - // numLimitInput.clear(); - // numLimitInput.sendKeys('-3'); - // letterLimitInput.clear(); - // letterLimitInput.sendKeys('-3'); - // longNumberLimitInput.clear(); - // longNumberLimitInput.sendKeys('-3'); - // expect(limitedNumbers.getText()).toEqual('Output numbers: [7,8,9]'); - // expect(limitedLetters.getText()).toEqual('Output letters: ghi'); - // expect(limitedLongNumber.getText()).toEqual('Output long number: 342'); - // }); - - it('should not exceed the maximum size of input array', function() { - numLimitInput.clear(); - numLimitInput.sendKeys('100'); - letterLimitInput.clear(); - letterLimitInput.sendKeys('100'); - longNumberLimitInput.clear(); - longNumberLimitInput.sendKeys('100'); - expect(limitedNumbers.getText()).toEqual('Output numbers: [1,2,3,4,5,6,7,8,9]'); - expect(limitedLetters.getText()).toEqual('Output letters: abcdefghi'); - expect(limitedLongNumber.getText()).toEqual('Output long number: 2345432342'); - }); - -
    -*/ -function limitToFilter() { - return function(input, limit, begin) { - if (Math.abs(Number(limit)) === Infinity) { - limit = Number(limit); - } else { - limit = toInt(limit); - } - if (isNumberNaN(limit)) return input; - - if (isNumber(input)) input = input.toString(); - if (!isArrayLike(input)) return input; - - begin = (!begin || isNaN(begin)) ? 0 : toInt(begin); - begin = (begin < 0) ? Math.max(0, input.length + begin) : begin; - - if (limit >= 0) { - return sliceFn(input, begin, begin + limit); - } else { - if (begin === 0) { - return sliceFn(input, limit, input.length); - } else { - return sliceFn(input, Math.max(0, begin + limit), begin); - } - } - }; -} - -function sliceFn(input, begin, end) { - if (isString(input)) return input.slice(begin, end); - - return slice.call(input, begin, end); -} - -/** - * @ngdoc filter - * @name orderBy - * @kind function - * - * @description - * Returns an array containing the items from the specified `collection`, ordered by a `comparator` - * function based on the values computed using the `expression` predicate. - * - * For example, `[{id: 'foo'}, {id: 'bar'}] | orderBy:'id'` would result in - * `[{id: 'bar'}, {id: 'foo'}]`. - * - * The `collection` can be an Array or array-like object (e.g. NodeList, jQuery object, TypedArray, - * String, etc). - * - * The `expression` can be a single predicate, or a list of predicates each serving as a tie-breaker - * for the preceding one. The `expression` is evaluated against each item and the output is used - * for comparing with other items. - * - * You can change the sorting order by setting `reverse` to `true`. By default, items are sorted in - * ascending order. - * - * The comparison is done using the `comparator` function. If none is specified, a default, built-in - * comparator is used (see below for details - in a nutshell, it compares numbers numerically and - * strings alphabetically). - * - * ### Under the hood - * - * Ordering the specified `collection` happens in two phases: - * - * 1. All items are passed through the predicate (or predicates), and the returned values are saved - * along with their type (`string`, `number` etc). For example, an item `{label: 'foo'}`, passed - * through a predicate that extracts the value of the `label` property, would be transformed to: - * ``` - * { - * value: 'foo', - * type: 'string', - * index: ... - * } - * ``` - * **Note:** `null` values use `'null'` as their type. - * 2. The comparator function is used to sort the items, based on the derived values, types and - * indices. - * - * If you use a custom comparator, it will be called with pairs of objects of the form - * `{value: ..., type: '...', index: ...}` and is expected to return `0` if the objects are equal - * (as far as the comparator is concerned), `-1` if the 1st one should be ranked higher than the - * second, or `1` otherwise. - * - * In order to ensure that the sorting will be deterministic across platforms, if none of the - * specified predicates can distinguish between two items, `orderBy` will automatically introduce a - * dummy predicate that returns the item's index as `value`. - * (If you are using a custom comparator, make sure it can handle this predicate as well.) - * - * If a custom comparator still can't distinguish between two items, then they will be sorted based - * on their index using the built-in comparator. - * - * Finally, in an attempt to simplify things, if a predicate returns an object as the extracted - * value for an item, `orderBy` will try to convert that object to a primitive value, before passing - * it to the comparator. The following rules govern the conversion: - * - * 1. If the object has a `valueOf()` method that returns a primitive, its return value will be - * used instead.
    - * (If the object has a `valueOf()` method that returns another object, then the returned object - * will be used in subsequent steps.) - * 2. If the object has a custom `toString()` method (i.e. not the one inherited from `Object`) that - * returns a primitive, its return value will be used instead.
    - * (If the object has a `toString()` method that returns another object, then the returned object - * will be used in subsequent steps.) - * 3. No conversion; the object itself is used. - * - * ### The default comparator - * - * The default, built-in comparator should be sufficient for most usecases. In short, it compares - * numbers numerically, strings alphabetically (and case-insensitively), for objects falls back to - * using their index in the original collection, sorts values of different types by type and puts - * `undefined` and `null` values at the end of the sorted list. - * - * More specifically, it follows these steps to determine the relative order of items: - * - * 1. If the compared values are of different types: - * - If one of the values is undefined, consider it "greater than" the other. - * - Else if one of the values is null, consider it "greater than" the other. - * - Else compare the types themselves alphabetically. - * 2. If both values are of type `string`, compare them alphabetically in a case- and - * locale-insensitive way. - * 3. If both values are objects, compare their indices instead. - * 4. Otherwise, return: - * - `0`, if the values are equal (by strict equality comparison, i.e. using `===`). - * - `-1`, if the 1st value is "less than" the 2nd value (compared using the `<` operator). - * - `1`, otherwise. - * - * **Note:** If you notice numbers not being sorted as expected, make sure they are actually being - * saved as numbers and not strings. - * **Note:** For the purpose of sorting, `null` and `undefined` are considered "greater than" - * any other value (with undefined "greater than" null). This effectively means that `null` - * and `undefined` values end up at the end of a list sorted in ascending order. - * **Note:** `null` values use `'null'` as their type to be able to distinguish them from objects. - * - * @param {Array|ArrayLike} collection - The collection (array or array-like object) to sort. - * @param {(Function|string|Array.)=} expression - A predicate (or list of - * predicates) to be used by the comparator to determine the order of elements. - * - * Can be one of: - * - * - `Function`: A getter function. This function will be called with each item as argument and - * the return value will be used for sorting. - * - `string`: An AngularJS expression. This expression will be evaluated against each item and the - * result will be used for sorting. For example, use `'label'` to sort by a property called - * `label` or `'label.substring(0, 3)'` to sort by the first 3 characters of the `label` - * property.
    - * (The result of a constant expression is interpreted as a property name to be used for - * comparison. For example, use `'"special name"'` (note the extra pair of quotes) to sort by a - * property called `special name`.)
    - * An expression can be optionally prefixed with `+` or `-` to control the sorting direction, - * ascending or descending. For example, `'+label'` or `'-label'`. If no property is provided, - * (e.g. `'+'` or `'-'`), the collection element itself is used in comparisons. - * - `Array`: An array of function and/or string predicates. If a predicate cannot determine the - * relative order of two items, the next predicate is used as a tie-breaker. - * - * **Note:** If the predicate is missing or empty then it defaults to `'+'`. - * - * @param {boolean=} reverse - If `true`, reverse the sorting order. - * @param {(Function)=} comparator - The comparator function used to determine the relative order of - * value pairs. If omitted, the built-in comparator will be used. - * - * @returns {Array} - The sorted array. - * - * - * @example - * ### Ordering a table with `ngRepeat` - * - * The example below demonstrates a simple {@link ngRepeat ngRepeat}, where the data is sorted by - * age in descending order (expression is set to `'-age'`). The `comparator` is not set, which means - * it defaults to the built-in comparator. - * - - -
    - - - - - - - - - - - -
    NamePhone NumberAge
    {{friend.name}}{{friend.phone}}{{friend.age}}
    -
    -
    - - angular.module('orderByExample1', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.friends = [ - {name: 'John', phone: '555-1212', age: 10}, - {name: 'Mary', phone: '555-9876', age: 19}, - {name: 'Mike', phone: '555-4321', age: 21}, - {name: 'Adam', phone: '555-5678', age: 35}, - {name: 'Julie', phone: '555-8765', age: 29} - ]; - }]); - - - .friends { - border-collapse: collapse; - } - - .friends th { - border-bottom: 1px solid; - } - .friends td, .friends th { - border-left: 1px solid; - padding: 5px 10px; - } - .friends td:first-child, .friends th:first-child { - border-left: none; - } - - - // Element locators - var names = element.all(by.repeater('friends').column('friend.name')); - - it('should sort friends by age in reverse order', function() { - expect(names.get(0).getText()).toBe('Adam'); - expect(names.get(1).getText()).toBe('Julie'); - expect(names.get(2).getText()).toBe('Mike'); - expect(names.get(3).getText()).toBe('Mary'); - expect(names.get(4).getText()).toBe('John'); - }); - -
    - *
    - * - * @example - * ### Changing parameters dynamically - * - * All parameters can be changed dynamically. The next example shows how you can make the columns of - * a table sortable, by binding the `expression` and `reverse` parameters to scope properties. - * - - -
    -
    Sort by = {{propertyName}}; reverse = {{reverse}}
    -
    - -
    - - - - - - - - - - - -
    - - - - - - - - -
    {{friend.name}}{{friend.phone}}{{friend.age}}
    -
    -
    - - angular.module('orderByExample2', []) - .controller('ExampleController', ['$scope', function($scope) { - var friends = [ - {name: 'John', phone: '555-1212', age: 10}, - {name: 'Mary', phone: '555-9876', age: 19}, - {name: 'Mike', phone: '555-4321', age: 21}, - {name: 'Adam', phone: '555-5678', age: 35}, - {name: 'Julie', phone: '555-8765', age: 29} - ]; - - $scope.propertyName = 'age'; - $scope.reverse = true; - $scope.friends = friends; - - $scope.sortBy = function(propertyName) { - $scope.reverse = ($scope.propertyName === propertyName) ? !$scope.reverse : false; - $scope.propertyName = propertyName; - }; - }]); - - - .friends { - border-collapse: collapse; - } - - .friends th { - border-bottom: 1px solid; - } - .friends td, .friends th { - border-left: 1px solid; - padding: 5px 10px; - } - .friends td:first-child, .friends th:first-child { - border-left: none; - } - - .sortorder:after { - content: '\25b2'; // BLACK UP-POINTING TRIANGLE - } - .sortorder.reverse:after { - content: '\25bc'; // BLACK DOWN-POINTING TRIANGLE - } - - - // Element locators - var unsortButton = element(by.partialButtonText('unsorted')); - var nameHeader = element(by.partialButtonText('Name')); - var phoneHeader = element(by.partialButtonText('Phone')); - var ageHeader = element(by.partialButtonText('Age')); - var firstName = element(by.repeater('friends').column('friend.name').row(0)); - var lastName = element(by.repeater('friends').column('friend.name').row(4)); - - it('should sort friends by some property, when clicking on the column header', function() { - expect(firstName.getText()).toBe('Adam'); - expect(lastName.getText()).toBe('John'); - - phoneHeader.click(); - expect(firstName.getText()).toBe('John'); - expect(lastName.getText()).toBe('Mary'); - - nameHeader.click(); - expect(firstName.getText()).toBe('Adam'); - expect(lastName.getText()).toBe('Mike'); - - ageHeader.click(); - expect(firstName.getText()).toBe('John'); - expect(lastName.getText()).toBe('Adam'); - }); - - it('should sort friends in reverse order, when clicking on the same column', function() { - expect(firstName.getText()).toBe('Adam'); - expect(lastName.getText()).toBe('John'); - - ageHeader.click(); - expect(firstName.getText()).toBe('John'); - expect(lastName.getText()).toBe('Adam'); - - ageHeader.click(); - expect(firstName.getText()).toBe('Adam'); - expect(lastName.getText()).toBe('John'); - }); - - it('should restore the original order, when clicking "Set to unsorted"', function() { - expect(firstName.getText()).toBe('Adam'); - expect(lastName.getText()).toBe('John'); - - unsortButton.click(); - expect(firstName.getText()).toBe('John'); - expect(lastName.getText()).toBe('Julie'); - }); - -
    - *
    - * - * @example - * ### Using `orderBy` inside a controller - * - * It is also possible to call the `orderBy` filter manually, by injecting `orderByFilter`, and - * calling it with the desired parameters. (Alternatively, you could inject the `$filter` factory - * and retrieve the `orderBy` filter with `$filter('orderBy')`.) - * - - -
    -
    Sort by = {{propertyName}}; reverse = {{reverse}}
    -
    - -
    - - - - - - - - - - - -
    - - - - - - - - -
    {{friend.name}}{{friend.phone}}{{friend.age}}
    -
    -
    - - angular.module('orderByExample3', []) - .controller('ExampleController', ['$scope', 'orderByFilter', function($scope, orderBy) { - var friends = [ - {name: 'John', phone: '555-1212', age: 10}, - {name: 'Mary', phone: '555-9876', age: 19}, - {name: 'Mike', phone: '555-4321', age: 21}, - {name: 'Adam', phone: '555-5678', age: 35}, - {name: 'Julie', phone: '555-8765', age: 29} - ]; - - $scope.propertyName = 'age'; - $scope.reverse = true; - $scope.friends = orderBy(friends, $scope.propertyName, $scope.reverse); - - $scope.sortBy = function(propertyName) { - $scope.reverse = (propertyName !== null && $scope.propertyName === propertyName) - ? !$scope.reverse : false; - $scope.propertyName = propertyName; - $scope.friends = orderBy(friends, $scope.propertyName, $scope.reverse); - }; - }]); - - - .friends { - border-collapse: collapse; - } - - .friends th { - border-bottom: 1px solid; - } - .friends td, .friends th { - border-left: 1px solid; - padding: 5px 10px; - } - .friends td:first-child, .friends th:first-child { - border-left: none; - } - - .sortorder:after { - content: '\25b2'; // BLACK UP-POINTING TRIANGLE - } - .sortorder.reverse:after { - content: '\25bc'; // BLACK DOWN-POINTING TRIANGLE - } - - - // Element locators - var unsortButton = element(by.partialButtonText('unsorted')); - var nameHeader = element(by.partialButtonText('Name')); - var phoneHeader = element(by.partialButtonText('Phone')); - var ageHeader = element(by.partialButtonText('Age')); - var firstName = element(by.repeater('friends').column('friend.name').row(0)); - var lastName = element(by.repeater('friends').column('friend.name').row(4)); - - it('should sort friends by some property, when clicking on the column header', function() { - expect(firstName.getText()).toBe('Adam'); - expect(lastName.getText()).toBe('John'); - - phoneHeader.click(); - expect(firstName.getText()).toBe('John'); - expect(lastName.getText()).toBe('Mary'); - - nameHeader.click(); - expect(firstName.getText()).toBe('Adam'); - expect(lastName.getText()).toBe('Mike'); - - ageHeader.click(); - expect(firstName.getText()).toBe('John'); - expect(lastName.getText()).toBe('Adam'); - }); - - it('should sort friends in reverse order, when clicking on the same column', function() { - expect(firstName.getText()).toBe('Adam'); - expect(lastName.getText()).toBe('John'); - - ageHeader.click(); - expect(firstName.getText()).toBe('John'); - expect(lastName.getText()).toBe('Adam'); - - ageHeader.click(); - expect(firstName.getText()).toBe('Adam'); - expect(lastName.getText()).toBe('John'); - }); - - it('should restore the original order, when clicking "Set to unsorted"', function() { - expect(firstName.getText()).toBe('Adam'); - expect(lastName.getText()).toBe('John'); - - unsortButton.click(); - expect(firstName.getText()).toBe('John'); - expect(lastName.getText()).toBe('Julie'); - }); - -
    - *
    - * - * @example - * ### Using a custom comparator - * - * If you have very specific requirements about the way items are sorted, you can pass your own - * comparator function. For example, you might need to compare some strings in a locale-sensitive - * way. (When specifying a custom comparator, you also need to pass a value for the `reverse` - * argument - passing `false` retains the default sorting order, i.e. ascending.) - * - - -
    -
    -

    Locale-sensitive Comparator

    - - - - - - - - - -
    NameFavorite Letter
    {{friend.name}}{{friend.favoriteLetter}}
    -
    -
    -

    Default Comparator

    - - - - - - - - - -
    NameFavorite Letter
    {{friend.name}}{{friend.favoriteLetter}}
    -
    -
    -
    - - angular.module('orderByExample4', []) - .controller('ExampleController', ['$scope', function($scope) { - $scope.friends = [ - {name: 'John', favoriteLetter: 'Ä'}, - {name: 'Mary', favoriteLetter: 'Ü'}, - {name: 'Mike', favoriteLetter: 'Ö'}, - {name: 'Adam', favoriteLetter: 'H'}, - {name: 'Julie', favoriteLetter: 'Z'} - ]; - - $scope.localeSensitiveComparator = function(v1, v2) { - // If we don't get strings, just compare by index - if (v1.type !== 'string' || v2.type !== 'string') { - return (v1.index < v2.index) ? -1 : 1; - } - - // Compare strings alphabetically, taking locale into account - return v1.value.localeCompare(v2.value); - }; - }]); - - - .friends-container { - display: inline-block; - margin: 0 30px; - } - - .friends { - border-collapse: collapse; - } - - .friends th { - border-bottom: 1px solid; - } - .friends td, .friends th { - border-left: 1px solid; - padding: 5px 10px; - } - .friends td:first-child, .friends th:first-child { - border-left: none; - } - - - // Element locators - var container = element(by.css('.custom-comparator')); - var names = container.all(by.repeater('friends').column('friend.name')); - - it('should sort friends by favorite letter (in correct alphabetical order)', function() { - expect(names.get(0).getText()).toBe('John'); - expect(names.get(1).getText()).toBe('Adam'); - expect(names.get(2).getText()).toBe('Mike'); - expect(names.get(3).getText()).toBe('Mary'); - expect(names.get(4).getText()).toBe('Julie'); - }); - -
    - * - */ -orderByFilter.$inject = ['$parse']; -function orderByFilter($parse) { - return function(array, sortPredicate, reverseOrder, compareFn) { - - if (array == null) return array; - if (!isArrayLike(array)) { - throw minErr('orderBy')('notarray', 'Expected array but received: {0}', array); - } - - if (!isArray(sortPredicate)) { sortPredicate = [sortPredicate]; } - if (sortPredicate.length === 0) { sortPredicate = ['+']; } - - var predicates = processPredicates(sortPredicate); - - var descending = reverseOrder ? -1 : 1; - - // Define the `compare()` function. Use a default comparator if none is specified. - var compare = isFunction(compareFn) ? compareFn : defaultCompare; - - // The next three lines are a version of a Swartzian Transform idiom from Perl - // (sometimes called the Decorate-Sort-Undecorate idiom) - // See https://en.wikipedia.org/wiki/Schwartzian_transform - var compareValues = Array.prototype.map.call(array, getComparisonObject); - compareValues.sort(doComparison); - array = compareValues.map(function(item) { return item.value; }); - - return array; - - function getComparisonObject(value, index) { - // NOTE: We are adding an extra `tieBreaker` value based on the element's index. - // This will be used to keep the sort stable when none of the input predicates can - // distinguish between two elements. - return { - value: value, - tieBreaker: {value: index, type: 'number', index: index}, - predicateValues: predicates.map(function(predicate) { - return getPredicateValue(predicate.get(value), index); - }) - }; - } - - function doComparison(v1, v2) { - for (var i = 0, ii = predicates.length; i < ii; i++) { - var result = compare(v1.predicateValues[i], v2.predicateValues[i]); - if (result) { - return result * predicates[i].descending * descending; - } - } - - return (compare(v1.tieBreaker, v2.tieBreaker) || defaultCompare(v1.tieBreaker, v2.tieBreaker)) * descending; - } - }; - - function processPredicates(sortPredicates) { - return sortPredicates.map(function(predicate) { - var descending = 1, get = identity; - - if (isFunction(predicate)) { - get = predicate; - } else if (isString(predicate)) { - if ((predicate.charAt(0) === '+' || predicate.charAt(0) === '-')) { - descending = predicate.charAt(0) === '-' ? -1 : 1; - predicate = predicate.substring(1); - } - if (predicate !== '') { - get = $parse(predicate); - if (get.constant) { - var key = get(); - get = function(value) { return value[key]; }; - } - } - } - return {get: get, descending: descending}; - }); - } - - function isPrimitive(value) { - switch (typeof value) { - case 'number': /* falls through */ - case 'boolean': /* falls through */ - case 'string': - return true; - default: - return false; - } - } - - function objectValue(value) { - // If `valueOf` is a valid function use that - if (isFunction(value.valueOf)) { - value = value.valueOf(); - if (isPrimitive(value)) return value; - } - // If `toString` is a valid function and not the one from `Object.prototype` use that - if (hasCustomToString(value)) { - value = value.toString(); - if (isPrimitive(value)) return value; - } - - return value; - } - - function getPredicateValue(value, index) { - var type = typeof value; - if (value === null) { - type = 'null'; - } else if (type === 'object') { - value = objectValue(value); - } - return {value: value, type: type, index: index}; - } - - function defaultCompare(v1, v2) { - var result = 0; - var type1 = v1.type; - var type2 = v2.type; - - if (type1 === type2) { - var value1 = v1.value; - var value2 = v2.value; - - if (type1 === 'string') { - // Compare strings case-insensitively - value1 = value1.toLowerCase(); - value2 = value2.toLowerCase(); - } else if (type1 === 'object') { - // For basic objects, use the position of the object - // in the collection instead of the value - if (isObject(value1)) value1 = v1.index; - if (isObject(value2)) value2 = v2.index; - } - - if (value1 !== value2) { - result = value1 < value2 ? -1 : 1; - } - } else { - result = (type1 === 'undefined') ? 1 : - (type2 === 'undefined') ? -1 : - (type1 === 'null') ? 1 : - (type2 === 'null') ? -1 : - (type1 < type2) ? -1 : 1; - } - - return result; - } -} - -function ngDirective(directive) { - if (isFunction(directive)) { - directive = { - link: directive - }; - } - directive.restrict = directive.restrict || 'AC'; - return valueFn(directive); -} - -/** - * @ngdoc directive - * @name a - * @restrict E - * - * @description - * Modifies the default behavior of the html a tag so that the default action is prevented when - * the href attribute is empty. - * - * For dynamically creating `href` attributes for a tags, see the {@link ng.ngHref `ngHref`} directive. - */ -var htmlAnchorDirective = valueFn({ - restrict: 'E', - compile: function(element, attr) { - if (!attr.href && !attr.xlinkHref) { - return function(scope, element) { - // If the linked element is not an anchor tag anymore, do nothing - if (element[0].nodeName.toLowerCase() !== 'a') return; - - // SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute. - var href = toString.call(element.prop('href')) === '[object SVGAnimatedString]' ? - 'xlink:href' : 'href'; - element.on('click', function(event) { - // if we have no href url, then don't navigate anywhere. - if (!element.attr(href)) { - event.preventDefault(); - } - }); - }; - } - } -}); - -/** - * @ngdoc directive - * @name ngHref - * @restrict A - * @priority 99 - * - * @description - * Using AngularJS markup like `{{hash}}` in an href attribute will - * make the link go to the wrong URL if the user clicks it before - * AngularJS has a chance to replace the `{{hash}}` markup with its - * value. Until AngularJS replaces the markup the link will be broken - * and will most likely return a 404 error. The `ngHref` directive - * solves this problem. - * - * The wrong way to write it: - * ```html - * link1 - * ``` - * - * The correct way to write it: - * ```html - * link1 - * ``` - * - * @element A - * @param {template} ngHref any string which can contain `{{}}` markup. - * - * @example - * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes - * in links and their different behaviors: - - -
    - link 1 (link, don't reload)
    - link 2 (link, don't reload)
    - link 3 (link, reload!)
    - anchor (link, don't reload)
    - anchor (no link)
    - link (link, change location) -
    - - it('should execute ng-click but not reload when href without value', function() { - element(by.id('link-1')).click(); - expect(element(by.model('value')).getAttribute('value')).toEqual('1'); - expect(element(by.id('link-1')).getAttribute('href')).toBe(''); - }); - - it('should execute ng-click but not reload when href empty string', function() { - element(by.id('link-2')).click(); - expect(element(by.model('value')).getAttribute('value')).toEqual('2'); - expect(element(by.id('link-2')).getAttribute('href')).toBe(''); - }); - - it('should execute ng-click and change url when ng-href specified', function() { - expect(element(by.id('link-3')).getAttribute('href')).toMatch(/\/123$/); - - element(by.id('link-3')).click(); - - // At this point, we navigate away from an AngularJS page, so we need - // to use browser.driver to get the base webdriver. - - browser.wait(function() { - return browser.driver.getCurrentUrl().then(function(url) { - return url.match(/\/123$/); - }); - }, 5000, 'page should navigate to /123'); - }); - - it('should execute ng-click but not reload when href empty string and name specified', function() { - element(by.id('link-4')).click(); - expect(element(by.model('value')).getAttribute('value')).toEqual('4'); - expect(element(by.id('link-4')).getAttribute('href')).toBe(''); - }); - - it('should execute ng-click but not reload when no href but name specified', function() { - element(by.id('link-5')).click(); - expect(element(by.model('value')).getAttribute('value')).toEqual('5'); - expect(element(by.id('link-5')).getAttribute('href')).toBe(null); - }); - - it('should only change url when only ng-href', function() { - element(by.model('value')).clear(); - element(by.model('value')).sendKeys('6'); - expect(element(by.id('link-6')).getAttribute('href')).toMatch(/\/6$/); - - element(by.id('link-6')).click(); - - // At this point, we navigate away from an AngularJS page, so we need - // to use browser.driver to get the base webdriver. - browser.wait(function() { - return browser.driver.getCurrentUrl().then(function(url) { - return url.match(/\/6$/); - }); - }, 5000, 'page should navigate to /6'); - }); - -
    - */ - -/** - * @ngdoc directive - * @name ngSrc - * @restrict A - * @priority 99 - * - * @description - * Using AngularJS markup like `{{hash}}` in a `src` attribute doesn't - * work right: The browser will fetch from the URL with the literal - * text `{{hash}}` until AngularJS replaces the expression inside - * `{{hash}}`. The `ngSrc` directive solves this problem. - * - * The buggy way to write it: - * ```html - * Description - * ``` - * - * The correct way to write it: - * ```html - * Description - * ``` - * - * @element IMG - * @param {template} ngSrc any string which can contain `{{}}` markup. - */ - -/** - * @ngdoc directive - * @name ngSrcset - * @restrict A - * @priority 99 - * - * @description - * Using AngularJS markup like `{{hash}}` in a `srcset` attribute doesn't - * work right: The browser will fetch from the URL with the literal - * text `{{hash}}` until AngularJS replaces the expression inside - * `{{hash}}`. The `ngSrcset` directive solves this problem. - * - * The buggy way to write it: - * ```html - * Description - * ``` - * - * The correct way to write it: - * ```html - * Description - * ``` - * - * @element IMG - * @param {template} ngSrcset any string which can contain `{{}}` markup. - */ - -/** - * @ngdoc directive - * @name ngDisabled - * @restrict A - * @priority 100 - * - * @description - * - * This directive sets the `disabled` attribute on the element (typically a form control, - * e.g. `input`, `button`, `select` etc.) if the - * {@link guide/expression expression} inside `ngDisabled` evaluates to truthy. - * - * A special directive is necessary because we cannot use interpolation inside the `disabled` - * attribute. See the {@link guide/interpolation interpolation guide} for more info. - * - * @example - - -
    - -
    - - it('should toggle button', function() { - expect(element(by.css('button')).getAttribute('disabled')).toBeFalsy(); - element(by.model('checked')).click(); - expect(element(by.css('button')).getAttribute('disabled')).toBeTruthy(); - }); - -
    - * - * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy, - * then the `disabled` attribute will be set on the element - */ - - -/** - * @ngdoc directive - * @name ngChecked - * @restrict A - * @priority 100 - * - * @description - * Sets the `checked` attribute on the element, if the expression inside `ngChecked` is truthy. - * - * Note that this directive should not be used together with {@link ngModel `ngModel`}, - * as this can lead to unexpected behavior. - * - * A special directive is necessary because we cannot use interpolation inside the `checked` - * attribute. See the {@link guide/interpolation interpolation guide} for more info. - * - * @example - - -
    - -
    - - it('should check both checkBoxes', function() { - expect(element(by.id('checkFollower')).getAttribute('checked')).toBeFalsy(); - element(by.model('leader')).click(); - expect(element(by.id('checkFollower')).getAttribute('checked')).toBeTruthy(); - }); - -
    - * - * @element INPUT - * @param {expression} ngChecked If the {@link guide/expression expression} is truthy, - * then the `checked` attribute will be set on the element - */ - - -/** - * @ngdoc directive - * @name ngReadonly - * @restrict A - * @priority 100 - * - * @description - * - * Sets the `readonly` attribute on the element, if the expression inside `ngReadonly` is truthy. - * Note that `readonly` applies only to `input` elements with specific types. [See the input docs on - * MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-readonly) for more information. - * - * A special directive is necessary because we cannot use interpolation inside the `readonly` - * attribute. See the {@link guide/interpolation interpolation guide} for more info. - * - * @example - - -
    - -
    - - it('should toggle readonly attr', function() { - expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeFalsy(); - element(by.model('checked')).click(); - expect(element(by.css('[type="text"]')).getAttribute('readonly')).toBeTruthy(); - }); - -
    - * - * @element INPUT - * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy, - * then special attribute "readonly" will be set on the element - */ - - -/** - * @ngdoc directive - * @name ngSelected - * @restrict A - * @priority 100 - * - * @description - * - * Sets the `selected` attribute on the element, if the expression inside `ngSelected` is truthy. - * - * A special directive is necessary because we cannot use interpolation inside the `selected` - * attribute. See the {@link guide/interpolation interpolation guide} for more info. - * - *
    - * **Note:** `ngSelected` does not interact with the `select` and `ngModel` directives, it only - * sets the `selected` attribute on the element. If you are using `ngModel` on the select, you - * should not use `ngSelected` on the options, as `ngModel` will set the select value and - * selected options. - *
    - * - * @example - - -
    - -
    - - it('should select Greetings!', function() { - expect(element(by.id('greet')).getAttribute('selected')).toBeFalsy(); - element(by.model('selected')).click(); - expect(element(by.id('greet')).getAttribute('selected')).toBeTruthy(); - }); - -
    - * - * @element OPTION - * @param {expression} ngSelected If the {@link guide/expression expression} is truthy, - * then special attribute "selected" will be set on the element - */ - -/** - * @ngdoc directive - * @name ngOpen - * @restrict A - * @priority 100 - * - * @description - * - * Sets the `open` attribute on the element, if the expression inside `ngOpen` is truthy. - * - * A special directive is necessary because we cannot use interpolation inside the `open` - * attribute. See the {@link guide/interpolation interpolation guide} for more info. - * - * ## A note about browser compatibility - * - * Internet Explorer and Edge do not support the `details` element, it is - * recommended to use {@link ng.ngShow} and {@link ng.ngHide} instead. - * - * @example - - -
    -
    - List -
      -
    • Apple
    • -
    • Orange
    • -
    • Durian
    • -
    -
    -
    - - it('should toggle open', function() { - expect(element(by.id('details')).getAttribute('open')).toBeFalsy(); - element(by.model('open')).click(); - expect(element(by.id('details')).getAttribute('open')).toBeTruthy(); - }); - -
    - * - * @element DETAILS - * @param {expression} ngOpen If the {@link guide/expression expression} is truthy, - * then special attribute "open" will be set on the element - */ - -var ngAttributeAliasDirectives = {}; - -// boolean attrs are evaluated -forEach(BOOLEAN_ATTR, function(propName, attrName) { - // binding to multiple is not supported - if (propName === 'multiple') return; - - function defaultLinkFn(scope, element, attr) { - scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { - attr.$set(attrName, !!value); - }); - } - - var normalized = directiveNormalize('ng-' + attrName); - var linkFn = defaultLinkFn; - - if (propName === 'checked') { - linkFn = function(scope, element, attr) { - // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input - if (attr.ngModel !== attr[normalized]) { - defaultLinkFn(scope, element, attr); - } - }; - } - - ngAttributeAliasDirectives[normalized] = function() { - return { - restrict: 'A', - priority: 100, - link: linkFn - }; - }; -}); - -// aliased input attrs are evaluated -forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) { - ngAttributeAliasDirectives[ngAttr] = function() { - return { - priority: 100, - link: function(scope, element, attr) { - //special case ngPattern when a literal regular expression value - //is used as the expression (this way we don't have to watch anything). - if (ngAttr === 'ngPattern' && attr.ngPattern.charAt(0) === '/') { - var match = attr.ngPattern.match(REGEX_STRING_REGEXP); - if (match) { - attr.$set('ngPattern', new RegExp(match[1], match[2])); - return; - } - } - - scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) { - attr.$set(ngAttr, value); - }); - } - }; - }; -}); - -// ng-src, ng-srcset, ng-href are interpolated -forEach(['src', 'srcset', 'href'], function(attrName) { - var normalized = directiveNormalize('ng-' + attrName); - ngAttributeAliasDirectives[normalized] = ['$sce', function($sce) { - return { - priority: 99, // it needs to run after the attributes are interpolated - link: function(scope, element, attr) { - var propName = attrName, - name = attrName; - - if (attrName === 'href' && - toString.call(element.prop('href')) === '[object SVGAnimatedString]') { - name = 'xlinkHref'; - attr.$attr[name] = 'xlink:href'; - propName = null; - } - - // We need to sanitize the url at least once, in case it is a constant - // non-interpolated attribute. - attr.$set(normalized, $sce.getTrustedMediaUrl(attr[normalized])); - - attr.$observe(normalized, function(value) { - if (!value) { - if (attrName === 'href') { - attr.$set(name, null); - } - return; - } - - attr.$set(name, value); - - // Support: IE 9-11 only - // On IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist - // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need - // to set the property as well to achieve the desired effect. - // We use attr[attrName] value since $set might have sanitized the url. - if (msie && propName) element.prop(propName, attr[name]); - }); - } - }; - }]; -}); - -/* global -nullFormCtrl, -PENDING_CLASS, -SUBMITTED_CLASS - */ -var nullFormCtrl = { - $addControl: noop, - $getControls: valueFn([]), - $$renameControl: nullFormRenameControl, - $removeControl: noop, - $setValidity: noop, - $setDirty: noop, - $setPristine: noop, - $setSubmitted: noop, - $$setSubmitted: noop -}, -PENDING_CLASS = 'ng-pending', -SUBMITTED_CLASS = 'ng-submitted'; - -function nullFormRenameControl(control, name) { - control.$name = name; -} - -/** - * @ngdoc type - * @name form.FormController - * - * @property {boolean} $pristine True if user has not interacted with the form yet. - * @property {boolean} $dirty True if user has already interacted with the form. - * @property {boolean} $valid True if all of the containing forms and controls are valid. - * @property {boolean} $invalid True if at least one containing control or form is invalid. - * @property {boolean} $submitted True if user has submitted the form even if its invalid. - * - * @property {Object} $pending An object hash, containing references to controls or forms with - * pending validators, where: - * - * - keys are validations tokens (error names). - * - values are arrays of controls or forms that have a pending validator for the given error name. - * - * See {@link form.FormController#$error $error} for a list of built-in validation tokens. - * - * @property {Object} $error An object hash, containing references to controls or forms with failing - * validators, where: - * - * - keys are validation tokens (error names), - * - values are arrays of controls or forms that have a failing validator for the given error name. - * - * Built-in validation tokens: - * - `email` - * - `max` - * - `maxlength` - * - `min` - * - `minlength` - * - `number` - * - `pattern` - * - `required` - * - `url` - * - `date` - * - `datetimelocal` - * - `time` - * - `week` - * - `month` - * - * @description - * `FormController` keeps track of all its controls and nested forms as well as the state of them, - * such as being valid/invalid or dirty/pristine. - * - * Each {@link ng.directive:form form} directive creates an instance - * of `FormController`. - * - */ -//asks for $scope to fool the BC controller module -FormController.$inject = ['$element', '$attrs', '$scope', '$animate', '$interpolate']; -function FormController($element, $attrs, $scope, $animate, $interpolate) { - this.$$controls = []; - - // init state - this.$error = {}; - this.$$success = {}; - this.$pending = undefined; - this.$name = $interpolate($attrs.name || $attrs.ngForm || '')($scope); - this.$dirty = false; - this.$pristine = true; - this.$valid = true; - this.$invalid = false; - this.$submitted = false; - this.$$parentForm = nullFormCtrl; - - this.$$element = $element; - this.$$animate = $animate; - - setupValidity(this); -} - -FormController.prototype = { - /** - * @ngdoc method - * @name form.FormController#$rollbackViewValue - * - * @description - * Rollback all form controls pending updates to the `$modelValue`. - * - * Updates may be pending by a debounced event or because the input is waiting for a some future - * event defined in `ng-model-options`. This method is typically needed by the reset button of - * a form that uses `ng-model-options` to pend updates. - */ - $rollbackViewValue: function() { - forEach(this.$$controls, function(control) { - control.$rollbackViewValue(); - }); - }, - - /** - * @ngdoc method - * @name form.FormController#$commitViewValue - * - * @description - * Commit all form controls pending updates to the `$modelValue`. - * - * Updates may be pending by a debounced event or because the input is waiting for a some future - * event defined in `ng-model-options`. This method is rarely needed as `NgModelController` - * usually handles calling this in response to input events. - */ - $commitViewValue: function() { - forEach(this.$$controls, function(control) { - control.$commitViewValue(); - }); - }, - - /** - * @ngdoc method - * @name form.FormController#$addControl - * @param {object} control control object, either a {@link form.FormController} or an - * {@link ngModel.NgModelController} - * - * @description - * Register a control with the form. Input elements using ngModelController do this automatically - * when they are linked. - * - * Note that the current state of the control will not be reflected on the new parent form. This - * is not an issue with normal use, as freshly compiled and linked controls are in a `$pristine` - * state. - * - * However, if the method is used programmatically, for example by adding dynamically created controls, - * or controls that have been previously removed without destroying their corresponding DOM element, - * it's the developers responsibility to make sure the current state propagates to the parent form. - * - * For example, if an input control is added that is already `$dirty` and has `$error` properties, - * calling `$setDirty()` and `$validate()` afterwards will propagate the state to the parent form. - */ - $addControl: function(control) { - // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored - // and not added to the scope. Now we throw an error. - assertNotHasOwnProperty(control.$name, 'input'); - this.$$controls.push(control); - - if (control.$name) { - this[control.$name] = control; - } - - control.$$parentForm = this; - }, - - /** - * @ngdoc method - * @name form.FormController#$getControls - * @returns {Array} the controls that are currently part of this form - * - * @description - * This method returns a **shallow copy** of the controls that are currently part of this form. - * The controls can be instances of {@link form.FormController `FormController`} - * ({@link ngForm "child-forms"}) and of {@link ngModel.NgModelController `NgModelController`}. - * If you need access to the controls of child-forms, you have to call `$getControls()` - * recursively on them. - * This can be used for example to iterate over all controls to validate them. - * - * The controls can be accessed normally, but adding to, or removing controls from the array has - * no effect on the form. Instead, use {@link form.FormController#$addControl `$addControl()`} and - * {@link form.FormController#$removeControl `$removeControl()`} for this use-case. - * Likewise, adding a control to, or removing a control from the form is not reflected - * in the shallow copy. That means you should get a fresh copy from `$getControls()` every time - * you need access to the controls. - */ - $getControls: function() { - return shallowCopy(this.$$controls); - }, - - // Private API: rename a form control - $$renameControl: function(control, newName) { - var oldName = control.$name; - - if (this[oldName] === control) { - delete this[oldName]; - } - this[newName] = control; - control.$name = newName; - }, - - /** - * @ngdoc method - * @name form.FormController#$removeControl - * @param {object} control control object, either a {@link form.FormController} or an - * {@link ngModel.NgModelController} - * - * @description - * Deregister a control from the form. - * - * Input elements using ngModelController do this automatically when they are destroyed. - * - * Note that only the removed control's validation state (`$errors`etc.) will be removed from the - * form. `$dirty`, `$submitted` states will not be changed, because the expected behavior can be - * different from case to case. For example, removing the only `$dirty` control from a form may or - * may not mean that the form is still `$dirty`. - */ - $removeControl: function(control) { - if (control.$name && this[control.$name] === control) { - delete this[control.$name]; - } - forEach(this.$pending, function(value, name) { - // eslint-disable-next-line no-invalid-this - this.$setValidity(name, null, control); - }, this); - forEach(this.$error, function(value, name) { - // eslint-disable-next-line no-invalid-this - this.$setValidity(name, null, control); - }, this); - forEach(this.$$success, function(value, name) { - // eslint-disable-next-line no-invalid-this - this.$setValidity(name, null, control); - }, this); - - arrayRemove(this.$$controls, control); - control.$$parentForm = nullFormCtrl; - }, - - /** - * @ngdoc method - * @name form.FormController#$setDirty - * - * @description - * Sets the form to a dirty state. - * - * This method can be called to add the 'ng-dirty' class and set the form to a dirty - * state (ng-dirty class). This method will also propagate to parent forms. - */ - $setDirty: function() { - this.$$animate.removeClass(this.$$element, PRISTINE_CLASS); - this.$$animate.addClass(this.$$element, DIRTY_CLASS); - this.$dirty = true; - this.$pristine = false; - this.$$parentForm.$setDirty(); - }, - - /** - * @ngdoc method - * @name form.FormController#$setPristine - * - * @description - * Sets the form to its pristine state. - * - * This method sets the form's `$pristine` state to true, the `$dirty` state to false, removes - * the `ng-dirty` class and adds the `ng-pristine` class. Additionally, it sets the `$submitted` - * state to false. - * - * This method will also propagate to all the controls contained in this form. - * - * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after - * saving or resetting it. - */ - $setPristine: function() { - this.$$animate.setClass(this.$$element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS); - this.$dirty = false; - this.$pristine = true; - this.$submitted = false; - forEach(this.$$controls, function(control) { - control.$setPristine(); - }); - }, - - /** - * @ngdoc method - * @name form.FormController#$setUntouched - * - * @description - * Sets the form to its untouched state. - * - * This method can be called to remove the 'ng-touched' class and set the form controls to their - * untouched state (ng-untouched class). - * - * Setting a form controls back to their untouched state is often useful when setting the form - * back to its pristine state. - */ - $setUntouched: function() { - forEach(this.$$controls, function(control) { - control.$setUntouched(); - }); - }, - - /** - * @ngdoc method - * @name form.FormController#$setSubmitted - * - * @description - * Sets the form to its `$submitted` state. This will also set `$submitted` on all child and - * parent forms of the form. - */ - $setSubmitted: function() { - var rootForm = this; - while (rootForm.$$parentForm && (rootForm.$$parentForm !== nullFormCtrl)) { - rootForm = rootForm.$$parentForm; - } - rootForm.$$setSubmitted(); - }, - - $$setSubmitted: function() { - this.$$animate.addClass(this.$$element, SUBMITTED_CLASS); - this.$submitted = true; - forEach(this.$$controls, function(control) { - if (control.$$setSubmitted) { - control.$$setSubmitted(); - } - }); - } -}; - -/** - * @ngdoc method - * @name form.FormController#$setValidity - * - * @description - * Change the validity state of the form, and notify the parent form (if any). - * - * Application developers will rarely need to call this method directly. It is used internally, by - * {@link ngModel.NgModelController#$setValidity NgModelController.$setValidity()}, to propagate a - * control's validity state to the parent `FormController`. - * - * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be - * assigned to either `$error[validationErrorKey]` or `$pending[validationErrorKey]` (for - * unfulfilled `$asyncValidators`), so that it is available for data-binding. The - * `validationErrorKey` should be in camelCase and will get converted into dash-case for - * class name. Example: `myError` will result in `ng-valid-my-error` and - * `ng-invalid-my-error` classes and can be bound to as `{{ someForm.$error.myError }}`. - * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending - * (undefined), or skipped (null). Pending is used for unfulfilled `$asyncValidators`. - * Skipped is used by AngularJS when validators do not run because of parse errors and when - * `$asyncValidators` do not run because any of the `$validators` failed. - * @param {NgModelController | FormController} controller - The controller whose validity state is - * triggering the change. - */ -addSetValidityMethod({ - clazz: FormController, - set: function(object, property, controller) { - var list = object[property]; - if (!list) { - object[property] = [controller]; - } else { - var index = list.indexOf(controller); - if (index === -1) { - list.push(controller); - } - } - }, - unset: function(object, property, controller) { - var list = object[property]; - if (!list) { - return; - } - arrayRemove(list, controller); - if (list.length === 0) { - delete object[property]; - } - } -}); - -/** - * @ngdoc directive - * @name ngForm - * @restrict EAC - * - * @description - * Helper directive that makes it possible to create control groups inside a - * {@link ng.directive:form `form`} directive. - * These "child forms" can be used, for example, to determine the validity of a sub-group of - * controls. - * - *
    - * **Note**: `ngForm` cannot be used as a replacement for `
    `, because it lacks its - * [built-in HTML functionality](https://html.spec.whatwg.org/#the-form-element). - * Specifically, you cannot submit `ngForm` like a `` tag. That means, - * you cannot send data to the server with `ngForm`, or integrate it with - * {@link ng.directive:ngSubmit `ngSubmit`}. - *
    - * - * @param {string=} ngForm|name Name of the form. If specified, the form controller will - * be published into the related scope, under this name. - * - */ - - /** - * @ngdoc directive - * @name form - * @restrict E - * - * @description - * Directive that instantiates - * {@link form.FormController FormController}. - * - * If the `name` attribute is specified, the form controller is published onto the current scope under - * this name. - * - * ## Alias: {@link ng.directive:ngForm `ngForm`} - * - * In AngularJS, forms can be nested. This means that the outer form is valid when all of the child - * forms are valid as well. However, browsers do not allow nesting of `` elements, so - * AngularJS provides the {@link ng.directive:ngForm `ngForm`} directive, which behaves identically to - * `form` but can be nested. Nested forms can be useful, for example, if the validity of a sub-group - * of controls needs to be determined. - * - * ## CSS classes - * - `ng-valid` is set if the form is valid. - * - `ng-invalid` is set if the form is invalid. - * - `ng-pending` is set if the form is pending. - * - `ng-pristine` is set if the form is pristine. - * - `ng-dirty` is set if the form is dirty. - * - `ng-submitted` is set if the form was submitted. - * - * Keep in mind that ngAnimate can detect each of these classes when added and removed. - * - * - * ## Submitting a form and preventing the default action - * - * Since the role of forms in client-side AngularJS applications is different than in classical - * roundtrip apps, it is desirable for the browser not to translate the form submission into a full - * page reload that sends the data to the server. Instead some javascript logic should be triggered - * to handle the form submission in an application-specific way. - * - * For this reason, AngularJS prevents the default action (form submission to the server) unless the - * `` element has an `action` attribute specified. - * - * You can use one of the following two ways to specify what javascript method should be called when - * a form is submitted: - * - * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element - * - {@link ng.directive:ngClick ngClick} directive on the first - * button or input field of type submit (input[type=submit]) - * - * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit} - * or {@link ng.directive:ngClick ngClick} directives. - * This is because of the following form submission rules in the HTML specification: - * - * - If a form has only one input field then hitting enter in this field triggers form submit - * (`ngSubmit`) - * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter - * doesn't trigger submit - * - if a form has one or more input fields and one or more buttons or input[type=submit] then - * hitting enter in any of the input fields will trigger the click handler on the *first* button or - * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`) - * - * Any pending `ngModelOptions` changes will take place immediately when an enclosing form is - * submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` - * to have access to the updated model. - * - * @animations - * Animations in ngForm are triggered when any of the associated CSS classes are added and removed. - * These classes are: `.ng-pristine`, `.ng-dirty`, `.ng-invalid` and `.ng-valid` as well as any - * other validations that are performed within the form. Animations in ngForm are similar to how - * they work in ngClass and animations can be hooked into using CSS transitions, keyframes as well - * as JS animations. - * - * The following example shows a simple way to utilize CSS transitions to style a form element - * that has been rendered as invalid after it has been validated: - * - *
    - * //be sure to include ngAnimate as a module to hook into more
    - * //advanced animations
    - * .my-form {
    - *   transition:0.5s linear all;
    - *   background: white;
    - * }
    - * .my-form.ng-invalid {
    - *   background: red;
    - *   color:white;
    - * }
    - * 
    - * - * @example - - - - - - userType: - Required!
    - userType = {{userType}}
    - myForm.input.$valid = {{myForm.input.$valid}}
    - myForm.input.$error = {{myForm.input.$error}}
    - myForm.$valid = {{myForm.$valid}}
    - myForm.$error.required = {{!!myForm.$error.required}}
    - -
    - - it('should initialize to model', function() { - var userType = element(by.binding('userType')); - var valid = element(by.binding('myForm.input.$valid')); - - expect(userType.getText()).toContain('guest'); - expect(valid.getText()).toContain('true'); - }); - - it('should be invalid if empty', function() { - var userType = element(by.binding('userType')); - var valid = element(by.binding('myForm.input.$valid')); - var userInput = element(by.model('userType')); - - userInput.clear(); - userInput.sendKeys(''); - - expect(userType.getText()).toEqual('userType ='); - expect(valid.getText()).toContain('false'); - }); - -
    - * - * @param {string=} name Name of the form. If specified, the form controller will be published into - * related scope, under this name. - */ -var formDirectiveFactory = function(isNgForm) { - return ['$timeout', '$parse', function($timeout, $parse) { - var formDirective = { - name: 'form', - restrict: isNgForm ? 'EAC' : 'E', - require: ['form', '^^?form'], //first is the form's own ctrl, second is an optional parent form - controller: FormController, - compile: function ngFormCompile(formElement, attr) { - // Setup initial state of the control - formElement.addClass(PRISTINE_CLASS).addClass(VALID_CLASS); - - var nameAttr = attr.name ? 'name' : (isNgForm && attr.ngForm ? 'ngForm' : false); - - return { - pre: function ngFormPreLink(scope, formElement, attr, ctrls) { - var controller = ctrls[0]; - - // if `action` attr is not present on the form, prevent the default action (submission) - if (!('action' in attr)) { - // we can't use jq events because if a form is destroyed during submission the default - // action is not prevented. see #1238 - // - // IE 9 is not affected because it doesn't fire a submit event and try to do a full - // page reload if the form was destroyed by submission of the form via a click handler - // on a button in the form. Looks like an IE9 specific bug. - var handleFormSubmission = function(event) { - scope.$apply(function() { - controller.$commitViewValue(); - controller.$setSubmitted(); - }); - - event.preventDefault(); - }; - - formElement[0].addEventListener('submit', handleFormSubmission); - - // unregister the preventDefault listener so that we don't not leak memory but in a - // way that will achieve the prevention of the default action. - formElement.on('$destroy', function() { - $timeout(function() { - formElement[0].removeEventListener('submit', handleFormSubmission); - }, 0, false); - }); - } - - var parentFormCtrl = ctrls[1] || controller.$$parentForm; - parentFormCtrl.$addControl(controller); - - var setter = nameAttr ? getSetter(controller.$name) : noop; - - if (nameAttr) { - setter(scope, controller); - attr.$observe(nameAttr, function(newValue) { - if (controller.$name === newValue) return; - setter(scope, undefined); - controller.$$parentForm.$$renameControl(controller, newValue); - setter = getSetter(controller.$name); - setter(scope, controller); - }); - } - formElement.on('$destroy', function() { - controller.$$parentForm.$removeControl(controller); - setter(scope, undefined); - extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards - }); - } - }; - } - }; - - return formDirective; - - function getSetter(expression) { - if (expression === '') { - //create an assignable expression, so forms with an empty name can be renamed later - return $parse('this[""]').assign; - } - return $parse(expression).assign || noop; - } - }]; -}; - -var formDirective = formDirectiveFactory(); -var ngFormDirective = formDirectiveFactory(true); - - - -// helper methods -function setupValidity(instance) { - instance.$$classCache = {}; - instance.$$classCache[INVALID_CLASS] = !(instance.$$classCache[VALID_CLASS] = instance.$$element.hasClass(VALID_CLASS)); -} -function addSetValidityMethod(context) { - var clazz = context.clazz, - set = context.set, - unset = context.unset; - - clazz.prototype.$setValidity = function(validationErrorKey, state, controller) { - if (isUndefined(state)) { - createAndSet(this, '$pending', validationErrorKey, controller); - } else { - unsetAndCleanup(this, '$pending', validationErrorKey, controller); - } - if (!isBoolean(state)) { - unset(this.$error, validationErrorKey, controller); - unset(this.$$success, validationErrorKey, controller); - } else { - if (state) { - unset(this.$error, validationErrorKey, controller); - set(this.$$success, validationErrorKey, controller); - } else { - set(this.$error, validationErrorKey, controller); - unset(this.$$success, validationErrorKey, controller); - } - } - if (this.$pending) { - cachedToggleClass(this, PENDING_CLASS, true); - this.$valid = this.$invalid = undefined; - toggleValidationCss(this, '', null); - } else { - cachedToggleClass(this, PENDING_CLASS, false); - this.$valid = isObjectEmpty(this.$error); - this.$invalid = !this.$valid; - toggleValidationCss(this, '', this.$valid); - } - - // re-read the state as the set/unset methods could have - // combined state in this.$error[validationError] (used for forms), - // where setting/unsetting only increments/decrements the value, - // and does not replace it. - var combinedState; - if (this.$pending && this.$pending[validationErrorKey]) { - combinedState = undefined; - } else if (this.$error[validationErrorKey]) { - combinedState = false; - } else if (this.$$success[validationErrorKey]) { - combinedState = true; - } else { - combinedState = null; - } - - toggleValidationCss(this, validationErrorKey, combinedState); - this.$$parentForm.$setValidity(validationErrorKey, combinedState, this); - }; - - function createAndSet(ctrl, name, value, controller) { - if (!ctrl[name]) { - ctrl[name] = {}; - } - set(ctrl[name], value, controller); - } - - function unsetAndCleanup(ctrl, name, value, controller) { - if (ctrl[name]) { - unset(ctrl[name], value, controller); - } - if (isObjectEmpty(ctrl[name])) { - ctrl[name] = undefined; - } - } - - function cachedToggleClass(ctrl, className, switchValue) { - if (switchValue && !ctrl.$$classCache[className]) { - ctrl.$$animate.addClass(ctrl.$$element, className); - ctrl.$$classCache[className] = true; - } else if (!switchValue && ctrl.$$classCache[className]) { - ctrl.$$animate.removeClass(ctrl.$$element, className); - ctrl.$$classCache[className] = false; - } - } - - function toggleValidationCss(ctrl, validationErrorKey, isValid) { - validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; - - cachedToggleClass(ctrl, VALID_CLASS + validationErrorKey, isValid === true); - cachedToggleClass(ctrl, INVALID_CLASS + validationErrorKey, isValid === false); - } -} - -function isObjectEmpty(obj) { - if (obj) { - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { - return false; - } - } - } - return true; -} - -/* global - VALID_CLASS: false, - INVALID_CLASS: false, - PRISTINE_CLASS: false, - DIRTY_CLASS: false, - ngModelMinErr: false -*/ - -// Regex code was initially obtained from SO prior to modification: https://stackoverflow.com/questions/3143070/javascript-regex-iso-datetime#answer-3143231 -var ISO_DATE_REGEXP = /^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/; -// See valid URLs in RFC3987 (http://tools.ietf.org/html/rfc3987) -// Note: We are being more lenient, because browsers are too. -// 1. Scheme -// 2. Slashes -// 3. Username -// 4. Password -// 5. Hostname -// 6. Port -// 7. Path -// 8. Query -// 9. Fragment -// 1111111111111111 222 333333 44444 55555555555555555555555 666 77777777 8888888 999 -var URL_REGEXP = /^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i; -// eslint-disable-next-line max-len -var EMAIL_REGEXP = /^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/; -var NUMBER_REGEXP = /^\s*(-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/; -var DATE_REGEXP = /^(\d{4,})-(\d{2})-(\d{2})$/; -var DATETIMELOCAL_REGEXP = /^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; -var WEEK_REGEXP = /^(\d{4,})-W(\d\d)$/; -var MONTH_REGEXP = /^(\d{4,})-(\d\d)$/; -var TIME_REGEXP = /^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/; - -var PARTIAL_VALIDATION_EVENTS = 'keydown wheel mousedown'; -var PARTIAL_VALIDATION_TYPES = createMap(); -forEach('date,datetime-local,month,time,week'.split(','), function(type) { - PARTIAL_VALIDATION_TYPES[type] = true; -}); - -var inputType = { - - /** - * @ngdoc input - * @name input[text] - * - * @description - * Standard HTML text input with AngularJS data binding, inherited by most of the `input` elements. - * - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Adds `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of - * any length. - * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string - * that contains the regular expression body that will be converted to a regular expression - * as in the ngPattern directive. - * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} - * does not match a RegExp found by evaluating the AngularJS expression given in the attribute value. - * If the expression evaluates to a RegExp object, then this is used directly. - * If the expression evaluates to a string, then it will be converted to a RegExp - * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to - * `new RegExp('^abc$')`.
    - * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to - * start at the index of the last search's match, thus not taking the whole input value into - * account. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * @param {boolean=} [ngTrim=true] If set to false AngularJS will not automatically trim the input. - * This parameter is ignored for input[type=password] controls, which will never trim the - * input. - * - * @example - - - -
    - -
    - - Required! - - Single word only! -
    - text = {{example.text}}
    - myForm.input.$valid = {{myForm.input.$valid}}
    - myForm.input.$error = {{myForm.input.$error}}
    - myForm.$valid = {{myForm.$valid}}
    - myForm.$error.required = {{!!myForm.$error.required}}
    -
    -
    - - var text = element(by.binding('example.text')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('example.text')); - - it('should initialize to model', function() { - expect(text.getText()).toContain('guest'); - expect(valid.getText()).toContain('true'); - }); - - it('should be invalid if empty', function() { - input.clear(); - input.sendKeys(''); - - expect(text.getText()).toEqual('text ='); - expect(valid.getText()).toContain('false'); - }); - - it('should be invalid if multi word', function() { - input.clear(); - input.sendKeys('hello world'); - - expect(valid.getText()).toContain('false'); - }); - -
    - */ - 'text': textInputType, - - /** - * @ngdoc input - * @name input[date] - * - * @description - * Input with date validation and transformation. In browsers that do not yet support - * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601 - * date format (yyyy-MM-dd), for example: `2009-01-06`. Since many - * modern browsers do not yet support this input type, it is important to provide cues to users on the - * expected input format via a placeholder or label. - * - * The model must always be a Date object, otherwise AngularJS will throw an error. - * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. - * - * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a - * valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute - * (e.g. `min="{{minDate | date:'yyyy-MM-dd'}}"`). Note that `min` will also add native HTML5 - * constraint validation. - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be - * a valid ISO date string (yyyy-MM-dd). You can also use interpolation inside this attribute - * (e.g. `max="{{maxDate | date:'yyyy-MM-dd'}}"`). Note that `max` will also add native HTML5 - * constraint validation. - * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO date string - * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. - * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO date string - * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
    - - -
    - - Required! - - Not a valid date! -
    - value = {{example.value | date: "yyyy-MM-dd"}}
    - myForm.input.$valid = {{myForm.input.$valid}}
    - myForm.input.$error = {{myForm.input.$error}}
    - myForm.$valid = {{myForm.$valid}}
    - myForm.$error.required = {{!!myForm.$error.required}}
    -
    -
    - - var value = element(by.binding('example.value | date: "yyyy-MM-dd"')); - var valid = element(by.binding('myForm.input.$valid')); - - // currently protractor/webdriver does not support - // sending keys to all known HTML5 input controls - // for various browsers (see https://github.com/angular/protractor/issues/562). - function setInput(val) { - // set the value of the element and force validation. - var scr = "var ipt = document.getElementById('exampleInput'); " + - "ipt.value = '" + val + "';" + - "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; - browser.executeScript(scr); - } - - it('should initialize to model', function() { - expect(value.getText()).toContain('2013-10-22'); - expect(valid.getText()).toContain('myForm.input.$valid = true'); - }); - - it('should be invalid if empty', function() { - setInput(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - - it('should be invalid if over max', function() { - setInput('2015-01-01'); - expect(value.getText()).toContain(''); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - -
    - */ - 'date': createDateInputType('date', DATE_REGEXP, - createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']), - 'yyyy-MM-dd'), - - /** - * @ngdoc input - * @name input[datetime-local] - * - * @description - * Input with datetime validation and transformation. In browsers that do not yet support - * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 - * local datetime format (yyyy-MM-ddTHH:mm:ss), for example: `2010-12-28T14:57:00`. - * - * The model must always be a Date object, otherwise AngularJS will throw an error. - * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. - * - * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. - * - * The format of the displayed time can be adjusted with the - * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat` - * and `timeStripZeroSeconds`. - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. - * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation - * inside this attribute (e.g. `min="{{minDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`). - * Note that `min` will also add native HTML5 constraint validation. - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. - * This must be a valid ISO datetime format (yyyy-MM-ddTHH:mm:ss). You can also use interpolation - * inside this attribute (e.g. `max="{{maxDatetimeLocal | date:'yyyy-MM-ddTHH:mm:ss'}}"`). - * Note that `max` will also add native HTML5 constraint validation. - * @param {(date|string)=} ngMin Sets the `min` validation error key to the Date / ISO datetime string - * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. - * @param {(date|string)=} ngMax Sets the `max` validation error key to the Date / ISO datetime string - * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
    - - -
    - - Required! - - Not a valid date! -
    - value = {{example.value | date: "yyyy-MM-ddTHH:mm:ss"}}
    - myForm.input.$valid = {{myForm.input.$valid}}
    - myForm.input.$error = {{myForm.input.$error}}
    - myForm.$valid = {{myForm.$valid}}
    - myForm.$error.required = {{!!myForm.$error.required}}
    -
    -
    - - var value = element(by.binding('example.value | date: "yyyy-MM-ddTHH:mm:ss"')); - var valid = element(by.binding('myForm.input.$valid')); - - // currently protractor/webdriver does not support - // sending keys to all known HTML5 input controls - // for various browsers (https://github.com/angular/protractor/issues/562). - function setInput(val) { - // set the value of the element and force validation. - var scr = "var ipt = document.getElementById('exampleInput'); " + - "ipt.value = '" + val + "';" + - "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; - browser.executeScript(scr); - } - - it('should initialize to model', function() { - expect(value.getText()).toContain('2010-12-28T14:57:00'); - expect(valid.getText()).toContain('myForm.input.$valid = true'); - }); - - it('should be invalid if empty', function() { - setInput(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - - it('should be invalid if over max', function() { - setInput('2015-01-01T23:59:00'); - expect(value.getText()).toContain(''); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - -
    - */ - 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP, - createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'sss']), - 'yyyy-MM-ddTHH:mm:ss.sss'), - - /** - * @ngdoc input - * @name input[time] - * - * @description - * Input with time validation and transformation. In browsers that do not yet support - * the HTML5 time input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 - * local time format (HH:mm:ss), for example: `14:57:00`. Model must be a Date object. This binding will always output a - * Date object to the model of January 1, 1970, or local date `new Date(1970, 0, 1, HH, mm, ss)`. - * - * The model must always be a Date object, otherwise AngularJS will throw an error. - * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. - * - * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions}. By default, - * this is the timezone of the browser. - * - * The format of the displayed time can be adjusted with the - * {@link ng.directive:ngModelOptions#ngModelOptions-arguments ngModelOptions} `timeSecondsFormat` - * and `timeStripZeroSeconds`. - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. - * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this - * attribute (e.g. `min="{{minTime | date:'HH:mm:ss'}}"`). Note that `min` will also add - * native HTML5 constraint validation. - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. - * This must be a valid ISO time format (HH:mm:ss). You can also use interpolation inside this - * attribute (e.g. `max="{{maxTime | date:'HH:mm:ss'}}"`). Note that `max` will also add - * native HTML5 constraint validation. - * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO time string the - * `ngMin` expression evaluates to. Note that it does not set the `min` attribute. - * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO time string the - * `ngMax` expression evaluates to. Note that it does not set the `max` attribute. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
    - - -
    - - Required! - - Not a valid date! -
    - value = {{example.value | date: "HH:mm:ss"}}
    - myForm.input.$valid = {{myForm.input.$valid}}
    - myForm.input.$error = {{myForm.input.$error}}
    - myForm.$valid = {{myForm.$valid}}
    - myForm.$error.required = {{!!myForm.$error.required}}
    -
    -
    - - var value = element(by.binding('example.value | date: "HH:mm:ss"')); - var valid = element(by.binding('myForm.input.$valid')); - - // currently protractor/webdriver does not support - // sending keys to all known HTML5 input controls - // for various browsers (https://github.com/angular/protractor/issues/562). - function setInput(val) { - // set the value of the element and force validation. - var scr = "var ipt = document.getElementById('exampleInput'); " + - "ipt.value = '" + val + "';" + - "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; - browser.executeScript(scr); - } - - it('should initialize to model', function() { - expect(value.getText()).toContain('14:57:00'); - expect(valid.getText()).toContain('myForm.input.$valid = true'); - }); - - it('should be invalid if empty', function() { - setInput(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - - it('should be invalid if over max', function() { - setInput('23:59:00'); - expect(value.getText()).toContain(''); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - -
    - */ - 'time': createDateInputType('time', TIME_REGEXP, - createDateParser(TIME_REGEXP, ['HH', 'mm', 'ss', 'sss']), - 'HH:mm:ss.sss'), - - /** - * @ngdoc input - * @name input[week] - * - * @description - * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support - * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 - * week format (yyyy-W##), for example: `2013-W02`. - * - * The model must always be a Date object, otherwise AngularJS will throw an error. - * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. - * - * The value of the resulting Date object will be set to Thursday at 00:00:00 of the requested week, - * due to ISO-8601 week numbering standards. Information on ISO's system for numbering the weeks of the - * year can be found at: https://en.wikipedia.org/wiki/ISO_8601#Week_dates - * - * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. - * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this - * attribute (e.g. `min="{{minWeek | date:'yyyy-Www'}}"`). Note that `min` will also add - * native HTML5 constraint validation. - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. - * This must be a valid ISO week format (yyyy-W##). You can also use interpolation inside this - * attribute (e.g. `max="{{maxWeek | date:'yyyy-Www'}}"`). Note that `max` will also add - * native HTML5 constraint validation. - * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string - * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. - * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string - * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
    - -
    - - Required! - - Not a valid date! -
    - value = {{example.value | date: "yyyy-Www"}}
    - myForm.input.$valid = {{myForm.input.$valid}}
    - myForm.input.$error = {{myForm.input.$error}}
    - myForm.$valid = {{myForm.$valid}}
    - myForm.$error.required = {{!!myForm.$error.required}}
    -
    -
    - - var value = element(by.binding('example.value | date: "yyyy-Www"')); - var valid = element(by.binding('myForm.input.$valid')); - - // currently protractor/webdriver does not support - // sending keys to all known HTML5 input controls - // for various browsers (https://github.com/angular/protractor/issues/562). - function setInput(val) { - // set the value of the element and force validation. - var scr = "var ipt = document.getElementById('exampleInput'); " + - "ipt.value = '" + val + "';" + - "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; - browser.executeScript(scr); - } - - it('should initialize to model', function() { - expect(value.getText()).toContain('2013-W01'); - expect(valid.getText()).toContain('myForm.input.$valid = true'); - }); - - it('should be invalid if empty', function() { - setInput(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - - it('should be invalid if over max', function() { - setInput('2015-W01'); - expect(value.getText()).toContain(''); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - -
    - */ - 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'), - - /** - * @ngdoc input - * @name input[month] - * - * @description - * Input with month validation and transformation. In browsers that do not yet support - * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601 - * month format (yyyy-MM), for example: `2009-01`. - * - * The model must always be a Date object, otherwise AngularJS will throw an error. - * Invalid `Date` objects (dates whose `getTime()` is `NaN`) will be rendered as an empty string. - * If the model is not set to the first of the month, the next view to model update will set it - * to the first of the month. - * - * The timezone to be used to read/write the `Date` instance in the model can be defined using - * {@link ng.directive:ngModelOptions ngModelOptions}. By default, this is the timezone of the browser. - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. - * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this - * attribute (e.g. `min="{{minMonth | date:'yyyy-MM'}}"`). Note that `min` will also add - * native HTML5 constraint validation. - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. - * This must be a valid ISO month format (yyyy-MM). You can also use interpolation inside this - * attribute (e.g. `max="{{maxMonth | date:'yyyy-MM'}}"`). Note that `max` will also add - * native HTML5 constraint validation. - * @param {(date|string)=} ngMin Sets the `min` validation constraint to the Date / ISO week string - * the `ngMin` expression evaluates to. Note that it does not set the `min` attribute. - * @param {(date|string)=} ngMax Sets the `max` validation constraint to the Date / ISO week string - * the `ngMax` expression evaluates to. Note that it does not set the `max` attribute. - - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
    - - -
    - - Required! - - Not a valid month! -
    - value = {{example.value | date: "yyyy-MM"}}
    - myForm.input.$valid = {{myForm.input.$valid}}
    - myForm.input.$error = {{myForm.input.$error}}
    - myForm.$valid = {{myForm.$valid}}
    - myForm.$error.required = {{!!myForm.$error.required}}
    -
    -
    - - var value = element(by.binding('example.value | date: "yyyy-MM"')); - var valid = element(by.binding('myForm.input.$valid')); - - // currently protractor/webdriver does not support - // sending keys to all known HTML5 input controls - // for various browsers (https://github.com/angular/protractor/issues/562). - function setInput(val) { - // set the value of the element and force validation. - var scr = "var ipt = document.getElementById('exampleInput'); " + - "ipt.value = '" + val + "';" + - "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });"; - browser.executeScript(scr); - } - - it('should initialize to model', function() { - expect(value.getText()).toContain('2013-10'); - expect(valid.getText()).toContain('myForm.input.$valid = true'); - }); - - it('should be invalid if empty', function() { - setInput(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - - it('should be invalid if over max', function() { - setInput('2015-01'); - expect(value.getText()).toContain(''); - expect(valid.getText()).toContain('myForm.input.$valid = false'); - }); - -
    - */ - 'month': createDateInputType('month', MONTH_REGEXP, - createDateParser(MONTH_REGEXP, ['yyyy', 'MM']), - 'yyyy-MM'), - - /** - * @ngdoc input - * @name input[number] - * - * @description - * Text input with number validation and transformation. Sets the `number` validation - * error if not a valid number. - * - *
    - * The model must always be of type `number` otherwise AngularJS will throw an error. - * Be aware that a string containing a number is not enough. See the {@link ngModel:numfmt} - * error docs for more information and an example of how to convert your model if necessary. - *
    - * - * - * - * @knownIssue - * - * ### HTML5 constraint validation and `allowInvalid` - * - * In browsers that follow the - * [HTML5 specification](https://html.spec.whatwg.org/multipage/forms.html#number-state-%28type=number%29), - * `input[number]` does not work as expected with {@link ngModelOptions `ngModelOptions.allowInvalid`}. - * If a non-number is entered in the input, the browser will report the value as an empty string, - * which means the view / model values in `ngModel` and subsequently the scope value - * will also be an empty string. - * - * @knownIssue - * - * ### Large numbers and `step` validation - * - * The `step` validation will not work correctly for very large numbers (e.g. 9999999999) due to - * Javascript's arithmetic limitations. If you need to handle large numbers, purpose-built - * libraries (e.g. https://github.com/MikeMcl/big.js/), can be included into AngularJS by - * {@link guide/forms#modifying-built-in-validators overwriting the validators} - * for `number` and / or `step`, or by {@link guide/forms#custom-validation applying custom validators} - * to an `input[text]` element. The source for `input[number]` type can be used as a starting - * point for both implementations. - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. - * Can be interpolated. - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. - * Can be interpolated. - * @param {string=} ngMin Like `min`, sets the `min` validation error key if the value entered is less than `ngMin`, - * but does not trigger HTML5 native validation. Takes an expression. - * @param {string=} ngMax Like `max`, sets the `max` validation error key if the value entered is greater than `ngMax`, - * but does not trigger HTML5 native validation. Takes an expression. - * @param {string=} step Sets the `step` validation error key if the value entered does not fit the `step` constraint. - * Can be interpolated. - * @param {string=} ngStep Like `step`, sets the `step` validation error key if the value entered does not fit the `ngStep` constraint, - * but does not trigger HTML5 native validation. Takes an expression. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of - * any length. - * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string - * that contains the regular expression body that will be converted to a regular expression - * as in the ngPattern directive. - * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} - * does not match a RegExp found by evaluating the AngularJS expression given in the attribute value. - * If the expression evaluates to a RegExp object, then this is used directly. - * If the expression evaluates to a string, then it will be converted to a RegExp - * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to - * `new RegExp('^abc$')`.
    - * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to - * start at the index of the last search's match, thus not taking the whole input value into - * account. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
    - -
    - - Required! - - Not valid number! -
    - value = {{example.value}}
    - myForm.input.$valid = {{myForm.input.$valid}}
    - myForm.input.$error = {{myForm.input.$error}}
    - myForm.$valid = {{myForm.$valid}}
    - myForm.$error.required = {{!!myForm.$error.required}}
    -
    -
    - - var value = element(by.binding('example.value')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('example.value')); - - it('should initialize to model', function() { - expect(value.getText()).toContain('12'); - expect(valid.getText()).toContain('true'); - }); - - it('should be invalid if empty', function() { - input.clear(); - input.sendKeys(''); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('false'); - }); - - it('should be invalid if over max', function() { - input.clear(); - input.sendKeys('123'); - expect(value.getText()).toEqual('value ='); - expect(valid.getText()).toContain('false'); - }); - -
    - */ - 'number': numberInputType, - - - /** - * @ngdoc input - * @name input[url] - * - * @description - * Text input with URL validation. Sets the `url` validation error key if the content is not a - * valid URL. - * - *
    - * **Note:** `input[url]` uses a regex to validate urls that is derived from the regex - * used in Chromium. If you need stricter validation, you can use `ng-pattern` or modify - * the built-in validators (see the {@link guide/forms Forms guide}) - *
    - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of - * any length. - * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string - * that contains the regular expression body that will be converted to a regular expression - * as in the ngPattern directive. - * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} - * does not match a RegExp found by evaluating the AngularJS expression given in the attribute value. - * If the expression evaluates to a RegExp object, then this is used directly. - * If the expression evaluates to a string, then it will be converted to a RegExp - * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to - * `new RegExp('^abc$')`.
    - * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to - * start at the index of the last search's match, thus not taking the whole input value into - * account. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
    -
    - - var text = element(by.binding('url.text')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('url.text')); - - it('should initialize to model', function() { - expect(text.getText()).toContain('http://google.com'); - expect(valid.getText()).toContain('true'); - }); - - it('should be invalid if empty', function() { - input.clear(); - input.sendKeys(''); - - expect(text.getText()).toEqual('text ='); - expect(valid.getText()).toContain('false'); - }); - - it('should be invalid if not url', function() { - input.clear(); - input.sendKeys('box'); - - expect(valid.getText()).toContain('false'); - }); - -
    - */ - 'url': urlInputType, - - - /** - * @ngdoc input - * @name input[email] - * - * @description - * Text input with email validation. Sets the `email` validation error key if not a valid email - * address. - * - *
    - * **Note:** `input[email]` uses a regex to validate email addresses that is derived from the regex - * used in Chromium, which may not fulfill your app's requirements. - * If you need stricter (e.g. requiring a top-level domain), or more relaxed validation - * (e.g. allowing IPv6 address literals) you can use `ng-pattern` or - * modify the built-in validators (see the {@link guide/forms Forms guide}). - *
    - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of - * any length. - * @param {string=} pattern Similar to `ngPattern` except that the attribute value is the actual string - * that contains the regular expression body that will be converted to a regular expression - * as in the ngPattern directive. - * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} - * does not match a RegExp found by evaluating the AngularJS expression given in the attribute value. - * If the expression evaluates to a RegExp object, then this is used directly. - * If the expression evaluates to a string, then it will be converted to a RegExp - * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to - * `new RegExp('^abc$')`.
    - * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to - * start at the index of the last search's match, thus not taking the whole input value into - * account. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
    - -
    - - Required! - - Not valid email! -
    - text = {{email.text}}
    - myForm.input.$valid = {{myForm.input.$valid}}
    - myForm.input.$error = {{myForm.input.$error}}
    - myForm.$valid = {{myForm.$valid}}
    - myForm.$error.required = {{!!myForm.$error.required}}
    - myForm.$error.email = {{!!myForm.$error.email}}
    -
    -
    - - var text = element(by.binding('email.text')); - var valid = element(by.binding('myForm.input.$valid')); - var input = element(by.model('email.text')); - - it('should initialize to model', function() { - expect(text.getText()).toContain('me@example.com'); - expect(valid.getText()).toContain('true'); - }); - - it('should be invalid if empty', function() { - input.clear(); - input.sendKeys(''); - expect(text.getText()).toEqual('text ='); - expect(valid.getText()).toContain('false'); - }); - - it('should be invalid if not email', function() { - input.clear(); - input.sendKeys('xxx'); - - expect(valid.getText()).toContain('false'); - }); - -
    - */ - 'email': emailInputType, - - - /** - * @ngdoc input - * @name input[radio] - * - * @description - * HTML radio button. - * - * **Note:**
    - * All inputs controlled by {@link ngModel ngModel} (including those of type `radio`) will use the - * value of their `name` attribute to determine the property under which their - * {@link ngModel.NgModelController NgModelController} will be published on the parent - * {@link form.FormController FormController}. Thus, if you use the same `name` for multiple - * inputs of a form (e.g. a group of radio inputs), only _one_ `NgModelController` will be - * published on the parent `FormController` under that name. The rest of the controllers will - * continue to work as expected, but you won't be able to access them as properties on the parent - * `FormController`. - * - *
    - *

    - * In plain HTML forms, the `name` attribute is used to identify groups of radio inputs, so - * that the browser can manage their state (checked/unchecked) based on the state of other - * inputs in the same group. - *

    - *

    - * In AngularJS forms, this is not necessary. The input's state will be updated based on the - * value of the underlying model data. - *

    - *
    - * - *
    - * If you omit the `name` attribute on a radio input, `ngModel` will automatically assign it a - * unique name. - *
    - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string} value The value to which the `ngModel` expression should be set when selected. - * Note that `value` only supports `string` values, i.e. the scope model needs to be a string, - * too. Use `ngValue` if you need complex models (`number`, `object`, ...). - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * @param {string} ngValue AngularJS expression to which `ngModel` will be be set when the radio - * is selected. Should be used instead of the `value` attribute if you need - * a non-string `ngModel` (`boolean`, `array`, ...). - * - * @example - - - -
    -
    -
    -
    - color = {{color.name | json}}
    -
    - Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`. -
    - - it('should change state', function() { - var inputs = element.all(by.model('color.name')); - var color = element(by.binding('color.name')); - - expect(color.getText()).toContain('blue'); - - inputs.get(0).click(); - expect(color.getText()).toContain('red'); - - inputs.get(1).click(); - expect(color.getText()).toContain('green'); - }); - -
    - */ - 'radio': radioInputType, - - /** - * @ngdoc input - * @name input[range] - * - * @description - * Native range input with validation and transformation. - * - * The model for the range input must always be a `Number`. - * - * IE9 and other browsers that do not support the `range` type fall back - * to a text input without any default values for `min`, `max` and `step`. Model binding, - * validation and number parsing are nevertheless supported. - * - * Browsers that support range (latest Chrome, Safari, Firefox, Edge) treat `input[range]` - * in a way that never allows the input to hold an invalid value. That means: - * - any non-numerical value is set to `(max + min) / 2`. - * - any numerical value that is less than the current min val, or greater than the current max val - * is set to the min / max val respectively. - * - additionally, the current `step` is respected, so the nearest value that satisfies a step - * is used. - * - * See the [HTML Spec on input[type=range]](https://www.w3.org/TR/html5/forms.html#range-state-(type=range)) - * for more info. - * - * This has the following consequences for AngularJS: - * - * Since the element value should always reflect the current model value, a range input - * will set the bound ngModel expression to the value that the browser has set for the - * input element. For example, in the following input ``, - * if the application sets `model.value = null`, the browser will set the input to `'50'`. - * AngularJS will then set the model to `50`, to prevent input and model value being out of sync. - * - * That means the model for range will immediately be set to `50` after `ngModel` has been - * initialized. It also means a range input can never have the required error. - * - * This does not only affect changes to the model value, but also to the values of the `min`, - * `max`, and `step` attributes. When these change in a way that will cause the browser to modify - * the input value, AngularJS will also update the model value. - * - * Automatic value adjustment also means that a range input element can never have the `required`, - * `min`, or `max` errors. - * - * However, `step` is currently only fully implemented by Firefox. Other browsers have problems - * when the step value changes dynamically - they do not adjust the element value correctly, but - * instead may set the `stepMismatch` error. If that's the case, the AngularJS will set the `step` - * error on the input, and set the model to `undefined`. - * - * Note that `input[range]` is not compatible with`ngMax`, `ngMin`, and `ngStep`, because they do - * not set the `min` and `max` attributes, which means that the browser won't automatically adjust - * the input value based on their values, and will always assume min = 0, max = 100, and step = 1. - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation to ensure that the value entered is greater - * than `min`. Can be interpolated. - * @param {string=} max Sets the `max` validation to ensure that the value entered is less than `max`. - * Can be interpolated. - * @param {string=} step Sets the `step` validation to ensure that the value entered matches the `step` - * Can be interpolated. - * @param {expression=} ngChange AngularJS expression to be executed when the ngModel value changes due - * to user interaction with the input element. - * @param {expression=} ngChecked If the expression is truthy, then the `checked` attribute will be set on the - * element. **Note** : `ngChecked` should not be used alongside `ngModel`. - * Checkout {@link ng.directive:ngChecked ngChecked} for usage. - * - * @example - - - -
    - - Model as range: -
    - Model as number:
    - Min:
    - Max:
    - value = {{value}}
    - myForm.range.$valid = {{myForm.range.$valid}}
    - myForm.range.$error = {{myForm.range.$error}} -
    -
    -
    - - * ## Range Input with ngMin & ngMax attributes - - * @example - - - -
    - Model as range: -
    - Model as number:
    - Min:
    - Max:
    - value = {{value}}
    - myForm.range.$valid = {{myForm.range.$valid}}
    - myForm.range.$error = {{myForm.range.$error}} -
    -
    -
    - - */ - 'range': rangeInputType, - - /** - * @ngdoc input - * @name input[checkbox] - * - * @description - * HTML checkbox. - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {expression=} ngTrueValue The value to which the expression should be set when selected. - * @param {expression=} ngFalseValue The value to which the expression should be set when not selected. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
    -
    -
    - value1 = {{checkboxModel.value1}}
    - value2 = {{checkboxModel.value2}}
    -
    -
    - - it('should change state', function() { - var value1 = element(by.binding('checkboxModel.value1')); - var value2 = element(by.binding('checkboxModel.value2')); - - expect(value1.getText()).toContain('true'); - expect(value2.getText()).toContain('YES'); - - element(by.model('checkboxModel.value1')).click(); - element(by.model('checkboxModel.value2')).click(); - - expect(value1.getText()).toContain('false'); - expect(value2.getText()).toContain('NO'); - }); - -
    - */ - 'checkbox': checkboxInputType, - - 'hidden': noop, - 'button': noop, - 'submit': noop, - 'reset': noop, - 'file': noop -}; - -function stringBasedInputType(ctrl) { - ctrl.$formatters.push(function(value) { - return ctrl.$isEmpty(value) ? value : value.toString(); - }); -} - -function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - stringBasedInputType(ctrl); -} - -function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) { - var type = lowercase(element[0].type); - - // In composition mode, users are still inputting intermediate text buffer, - // hold the listener until composition is done. - // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent - if (!$sniffer.android) { - var composing = false; - - element.on('compositionstart', function() { - composing = true; - }); - - // Support: IE9+ - element.on('compositionupdate', function(ev) { - // End composition when ev.data is empty string on 'compositionupdate' event. - // When the input de-focusses (e.g. by clicking away), IE triggers 'compositionupdate' - // instead of 'compositionend'. - if (isUndefined(ev.data) || ev.data === '') { - composing = false; - } - }); - - element.on('compositionend', function() { - composing = false; - listener(); - }); - } - - var timeout; - - var listener = function(ev) { - if (timeout) { - $browser.defer.cancel(timeout); - timeout = null; - } - if (composing) return; - var value = element.val(), - event = ev && ev.type; - - // By default we will trim the value - // If the attribute ng-trim exists we will avoid trimming - // If input type is 'password', the value is never trimmed - if (type !== 'password' && (!attr.ngTrim || attr.ngTrim !== 'false')) { - value = trim(value); - } - - // If a control is suffering from bad input (due to native validators), browsers discard its - // value, so it may be necessary to revalidate (by calling $setViewValue again) even if the - // control's value is the same empty value twice in a row. - if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) { - ctrl.$setViewValue(value, event); - } - }; - - // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the - // input event on backspace, delete or cut - if ($sniffer.hasEvent('input')) { - element.on('input', listener); - } else { - var deferListener = function(ev, input, origValue) { - if (!timeout) { - timeout = $browser.defer(function() { - timeout = null; - if (!input || input.value !== origValue) { - listener(ev); - } - }); - } - }; - - element.on('keydown', /** @this */ function(event) { - var key = event.keyCode; - - // ignore - // command modifiers arrows - if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; - - deferListener(event, this, this.value); - }); - - // if user modifies input value using context menu in IE, we need "paste", "cut" and "drop" events to catch it - if ($sniffer.hasEvent('paste')) { - element.on('paste cut drop', deferListener); - } - } - - // if user paste into input using mouse on older browser - // or form autocomplete on newer browser, we need "change" event to catch it - element.on('change', listener); - - // Some native input types (date-family) have the ability to change validity without - // firing any input/change events. - // For these event types, when native validators are present and the browser supports the type, - // check for validity changes on various DOM events. - if (PARTIAL_VALIDATION_TYPES[type] && ctrl.$$hasNativeValidators && type === attr.type) { - element.on(PARTIAL_VALIDATION_EVENTS, /** @this */ function(ev) { - if (!timeout) { - var validity = this[VALIDITY_STATE_PROPERTY]; - var origBadInput = validity.badInput; - var origTypeMismatch = validity.typeMismatch; - timeout = $browser.defer(function() { - timeout = null; - if (validity.badInput !== origBadInput || validity.typeMismatch !== origTypeMismatch) { - listener(ev); - } - }); - } - }); - } - - ctrl.$render = function() { - // Workaround for Firefox validation #12102. - var value = ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue; - if (element.val() !== value) { - element.val(value); - } - }; -} - -function weekParser(isoWeek, existingDate) { - if (isDate(isoWeek)) { - return isoWeek; - } - - if (isString(isoWeek)) { - WEEK_REGEXP.lastIndex = 0; - var parts = WEEK_REGEXP.exec(isoWeek); - if (parts) { - var year = +parts[1], - week = +parts[2], - hours = 0, - minutes = 0, - seconds = 0, - milliseconds = 0, - firstThurs = getFirstThursdayOfYear(year), - addDays = (week - 1) * 7; - - if (existingDate) { - hours = existingDate.getHours(); - minutes = existingDate.getMinutes(); - seconds = existingDate.getSeconds(); - milliseconds = existingDate.getMilliseconds(); - } - - return new Date(year, 0, firstThurs.getDate() + addDays, hours, minutes, seconds, milliseconds); - } - } - - return NaN; -} - -function createDateParser(regexp, mapping) { - return function(iso, previousDate) { - var parts, map; - - if (isDate(iso)) { - return iso; - } - - if (isString(iso)) { - // When a date is JSON'ified to wraps itself inside of an extra - // set of double quotes. This makes the date parsing code unable - // to match the date string and parse it as a date. - if (iso.charAt(0) === '"' && iso.charAt(iso.length - 1) === '"') { - iso = iso.substring(1, iso.length - 1); - } - if (ISO_DATE_REGEXP.test(iso)) { - return new Date(iso); - } - regexp.lastIndex = 0; - parts = regexp.exec(iso); - - if (parts) { - parts.shift(); - if (previousDate) { - map = { - yyyy: previousDate.getFullYear(), - MM: previousDate.getMonth() + 1, - dd: previousDate.getDate(), - HH: previousDate.getHours(), - mm: previousDate.getMinutes(), - ss: previousDate.getSeconds(), - sss: previousDate.getMilliseconds() / 1000 - }; - } else { - map = { yyyy: 1970, MM: 1, dd: 1, HH: 0, mm: 0, ss: 0, sss: 0 }; - } - - forEach(parts, function(part, index) { - if (index < mapping.length) { - map[mapping[index]] = +part; - } - }); - - var date = new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0); - if (map.yyyy < 100) { - // In the constructor, 2-digit years map to 1900-1999. - // Use `setFullYear()` to set the correct year. - date.setFullYear(map.yyyy); - } - - return date; - } - } - - return NaN; - }; -} - -function createDateInputType(type, regexp, parseDate, format) { - return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { - badInputChecker(scope, element, attr, ctrl, type); - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - - var isTimeType = type === 'time' || type === 'datetimelocal'; - var previousDate; - var previousTimezone; - - ctrl.$parsers.push(function(value) { - if (ctrl.$isEmpty(value)) return null; - - if (regexp.test(value)) { - // Note: We cannot read ctrl.$modelValue, as there might be a different - // parser/formatter in the processing chain so that the model - // contains some different data format! - return parseDateAndConvertTimeZoneToLocal(value, previousDate); - } - ctrl.$$parserName = type; - return undefined; - }); - - ctrl.$formatters.push(function(value) { - if (value && !isDate(value)) { - throw ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value); - } - if (isValidDate(value)) { - previousDate = value; - var timezone = ctrl.$options.getOption('timezone'); - - if (timezone) { - previousTimezone = timezone; - previousDate = convertTimezoneToLocal(previousDate, timezone, true); - } - - return formatter(value, timezone); - } else { - previousDate = null; - previousTimezone = null; - return ''; - } - }); - - if (isDefined(attr.min) || attr.ngMin) { - var minVal = attr.min || $parse(attr.ngMin)(scope); - var parsedMinVal = parseObservedDateValue(minVal); - - ctrl.$validators.min = function(value) { - return !isValidDate(value) || isUndefined(parsedMinVal) || parseDate(value) >= parsedMinVal; - }; - attr.$observe('min', function(val) { - if (val !== minVal) { - parsedMinVal = parseObservedDateValue(val); - minVal = val; - ctrl.$validate(); - } - }); - } - - if (isDefined(attr.max) || attr.ngMax) { - var maxVal = attr.max || $parse(attr.ngMax)(scope); - var parsedMaxVal = parseObservedDateValue(maxVal); - - ctrl.$validators.max = function(value) { - return !isValidDate(value) || isUndefined(parsedMaxVal) || parseDate(value) <= parsedMaxVal; - }; - attr.$observe('max', function(val) { - if (val !== maxVal) { - parsedMaxVal = parseObservedDateValue(val); - maxVal = val; - ctrl.$validate(); - } - }); - } - - function isValidDate(value) { - // Invalid Date: getTime() returns NaN - return value && !(value.getTime && value.getTime() !== value.getTime()); - } - - function parseObservedDateValue(val) { - return isDefined(val) && !isDate(val) ? parseDateAndConvertTimeZoneToLocal(val) || undefined : val; - } - - function parseDateAndConvertTimeZoneToLocal(value, previousDate) { - var timezone = ctrl.$options.getOption('timezone'); - - if (previousTimezone && previousTimezone !== timezone) { - // If the timezone has changed, adjust the previousDate to the default timezone - // so that the new date is converted with the correct timezone offset - previousDate = addDateMinutes(previousDate, timezoneToOffset(previousTimezone)); - } - - var parsedDate = parseDate(value, previousDate); - - if (!isNaN(parsedDate) && timezone) { - parsedDate = convertTimezoneToLocal(parsedDate, timezone); - } - return parsedDate; - } - - function formatter(value, timezone) { - var targetFormat = format; - - if (isTimeType && isString(ctrl.$options.getOption('timeSecondsFormat'))) { - targetFormat = format - .replace('ss.sss', ctrl.$options.getOption('timeSecondsFormat')) - .replace(/:$/, ''); - } - - var formatted = $filter('date')(value, targetFormat, timezone); - - if (isTimeType && ctrl.$options.getOption('timeStripZeroSeconds')) { - formatted = formatted.replace(/(?::00)?(?:\.000)?$/, ''); - } - - return formatted; - } - }; -} - -function badInputChecker(scope, element, attr, ctrl, parserName) { - var node = element[0]; - var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity); - if (nativeValidation) { - ctrl.$parsers.push(function(value) { - var validity = element.prop(VALIDITY_STATE_PROPERTY) || {}; - if (validity.badInput || validity.typeMismatch) { - ctrl.$$parserName = parserName; - return undefined; - } - - return value; - }); - } -} - -function numberFormatterParser(ctrl) { - ctrl.$parsers.push(function(value) { - if (ctrl.$isEmpty(value)) return null; - if (NUMBER_REGEXP.test(value)) return parseFloat(value); - - ctrl.$$parserName = 'number'; - return undefined; - }); - - ctrl.$formatters.push(function(value) { - if (!ctrl.$isEmpty(value)) { - if (!isNumber(value)) { - throw ngModelMinErr('numfmt', 'Expected `{0}` to be a number', value); - } - value = value.toString(); - } - return value; - }); -} - -function parseNumberAttrVal(val) { - if (isDefined(val) && !isNumber(val)) { - val = parseFloat(val); - } - return !isNumberNaN(val) ? val : undefined; -} - -function isNumberInteger(num) { - // See http://stackoverflow.com/questions/14636536/how-to-check-if-a-variable-is-an-integer-in-javascript#14794066 - // (minus the assumption that `num` is a number) - - // eslint-disable-next-line no-bitwise - return (num | 0) === num; -} - -function countDecimals(num) { - var numString = num.toString(); - var decimalSymbolIndex = numString.indexOf('.'); - - if (decimalSymbolIndex === -1) { - if (-1 < num && num < 1) { - // It may be in the exponential notation format (`1e-X`) - var match = /e-(\d+)$/.exec(numString); - - if (match) { - return Number(match[1]); - } - } - - return 0; - } - - return numString.length - decimalSymbolIndex - 1; -} - -function isValidForStep(viewValue, stepBase, step) { - // At this point `stepBase` and `step` are expected to be non-NaN values - // and `viewValue` is expected to be a valid stringified number. - var value = Number(viewValue); - - var isNonIntegerValue = !isNumberInteger(value); - var isNonIntegerStepBase = !isNumberInteger(stepBase); - var isNonIntegerStep = !isNumberInteger(step); - - // Due to limitations in Floating Point Arithmetic (e.g. `0.3 - 0.2 !== 0.1` or - // `0.5 % 0.1 !== 0`), we need to convert all numbers to integers. - if (isNonIntegerValue || isNonIntegerStepBase || isNonIntegerStep) { - var valueDecimals = isNonIntegerValue ? countDecimals(value) : 0; - var stepBaseDecimals = isNonIntegerStepBase ? countDecimals(stepBase) : 0; - var stepDecimals = isNonIntegerStep ? countDecimals(step) : 0; - - var decimalCount = Math.max(valueDecimals, stepBaseDecimals, stepDecimals); - var multiplier = Math.pow(10, decimalCount); - - value = value * multiplier; - stepBase = stepBase * multiplier; - step = step * multiplier; - - if (isNonIntegerValue) value = Math.round(value); - if (isNonIntegerStepBase) stepBase = Math.round(stepBase); - if (isNonIntegerStep) step = Math.round(step); - } - - return (value - stepBase) % step === 0; -} - -function numberInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { - badInputChecker(scope, element, attr, ctrl, 'number'); - numberFormatterParser(ctrl); - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - - var parsedMinVal; - - if (isDefined(attr.min) || attr.ngMin) { - var minVal = attr.min || $parse(attr.ngMin)(scope); - parsedMinVal = parseNumberAttrVal(minVal); - - ctrl.$validators.min = function(modelValue, viewValue) { - return ctrl.$isEmpty(viewValue) || isUndefined(parsedMinVal) || viewValue >= parsedMinVal; - }; - - attr.$observe('min', function(val) { - if (val !== minVal) { - parsedMinVal = parseNumberAttrVal(val); - minVal = val; - // TODO(matsko): implement validateLater to reduce number of validations - ctrl.$validate(); - } - }); - } - - if (isDefined(attr.max) || attr.ngMax) { - var maxVal = attr.max || $parse(attr.ngMax)(scope); - var parsedMaxVal = parseNumberAttrVal(maxVal); - - ctrl.$validators.max = function(modelValue, viewValue) { - return ctrl.$isEmpty(viewValue) || isUndefined(parsedMaxVal) || viewValue <= parsedMaxVal; - }; - - attr.$observe('max', function(val) { - if (val !== maxVal) { - parsedMaxVal = parseNumberAttrVal(val); - maxVal = val; - // TODO(matsko): implement validateLater to reduce number of validations - ctrl.$validate(); - } - }); - } - - if (isDefined(attr.step) || attr.ngStep) { - var stepVal = attr.step || $parse(attr.ngStep)(scope); - var parsedStepVal = parseNumberAttrVal(stepVal); - - ctrl.$validators.step = function(modelValue, viewValue) { - return ctrl.$isEmpty(viewValue) || isUndefined(parsedStepVal) || - isValidForStep(viewValue, parsedMinVal || 0, parsedStepVal); - }; - - attr.$observe('step', function(val) { - // TODO(matsko): implement validateLater to reduce number of validations - if (val !== stepVal) { - parsedStepVal = parseNumberAttrVal(val); - stepVal = val; - ctrl.$validate(); - } - - }); - - } -} - -function rangeInputType(scope, element, attr, ctrl, $sniffer, $browser) { - badInputChecker(scope, element, attr, ctrl, 'range'); - numberFormatterParser(ctrl); - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - - var supportsRange = ctrl.$$hasNativeValidators && element[0].type === 'range', - minVal = supportsRange ? 0 : undefined, - maxVal = supportsRange ? 100 : undefined, - stepVal = supportsRange ? 1 : undefined, - validity = element[0].validity, - hasMinAttr = isDefined(attr.min), - hasMaxAttr = isDefined(attr.max), - hasStepAttr = isDefined(attr.step); - - var originalRender = ctrl.$render; - - ctrl.$render = supportsRange && isDefined(validity.rangeUnderflow) && isDefined(validity.rangeOverflow) ? - //Browsers that implement range will set these values automatically, but reading the adjusted values after - //$render would cause the min / max validators to be applied with the wrong value - function rangeRender() { - originalRender(); - ctrl.$setViewValue(element.val()); - } : - originalRender; - - if (hasMinAttr) { - minVal = parseNumberAttrVal(attr.min); - - ctrl.$validators.min = supportsRange ? - // Since all browsers set the input to a valid value, we don't need to check validity - function noopMinValidator() { return true; } : - // non-support browsers validate the min val - function minValidator(modelValue, viewValue) { - return ctrl.$isEmpty(viewValue) || isUndefined(minVal) || viewValue >= minVal; - }; - - setInitialValueAndObserver('min', minChange); - } - - if (hasMaxAttr) { - maxVal = parseNumberAttrVal(attr.max); - - ctrl.$validators.max = supportsRange ? - // Since all browsers set the input to a valid value, we don't need to check validity - function noopMaxValidator() { return true; } : - // non-support browsers validate the max val - function maxValidator(modelValue, viewValue) { - return ctrl.$isEmpty(viewValue) || isUndefined(maxVal) || viewValue <= maxVal; - }; - - setInitialValueAndObserver('max', maxChange); - } - - if (hasStepAttr) { - stepVal = parseNumberAttrVal(attr.step); - - ctrl.$validators.step = supportsRange ? - function nativeStepValidator() { - // Currently, only FF implements the spec on step change correctly (i.e. adjusting the - // input element value to a valid value). It's possible that other browsers set the stepMismatch - // validity error instead, so we can at least report an error in that case. - return !validity.stepMismatch; - } : - // ngStep doesn't set the setp attr, so the browser doesn't adjust the input value as setting step would - function stepValidator(modelValue, viewValue) { - return ctrl.$isEmpty(viewValue) || isUndefined(stepVal) || - isValidForStep(viewValue, minVal || 0, stepVal); - }; - - setInitialValueAndObserver('step', stepChange); - } - - function setInitialValueAndObserver(htmlAttrName, changeFn) { - // interpolated attributes set the attribute value only after a digest, but we need the - // attribute value when the input is first rendered, so that the browser can adjust the - // input value based on the min/max value - element.attr(htmlAttrName, attr[htmlAttrName]); - var oldVal = attr[htmlAttrName]; - attr.$observe(htmlAttrName, function wrappedObserver(val) { - if (val !== oldVal) { - oldVal = val; - changeFn(val); - } - }); - } - - function minChange(val) { - minVal = parseNumberAttrVal(val); - // ignore changes before model is initialized - if (isNumberNaN(ctrl.$modelValue)) { - return; - } - - if (supportsRange) { - var elVal = element.val(); - // IE11 doesn't set the el val correctly if the minVal is greater than the element value - if (minVal > elVal) { - elVal = minVal; - element.val(elVal); - } - ctrl.$setViewValue(elVal); - } else { - // TODO(matsko): implement validateLater to reduce number of validations - ctrl.$validate(); - } - } - - function maxChange(val) { - maxVal = parseNumberAttrVal(val); - // ignore changes before model is initialized - if (isNumberNaN(ctrl.$modelValue)) { - return; - } - - if (supportsRange) { - var elVal = element.val(); - // IE11 doesn't set the el val correctly if the maxVal is less than the element value - if (maxVal < elVal) { - element.val(maxVal); - // IE11 and Chrome don't set the value to the minVal when max < min - elVal = maxVal < minVal ? minVal : maxVal; - } - ctrl.$setViewValue(elVal); - } else { - // TODO(matsko): implement validateLater to reduce number of validations - ctrl.$validate(); - } - } - - function stepChange(val) { - stepVal = parseNumberAttrVal(val); - // ignore changes before model is initialized - if (isNumberNaN(ctrl.$modelValue)) { - return; - } - - // Some browsers don't adjust the input value correctly, but set the stepMismatch error - if (!supportsRange) { - // TODO(matsko): implement validateLater to reduce number of validations - ctrl.$validate(); - } else if (ctrl.$viewValue !== element.val()) { - ctrl.$setViewValue(element.val()); - } - } -} - -function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { - // Note: no badInputChecker here by purpose as `url` is only a validation - // in browsers, i.e. we can always read out input.value even if it is not valid! - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - stringBasedInputType(ctrl); - - ctrl.$validators.url = function(modelValue, viewValue) { - var value = modelValue || viewValue; - return ctrl.$isEmpty(value) || URL_REGEXP.test(value); - }; -} - -function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { - // Note: no badInputChecker here by purpose as `url` is only a validation - // in browsers, i.e. we can always read out input.value even if it is not valid! - baseInputType(scope, element, attr, ctrl, $sniffer, $browser); - stringBasedInputType(ctrl); - - ctrl.$validators.email = function(modelValue, viewValue) { - var value = modelValue || viewValue; - return ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value); - }; -} - -function radioInputType(scope, element, attr, ctrl) { - var doTrim = !attr.ngTrim || trim(attr.ngTrim) !== 'false'; - // make the name unique, if not defined - if (isUndefined(attr.name)) { - element.attr('name', nextUid()); - } - - var listener = function(ev) { - var value; - if (element[0].checked) { - value = attr.value; - if (doTrim) { - value = trim(value); - } - ctrl.$setViewValue(value, ev && ev.type); - } - }; - - element.on('change', listener); - - ctrl.$render = function() { - var value = attr.value; - if (doTrim) { - value = trim(value); - } - element[0].checked = (value === ctrl.$viewValue); - }; - - attr.$observe('value', ctrl.$render); -} - -function parseConstantExpr($parse, context, name, expression, fallback) { - var parseFn; - if (isDefined(expression)) { - parseFn = $parse(expression); - if (!parseFn.constant) { - throw ngModelMinErr('constexpr', 'Expected constant expression for `{0}`, but saw ' + - '`{1}`.', name, expression); - } - return parseFn(context); - } - return fallback; -} - -function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter, $parse) { - var trueValue = parseConstantExpr($parse, scope, 'ngTrueValue', attr.ngTrueValue, true); - var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false); - - var listener = function(ev) { - ctrl.$setViewValue(element[0].checked, ev && ev.type); - }; - - element.on('change', listener); - - ctrl.$render = function() { - element[0].checked = ctrl.$viewValue; - }; - - // Override the standard `$isEmpty` because the $viewValue of an empty checkbox is always set to `false` - // This is because of the parser below, which compares the `$modelValue` with `trueValue` to convert - // it to a boolean. - ctrl.$isEmpty = function(value) { - return value === false; - }; - - ctrl.$formatters.push(function(value) { - return equals(value, trueValue); - }); - - ctrl.$parsers.push(function(value) { - return value ? trueValue : falseValue; - }); -} - - -/** - * @ngdoc directive - * @name textarea - * @restrict E - * - * @description - * HTML textarea element control with AngularJS data-binding. The data-binding and validation - * properties of this element are exactly the same as those of the - * {@link ng.directive:input input element}. - * - * @param {string} ngModel Assignable AngularJS expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. Setting the attribute to a negative or non-numeric value, allows view values of any - * length. - * @param {string=} ngPattern Sets `pattern` validation error key if the ngModel {@link ngModel.NgModelController#$viewValue $viewValue} - * does not match a RegExp found by evaluating the AngularJS expression given in the attribute value. - * If the expression evaluates to a RegExp object, then this is used directly. - * If the expression evaluates to a string, then it will be converted to a RegExp - * after wrapping it in `^` and `$` characters. For instance, `"abc"` will be converted to - * `new RegExp('^abc$')`.
    - * **Note:** Avoid using the `g` flag on the RegExp, as it will cause each successive search to - * start at the index of the last search's match, thus not taking the whole input value into - * account. - * @param {string=} ngChange AngularJS expression to be executed when input changes due to user - * interaction with the input element. - * @param {boolean=} [ngTrim=true] If set to false AngularJS will not automatically trim the input. - * - * @knownIssue - * - * When specifying the `placeholder` attribute of ` - *
    {{ list | json }}
    - * - * - * it("should split the text by newlines", function() { - * var listInput = element(by.model('list')); - * var output = element(by.binding('list | json')); - * listInput.sendKeys('abc\ndef\nghi'); - * expect(output.getText()).toContain('[\n "abc",\n "def",\n "ghi"\n]'); - * }); - * - * - * - */ -var ngListDirective = function() { - return { - restrict: 'A', - priority: 100, - require: 'ngModel', - link: function(scope, element, attr, ctrl) { - var ngList = attr.ngList || ', '; - var trimValues = attr.ngTrim !== 'false'; - var separator = trimValues ? trim(ngList) : ngList; - - var parse = function(viewValue) { - // If the viewValue is invalid (say required but empty) it will be `undefined` - if (isUndefined(viewValue)) return; - - var list = []; - - if (viewValue) { - forEach(viewValue.split(separator), function(value) { - if (value) list.push(trimValues ? trim(value) : value); - }); - } - - return list; - }; - - ctrl.$parsers.push(parse); - ctrl.$formatters.push(function(value) { - if (isArray(value)) { - return value.join(ngList); - } - - return undefined; - }); - - // Override the standard $isEmpty because an empty array means the input is empty. - ctrl.$isEmpty = function(value) { - return !value || !value.length; - }; - } - }; -}; - -/* global VALID_CLASS: true, - INVALID_CLASS: true, - PRISTINE_CLASS: true, - DIRTY_CLASS: true, - UNTOUCHED_CLASS: true, - TOUCHED_CLASS: true, - PENDING_CLASS: true, - addSetValidityMethod: true, - setupValidity: true, - defaultModelOptions: false -*/ - - -var VALID_CLASS = 'ng-valid', - INVALID_CLASS = 'ng-invalid', - PRISTINE_CLASS = 'ng-pristine', - DIRTY_CLASS = 'ng-dirty', - UNTOUCHED_CLASS = 'ng-untouched', - TOUCHED_CLASS = 'ng-touched', - EMPTY_CLASS = 'ng-empty', - NOT_EMPTY_CLASS = 'ng-not-empty'; - -var ngModelMinErr = minErr('ngModel'); - -/** - * @ngdoc type - * @name ngModel.NgModelController - * @property {*} $viewValue The actual value from the control's view. For `input` elements, this is a - * String. See {@link ngModel.NgModelController#$setViewValue} for information about when the $viewValue - * is set. - * - * @property {*} $modelValue The value in the model that the control is bound to. - * - * @property {Array.} $parsers Array of functions to execute, as a pipeline, whenever - * the control updates the ngModelController with a new {@link ngModel.NgModelController#$viewValue - `$viewValue`} from the DOM, usually via user input. - See {@link ngModel.NgModelController#$setViewValue `$setViewValue()`} for a detailed lifecycle explanation. - Note that the `$parsers` are not called when the bound ngModel expression changes programmatically. - - The functions are called in array order, each passing - its return value through to the next. The last return value is forwarded to the - {@link ngModel.NgModelController#$validators `$validators`} collection. - - Parsers are used to sanitize / convert the {@link ngModel.NgModelController#$viewValue - `$viewValue`}. - - Returning `undefined` from a parser means a parse error occurred. In that case, - no {@link ngModel.NgModelController#$validators `$validators`} will run and the `ngModel` - will be set to `undefined` unless {@link ngModelOptions `ngModelOptions.allowInvalid`} - is set to `true`. The parse error is stored in `ngModel.$error.parse`. - - This simple example shows a parser that would convert text input value to lowercase: - * ```js - * function parse(value) { - * if (value) { - * return value.toLowerCase(); - * } - * } - * ngModelController.$parsers.push(parse); - * ``` - - * - * @property {Array.} $formatters Array of functions to execute, as a pipeline, whenever - the bound ngModel expression changes programmatically. The `$formatters` are not called when the - value of the control is changed by user interaction. - - Formatters are used to format / convert the {@link ngModel.NgModelController#$modelValue - `$modelValue`} for display in the control. - - The functions are called in reverse array order, each passing the value through to the - next. The last return value is used as the actual DOM value. - - This simple example shows a formatter that would convert the model value to uppercase: - - * ```js - * function format(value) { - * if (value) { - * return value.toUpperCase(); - * } - * } - * ngModel.$formatters.push(format); - * ``` - * - * @property {Object.} $validators A collection of validators that are applied - * whenever the model value changes. The key value within the object refers to the name of the - * validator while the function refers to the validation operation. The validation operation is - * provided with the model value as an argument and must return a true or false value depending - * on the response of that validation. - * - * ```js - * ngModel.$validators.validCharacters = function(modelValue, viewValue) { - * var value = modelValue || viewValue; - * return /[0-9]+/.test(value) && - * /[a-z]+/.test(value) && - * /[A-Z]+/.test(value) && - * /\W+/.test(value); - * }; - * ``` - * - * @property {Object.} $asyncValidators A collection of validations that are expected to - * perform an asynchronous validation (e.g. a HTTP request). The validation function that is provided - * is expected to return a promise when it is run during the model validation process. Once the promise - * is delivered then the validation status will be set to true when fulfilled and false when rejected. - * When the asynchronous validators are triggered, each of the validators will run in parallel and the model - * value will only be updated once all validators have been fulfilled. As long as an asynchronous validator - * is unfulfilled, its key will be added to the controllers `$pending` property. Also, all asynchronous validators - * will only run once all synchronous validators have passed. - * - * Please note that if $http is used then it is important that the server returns a success HTTP response code - * in order to fulfill the validation and a status level of `4xx` in order to reject the validation. - * - * ```js - * ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) { - * var value = modelValue || viewValue; - * - * // Lookup user by username - * return $http.get('/api/users/' + value). - * then(function resolved() { - * //username exists, this means validation fails - * return $q.reject('exists'); - * }, function rejected() { - * //username does not exist, therefore this validation passes - * return true; - * }); - * }; - * ``` - * - * @property {Array.} $viewChangeListeners Array of functions to execute whenever - * a change to {@link ngModel.NgModelController#$viewValue `$viewValue`} has caused a change - * to {@link ngModel.NgModelController#$modelValue `$modelValue`}. - * It is called with no arguments, and its return value is ignored. - * This can be used in place of additional $watches against the model value. - * - * @property {Object} $error An object hash with all failing validator ids as keys. - * @property {Object} $pending An object hash with all pending validator ids as keys. - * - * @property {boolean} $untouched True if control has not lost focus yet. - * @property {boolean} $touched True if control has lost focus. - * @property {boolean} $pristine True if user has not interacted with the control yet. - * @property {boolean} $dirty True if user has already interacted with the control. - * @property {boolean} $valid True if there is no error. - * @property {boolean} $invalid True if at least one error on the control. - * @property {string} $name The name attribute of the control. - * - * @description - * - * `NgModelController` provides API for the {@link ngModel `ngModel`} directive. - * The controller contains services for data-binding, validation, CSS updates, and value formatting - * and parsing. It purposefully does not contain any logic which deals with DOM rendering or - * listening to DOM events. - * Such DOM related logic should be provided by other directives which make use of - * `NgModelController` for data-binding to control elements. - * AngularJS provides this DOM logic for most {@link input `input`} elements. - * At the end of this page you can find a {@link ngModel.NgModelController#custom-control-example - * custom control example} that uses `ngModelController` to bind to `contenteditable` elements. - * - * @example - * ### Custom Control Example - * This example shows how to use `NgModelController` with a custom control to achieve - * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`) - * collaborate together to achieve the desired result. - * - * `contenteditable` is an HTML5 attribute, which tells the browser to let the element - * contents be edited in place by the user. - * - * We are using the {@link ng.service:$sce $sce} service here and include the {@link ngSanitize $sanitize} - * module to automatically remove "bad" content like inline event listener (e.g. ``). - * However, as we are using `$sce` the model can still decide to provide unsafe content if it marks - * that content using the `$sce` service. - * - * - - [contenteditable] { - border: 1px solid black; - background-color: white; - min-height: 20px; - } - - .ng-invalid { - border: 1px solid red; - } - - - - angular.module('customControl', ['ngSanitize']). - directive('contenteditable', ['$sce', function($sce) { - return { - restrict: 'A', // only activate on element attribute - require: '?ngModel', // get a hold of NgModelController - link: function(scope, element, attrs, ngModel) { - if (!ngModel) return; // do nothing if no ng-model - - // Specify how UI should be updated - ngModel.$render = function() { - element.html($sce.getTrustedHtml(ngModel.$viewValue || '')); - }; - - // Listen for change events to enable binding - element.on('blur keyup change', function() { - scope.$evalAsync(read); - }); - read(); // initialize - - // Write data to the model - function read() { - var html = element.html(); - // When we clear the content editable the browser leaves a
    behind - // If strip-br attribute is provided then we strip this out - if (attrs.stripBr && html === '
    ') { - html = ''; - } - ngModel.$setViewValue(html); - } - } - }; - }]); -
    - -
    -
    Change me!
    - Required! -
    - -
    -
    - - it('should data-bind and become invalid', function() { - if (browser.params.browser === 'safari' || browser.params.browser === 'firefox') { - // SafariDriver can't handle contenteditable - // and Firefox driver can't clear contenteditables very well - return; - } - var contentEditable = element(by.css('[contenteditable]')); - var content = 'Change me!'; - - expect(contentEditable.getText()).toEqual(content); - - contentEditable.clear(); - contentEditable.sendKeys(protractor.Key.BACK_SPACE); - expect(contentEditable.getText()).toEqual(''); - expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/); - }); - - *
    - * - * - */ -NgModelController.$inject = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$q', '$interpolate']; -function NgModelController($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $q, $interpolate) { - this.$viewValue = Number.NaN; - this.$modelValue = Number.NaN; - this.$$rawModelValue = undefined; // stores the parsed modelValue / model set from scope regardless of validity. - this.$validators = {}; - this.$asyncValidators = {}; - this.$parsers = []; - this.$formatters = []; - this.$viewChangeListeners = []; - this.$untouched = true; - this.$touched = false; - this.$pristine = true; - this.$dirty = false; - this.$valid = true; - this.$invalid = false; - this.$error = {}; // keep invalid keys here - this.$$success = {}; // keep valid keys here - this.$pending = undefined; // keep pending keys here - this.$name = $interpolate($attr.name || '', false)($scope); - this.$$parentForm = nullFormCtrl; - this.$options = defaultModelOptions; - this.$$updateEvents = ''; - // Attach the correct context to the event handler function for updateOn - this.$$updateEventHandler = this.$$updateEventHandler.bind(this); - - this.$$parsedNgModel = $parse($attr.ngModel); - this.$$parsedNgModelAssign = this.$$parsedNgModel.assign; - this.$$ngModelGet = this.$$parsedNgModel; - this.$$ngModelSet = this.$$parsedNgModelAssign; - this.$$pendingDebounce = null; - this.$$parserValid = undefined; - this.$$parserName = 'parse'; - - this.$$currentValidationRunId = 0; - - this.$$scope = $scope; - this.$$rootScope = $scope.$root; - this.$$attr = $attr; - this.$$element = $element; - this.$$animate = $animate; - this.$$timeout = $timeout; - this.$$parse = $parse; - this.$$q = $q; - this.$$exceptionHandler = $exceptionHandler; - - setupValidity(this); - setupModelWatcher(this); -} - -NgModelController.prototype = { - $$initGetterSetters: function() { - if (this.$options.getOption('getterSetter')) { - var invokeModelGetter = this.$$parse(this.$$attr.ngModel + '()'), - invokeModelSetter = this.$$parse(this.$$attr.ngModel + '($$$p)'); - - this.$$ngModelGet = function($scope) { - var modelValue = this.$$parsedNgModel($scope); - if (isFunction(modelValue)) { - modelValue = invokeModelGetter($scope); - } - return modelValue; - }; - this.$$ngModelSet = function($scope, newValue) { - if (isFunction(this.$$parsedNgModel($scope))) { - invokeModelSetter($scope, {$$$p: newValue}); - } else { - this.$$parsedNgModelAssign($scope, newValue); - } - }; - } else if (!this.$$parsedNgModel.assign) { - throw ngModelMinErr('nonassign', 'Expression \'{0}\' is non-assignable. Element: {1}', - this.$$attr.ngModel, startingTag(this.$$element)); - } - }, - - - /** - * @ngdoc method - * @name ngModel.NgModelController#$render - * - * @description - * Called when the view needs to be updated. It is expected that the user of the ng-model - * directive will implement this method. - * - * The `$render()` method is invoked in the following situations: - * - * * `$rollbackViewValue()` is called. If we are rolling back the view value to the last - * committed value then `$render()` is called to update the input control. - * * The value referenced by `ng-model` is changed programmatically and both the `$modelValue` and - * the `$viewValue` are different from last time. - * - * Since `ng-model` does not do a deep watch, `$render()` is only invoked if the values of - * `$modelValue` and `$viewValue` are actually different from their previous values. If `$modelValue` - * or `$viewValue` are objects (rather than a string or number) then `$render()` will not be - * invoked if you only change a property on the objects. - */ - $render: noop, - - /** - * @ngdoc method - * @name ngModel.NgModelController#$isEmpty - * - * @description - * This is called when we need to determine if the value of an input is empty. - * - * For instance, the required directive does this to work out if the input has data or not. - * - * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`. - * - * You can override this for input directives whose concept of being empty is different from the - * default. The `checkboxInputType` directive does this because in its case a value of `false` - * implies empty. - * - * @param {*} value The value of the input to check for emptiness. - * @returns {boolean} True if `value` is "empty". - */ - $isEmpty: function(value) { - // eslint-disable-next-line no-self-compare - return isUndefined(value) || value === '' || value === null || value !== value; - }, - - $$updateEmptyClasses: function(value) { - if (this.$isEmpty(value)) { - this.$$animate.removeClass(this.$$element, NOT_EMPTY_CLASS); - this.$$animate.addClass(this.$$element, EMPTY_CLASS); - } else { - this.$$animate.removeClass(this.$$element, EMPTY_CLASS); - this.$$animate.addClass(this.$$element, NOT_EMPTY_CLASS); - } - }, - - /** - * @ngdoc method - * @name ngModel.NgModelController#$setPristine - * - * @description - * Sets the control to its pristine state. - * - * This method can be called to remove the `ng-dirty` class and set the control to its pristine - * state (`ng-pristine` class). A model is considered to be pristine when the control - * has not been changed from when first compiled. - */ - $setPristine: function() { - this.$dirty = false; - this.$pristine = true; - this.$$animate.removeClass(this.$$element, DIRTY_CLASS); - this.$$animate.addClass(this.$$element, PRISTINE_CLASS); - }, - - /** - * @ngdoc method - * @name ngModel.NgModelController#$setDirty - * - * @description - * Sets the control to its dirty state. - * - * This method can be called to remove the `ng-pristine` class and set the control to its dirty - * state (`ng-dirty` class). A model is considered to be dirty when the control has been changed - * from when first compiled. - */ - $setDirty: function() { - this.$dirty = true; - this.$pristine = false; - this.$$animate.removeClass(this.$$element, PRISTINE_CLASS); - this.$$animate.addClass(this.$$element, DIRTY_CLASS); - this.$$parentForm.$setDirty(); - }, - - /** - * @ngdoc method - * @name ngModel.NgModelController#$setUntouched - * - * @description - * Sets the control to its untouched state. - * - * This method can be called to remove the `ng-touched` class and set the control to its - * untouched state (`ng-untouched` class). Upon compilation, a model is set as untouched - * by default, however this function can be used to restore that state if the model has - * already been touched by the user. - */ - $setUntouched: function() { - this.$touched = false; - this.$untouched = true; - this.$$animate.setClass(this.$$element, UNTOUCHED_CLASS, TOUCHED_CLASS); - }, - - /** - * @ngdoc method - * @name ngModel.NgModelController#$setTouched - * - * @description - * Sets the control to its touched state. - * - * This method can be called to remove the `ng-untouched` class and set the control to its - * touched state (`ng-touched` class). A model is considered to be touched when the user has - * first focused the control element and then shifted focus away from the control (blur event). - */ - $setTouched: function() { - this.$touched = true; - this.$untouched = false; - this.$$animate.setClass(this.$$element, TOUCHED_CLASS, UNTOUCHED_CLASS); - }, - - /** - * @ngdoc method - * @name ngModel.NgModelController#$rollbackViewValue - * - * @description - * Cancel an update and reset the input element's value to prevent an update to the `$modelValue`, - * which may be caused by a pending debounced event or because the input is waiting for some - * future event. - * - * If you have an input that uses `ng-model-options` to set up debounced updates or updates that - * depend on special events such as `blur`, there can be a period when the `$viewValue` is out of - * sync with the ngModel's `$modelValue`. - * - * In this case, you can use `$rollbackViewValue()` to manually cancel the debounced / future update - * and reset the input to the last committed view value. - * - * It is also possible that you run into difficulties if you try to update the ngModel's `$modelValue` - * programmatically before these debounced/future events have resolved/occurred, because AngularJS's - * dirty checking mechanism is not able to tell whether the model has actually changed or not. - * - * The `$rollbackViewValue()` method should be called before programmatically changing the model of an - * input which may have such events pending. This is important in order to make sure that the - * input field will be updated with the new model value and any pending operations are cancelled. - * - * @example - * - * - * angular.module('cancel-update-example', []) - * - * .controller('CancelUpdateController', ['$scope', function($scope) { - * $scope.model = {value1: '', value2: ''}; - * - * $scope.setEmpty = function(e, value, rollback) { - * if (e.keyCode === 27) { - * e.preventDefault(); - * if (rollback) { - * $scope.myForm[value].$rollbackViewValue(); - * } - * $scope.model[value] = ''; - * } - * }; - * }]); - * - * - *
    - *

    Both of these inputs are only updated if they are blurred. Hitting escape should - * empty them. Follow these steps and observe the difference:

    - *
      - *
    1. Type something in the input. You will see that the model is not yet updated
    2. - *
    3. Press the Escape key. - *
        - *
      1. In the first example, nothing happens, because the model is already '', and no - * update is detected. If you blur the input, the model will be set to the current view. - *
      2. - *
      3. In the second example, the pending update is cancelled, and the input is set back - * to the last committed view value (''). Blurring the input does nothing. - *
      4. - *
      - *
    4. - *
    - * - *
    - *
    - *

    Without $rollbackViewValue():

    - * - * value1: "{{ model.value1 }}" - *
    - * - *
    - *

    With $rollbackViewValue():

    - * - * value2: "{{ model.value2 }}" - *
    - *
    - *
    - *
    - - div { - display: table-cell; - } - div:nth-child(1) { - padding-right: 30px; - } - - - *
    - */ - $rollbackViewValue: function() { - this.$$timeout.cancel(this.$$pendingDebounce); - this.$viewValue = this.$$lastCommittedViewValue; - this.$render(); - }, - - /** - * @ngdoc method - * @name ngModel.NgModelController#$validate - * - * @description - * Runs each of the registered validators (first synchronous validators and then - * asynchronous validators). - * If the validity changes to invalid, the model will be set to `undefined`, - * unless {@link ngModelOptions `ngModelOptions.allowInvalid`} is `true`. - * If the validity changes to valid, it will set the model to the last available valid - * `$modelValue`, i.e. either the last parsed value or the last value set from the scope. - */ - $validate: function() { - - // ignore $validate before model is initialized - if (isNumberNaN(this.$modelValue)) { - return; - } - - var viewValue = this.$$lastCommittedViewValue; - // Note: we use the $$rawModelValue as $modelValue might have been - // set to undefined during a view -> model update that found validation - // errors. We can't parse the view here, since that could change - // the model although neither viewValue nor the model on the scope changed - var modelValue = this.$$rawModelValue; - - var prevValid = this.$valid; - var prevModelValue = this.$modelValue; - - var allowInvalid = this.$options.getOption('allowInvalid'); - - var that = this; - this.$$runValidators(modelValue, viewValue, function(allValid) { - // If there was no change in validity, don't update the model - // This prevents changing an invalid modelValue to undefined - if (!allowInvalid && prevValid !== allValid) { - // Note: Don't check this.$valid here, as we could have - // external validators (e.g. calculated on the server), - // that just call $setValidity and need the model value - // to calculate their validity. - that.$modelValue = allValid ? modelValue : undefined; - - if (that.$modelValue !== prevModelValue) { - that.$$writeModelToScope(); - } - } - }); - }, - - $$runValidators: function(modelValue, viewValue, doneCallback) { - this.$$currentValidationRunId++; - var localValidationRunId = this.$$currentValidationRunId; - var that = this; - - // check parser error - if (!processParseErrors()) { - validationDone(false); - return; - } - if (!processSyncValidators()) { - validationDone(false); - return; - } - processAsyncValidators(); - - function processParseErrors() { - var errorKey = that.$$parserName; - - if (isUndefined(that.$$parserValid)) { - setValidity(errorKey, null); - } else { - if (!that.$$parserValid) { - forEach(that.$validators, function(v, name) { - setValidity(name, null); - }); - forEach(that.$asyncValidators, function(v, name) { - setValidity(name, null); - }); - } - - // Set the parse error last, to prevent unsetting it, should a $validators key == parserName - setValidity(errorKey, that.$$parserValid); - return that.$$parserValid; - } - return true; - } - - function processSyncValidators() { - var syncValidatorsValid = true; - forEach(that.$validators, function(validator, name) { - var result = Boolean(validator(modelValue, viewValue)); - syncValidatorsValid = syncValidatorsValid && result; - setValidity(name, result); - }); - if (!syncValidatorsValid) { - forEach(that.$asyncValidators, function(v, name) { - setValidity(name, null); - }); - return false; - } - return true; - } - - function processAsyncValidators() { - var validatorPromises = []; - var allValid = true; - forEach(that.$asyncValidators, function(validator, name) { - var promise = validator(modelValue, viewValue); - if (!isPromiseLike(promise)) { - throw ngModelMinErr('nopromise', - 'Expected asynchronous validator to return a promise but got \'{0}\' instead.', promise); - } - setValidity(name, undefined); - validatorPromises.push(promise.then(function() { - setValidity(name, true); - }, function() { - allValid = false; - setValidity(name, false); - })); - }); - if (!validatorPromises.length) { - validationDone(true); - } else { - that.$$q.all(validatorPromises).then(function() { - validationDone(allValid); - }, noop); - } - } - - function setValidity(name, isValid) { - if (localValidationRunId === that.$$currentValidationRunId) { - that.$setValidity(name, isValid); - } - } - - function validationDone(allValid) { - if (localValidationRunId === that.$$currentValidationRunId) { - - doneCallback(allValid); - } - } - }, - - /** - * @ngdoc method - * @name ngModel.NgModelController#$commitViewValue - * - * @description - * Commit a pending update to the `$modelValue`. - * - * Updates may be pending by a debounced event or because the input is waiting for a some future - * event defined in `ng-model-options`. this method is rarely needed as `NgModelController` - * usually handles calling this in response to input events. - */ - $commitViewValue: function() { - var viewValue = this.$viewValue; - - this.$$timeout.cancel(this.$$pendingDebounce); - - // If the view value has not changed then we should just exit, except in the case where there is - // a native validator on the element. In this case the validation state may have changed even though - // the viewValue has stayed empty. - if (this.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !this.$$hasNativeValidators)) { - return; - } - this.$$updateEmptyClasses(viewValue); - this.$$lastCommittedViewValue = viewValue; - - // change to dirty - if (this.$pristine) { - this.$setDirty(); - } - this.$$parseAndValidate(); - }, - - $$parseAndValidate: function() { - var viewValue = this.$$lastCommittedViewValue; - var modelValue = viewValue; - var that = this; - - this.$$parserValid = isUndefined(modelValue) ? undefined : true; - - // Reset any previous parse error - this.$setValidity(this.$$parserName, null); - this.$$parserName = 'parse'; - - if (this.$$parserValid) { - for (var i = 0; i < this.$parsers.length; i++) { - modelValue = this.$parsers[i](modelValue); - if (isUndefined(modelValue)) { - this.$$parserValid = false; - break; - } - } - } - if (isNumberNaN(this.$modelValue)) { - // this.$modelValue has not been touched yet... - this.$modelValue = this.$$ngModelGet(this.$$scope); - } - var prevModelValue = this.$modelValue; - var allowInvalid = this.$options.getOption('allowInvalid'); - this.$$rawModelValue = modelValue; - - if (allowInvalid) { - this.$modelValue = modelValue; - writeToModelIfNeeded(); - } - - // Pass the $$lastCommittedViewValue here, because the cached viewValue might be out of date. - // This can happen if e.g. $setViewValue is called from inside a parser - this.$$runValidators(modelValue, this.$$lastCommittedViewValue, function(allValid) { - if (!allowInvalid) { - // Note: Don't check this.$valid here, as we could have - // external validators (e.g. calculated on the server), - // that just call $setValidity and need the model value - // to calculate their validity. - that.$modelValue = allValid ? modelValue : undefined; - writeToModelIfNeeded(); - } - }); - - function writeToModelIfNeeded() { - if (that.$modelValue !== prevModelValue) { - that.$$writeModelToScope(); - } - } - }, - - $$writeModelToScope: function() { - this.$$ngModelSet(this.$$scope, this.$modelValue); - forEach(this.$viewChangeListeners, function(listener) { - try { - listener(); - } catch (e) { - // eslint-disable-next-line no-invalid-this - this.$$exceptionHandler(e); - } - }, this); - }, - - /** - * @ngdoc method - * @name ngModel.NgModelController#$setViewValue - * - * @description - * Update the view value. - * - * This method should be called when a control wants to change the view value; typically, - * this is done from within a DOM event handler. For example, the {@link ng.directive:input input} - * directive calls it when the value of the input changes and {@link ng.directive:select select} - * calls it when an option is selected. - * - * When `$setViewValue` is called, the new `value` will be staged for committing through the `$parsers` - * and `$validators` pipelines. If there are no special {@link ngModelOptions} specified then the staged - * value is sent directly for processing through the `$parsers` pipeline. After this, the `$validators` and - * `$asyncValidators` are called and the value is applied to `$modelValue`. - * Finally, the value is set to the **expression** specified in the `ng-model` attribute and - * all the registered change listeners, in the `$viewChangeListeners` list are called. - * - * In case the {@link ng.directive:ngModelOptions ngModelOptions} directive is used with `updateOn` - * and the `default` trigger is not listed, all those actions will remain pending until one of the - * `updateOn` events is triggered on the DOM element. - * All these actions will be debounced if the {@link ng.directive:ngModelOptions ngModelOptions} - * directive is used with a custom debounce for this particular event. - * Note that a `$digest` is only triggered once the `updateOn` events are fired, or if `debounce` - * is specified, once the timer runs out. - * - * When used with standard inputs, the view value will always be a string (which is in some cases - * parsed into another type, such as a `Date` object for `input[date]`.) - * However, custom controls might also pass objects to this method. In this case, we should make - * a copy of the object before passing it to `$setViewValue`. This is because `ngModel` does not - * perform a deep watch of objects, it only looks for a change of identity. If you only change - * the property of the object then ngModel will not realize that the object has changed and - * will not invoke the `$parsers` and `$validators` pipelines. For this reason, you should - * not change properties of the copy once it has been passed to `$setViewValue`. - * Otherwise you may cause the model value on the scope to change incorrectly. - * - *
    - * In any case, the value passed to the method should always reflect the current value - * of the control. For example, if you are calling `$setViewValue` for an input element, - * you should pass the input DOM value. Otherwise, the control and the scope model become - * out of sync. It's also important to note that `$setViewValue` does not call `$render` or change - * the control's DOM value in any way. If we want to change the control's DOM value - * programmatically, we should update the `ngModel` scope expression. Its new value will be - * picked up by the model controller, which will run it through the `$formatters`, `$render` it - * to update the DOM, and finally call `$validate` on it. - *
    - * - * @param {*} value value from the view. - * @param {string} trigger Event that triggered the update. - */ - $setViewValue: function(value, trigger) { - this.$viewValue = value; - if (this.$options.getOption('updateOnDefault')) { - this.$$debounceViewValueCommit(trigger); - } - }, - - $$debounceViewValueCommit: function(trigger) { - var debounceDelay = this.$options.getOption('debounce'); - - if (isNumber(debounceDelay[trigger])) { - debounceDelay = debounceDelay[trigger]; - } else if (isNumber(debounceDelay['default']) && - this.$options.getOption('updateOn').indexOf(trigger) === -1 - ) { - debounceDelay = debounceDelay['default']; - } else if (isNumber(debounceDelay['*'])) { - debounceDelay = debounceDelay['*']; - } - - this.$$timeout.cancel(this.$$pendingDebounce); - var that = this; - if (debounceDelay > 0) { // this fails if debounceDelay is an object - this.$$pendingDebounce = this.$$timeout(function() { - that.$commitViewValue(); - }, debounceDelay); - } else if (this.$$rootScope.$$phase) { - this.$commitViewValue(); - } else { - this.$$scope.$apply(function() { - that.$commitViewValue(); - }); - } - }, - - /** - * @ngdoc method - * - * @name ngModel.NgModelController#$overrideModelOptions - * - * @description - * - * Override the current model options settings programmatically. - * - * The previous `ModelOptions` value will not be modified. Instead, a - * new `ModelOptions` object will inherit from the previous one overriding - * or inheriting settings that are defined in the given parameter. - * - * See {@link ngModelOptions} for information about what options can be specified - * and how model option inheritance works. - * - *
    - * **Note:** this function only affects the options set on the `ngModelController`, - * and not the options on the {@link ngModelOptions} directive from which they might have been - * obtained initially. - *
    - * - *
    - * **Note:** it is not possible to override the `getterSetter` option. - *
    - * - * @param {Object} options a hash of settings to override the previous options - * - */ - $overrideModelOptions: function(options) { - this.$options = this.$options.createChild(options); - this.$$setUpdateOnEvents(); - }, - - /** - * @ngdoc method - * - * @name ngModel.NgModelController#$processModelValue - - * @description - * - * Runs the model -> view pipeline on the current - * {@link ngModel.NgModelController#$modelValue $modelValue}. - * - * The following actions are performed by this method: - * - * - the `$modelValue` is run through the {@link ngModel.NgModelController#$formatters $formatters} - * and the result is set to the {@link ngModel.NgModelController#$viewValue $viewValue} - * - the `ng-empty` or `ng-not-empty` class is set on the element - * - if the `$viewValue` has changed: - * - {@link ngModel.NgModelController#$render $render} is called on the control - * - the {@link ngModel.NgModelController#$validators $validators} are run and - * the validation status is set. - * - * This method is called by ngModel internally when the bound scope value changes. - * Application developers usually do not have to call this function themselves. - * - * This function can be used when the `$viewValue` or the rendered DOM value are not correctly - * formatted and the `$modelValue` must be run through the `$formatters` again. - * - * @example - * Consider a text input with an autocomplete list (for fruit), where the items are - * objects with a name and an id. - * A user enters `ap` and then selects `Apricot` from the list. - * Based on this, the autocomplete widget will call `$setViewValue({name: 'Apricot', id: 443})`, - * but the rendered value will still be `ap`. - * The widget can then call `ctrl.$processModelValue()` to run the model -> view - * pipeline again, which formats the object to the string `Apricot`, - * then updates the `$viewValue`, and finally renders it in the DOM. - * - * - -
    -
    - Search Fruit: - -
    -
    - Model:
    -
    {{selectedFruit | json}}
    -
    -
    -
    - - angular.module('inputExample', []) - .controller('inputController', function($scope) { - $scope.items = [ - {name: 'Apricot', id: 443}, - {name: 'Clementine', id: 972}, - {name: 'Durian', id: 169}, - {name: 'Jackfruit', id: 982}, - {name: 'Strawberry', id: 863} - ]; - }) - .component('basicAutocomplete', { - bindings: { - items: '<', - onSelect: '&' - }, - templateUrl: 'autocomplete.html', - controller: function($element, $scope) { - var that = this; - var ngModel; - - that.$postLink = function() { - ngModel = $element.find('input').controller('ngModel'); - - ngModel.$formatters.push(function(value) { - return (value && value.name) || value; - }); - - ngModel.$parsers.push(function(value) { - var match = value; - for (var i = 0; i < that.items.length; i++) { - if (that.items[i].name === value) { - match = that.items[i]; - break; - } - } - - return match; - }); - }; - - that.selectItem = function(item) { - ngModel.$setViewValue(item); - ngModel.$processModelValue(); - that.onSelect({item: item}); - }; - } - }); - - -
    - -
      -
    • - -
    • -
    -
    -
    - *
    - * - */ - $processModelValue: function() { - var viewValue = this.$$format(); - - if (this.$viewValue !== viewValue) { - this.$$updateEmptyClasses(viewValue); - this.$viewValue = this.$$lastCommittedViewValue = viewValue; - this.$render(); - // It is possible that model and view value have been updated during render - this.$$runValidators(this.$modelValue, this.$viewValue, noop); - } - }, - - /** - * This method is called internally to run the $formatters on the $modelValue - */ - $$format: function() { - var formatters = this.$formatters, - idx = formatters.length; - - var viewValue = this.$modelValue; - while (idx--) { - viewValue = formatters[idx](viewValue); - } - - return viewValue; - }, - - /** - * This method is called internally when the bound scope value changes. - */ - $$setModelValue: function(modelValue) { - this.$modelValue = this.$$rawModelValue = modelValue; - this.$$parserValid = undefined; - this.$processModelValue(); - }, - - $$setUpdateOnEvents: function() { - if (this.$$updateEvents) { - this.$$element.off(this.$$updateEvents, this.$$updateEventHandler); - } - - this.$$updateEvents = this.$options.getOption('updateOn'); - if (this.$$updateEvents) { - this.$$element.on(this.$$updateEvents, this.$$updateEventHandler); - } - }, - - $$updateEventHandler: function(ev) { - this.$$debounceViewValueCommit(ev && ev.type); - } -}; - -function setupModelWatcher(ctrl) { - // model -> value - // Note: we cannot use a normal scope.$watch as we want to detect the following: - // 1. scope value is 'a' - // 2. user enters 'b' - // 3. ng-change kicks in and reverts scope value to 'a' - // -> scope value did not change since the last digest as - // ng-change executes in apply phase - // 4. view should be changed back to 'a' - ctrl.$$scope.$watch(function ngModelWatch(scope) { - var modelValue = ctrl.$$ngModelGet(scope); - - // if scope model value and ngModel value are out of sync - // This cannot be moved to the action function, because it would not catch the - // case where the model is changed in the ngChange function or the model setter - if (modelValue !== ctrl.$modelValue && - // checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator - // eslint-disable-next-line no-self-compare - (ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue) - ) { - ctrl.$$setModelValue(modelValue); - } - - return modelValue; - }); -} - -/** - * @ngdoc method - * @name ngModel.NgModelController#$setValidity - * - * @description - * Change the validity state, and notify the form. - * - * This method can be called within $parsers/$formatters or a custom validation implementation. - * However, in most cases it should be sufficient to use the `ngModel.$validators` and - * `ngModel.$asyncValidators` collections which will call `$setValidity` automatically. - * - * @param {string} validationErrorKey Name of the validator. The `validationErrorKey` will be assigned - * to either `$error[validationErrorKey]` or `$pending[validationErrorKey]` - * (for unfulfilled `$asyncValidators`), so that it is available for data-binding. - * The `validationErrorKey` should be in camelCase and will get converted into dash-case - * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error` - * classes and can be bound to as `{{ someForm.someControl.$error.myError }}`. - * @param {boolean} isValid Whether the current state is valid (true), invalid (false), pending (undefined), - * or skipped (null). Pending is used for unfulfilled `$asyncValidators`. - * Skipped is used by AngularJS when validators do not run because of parse errors and - * when `$asyncValidators` do not run because any of the `$validators` failed. - */ -addSetValidityMethod({ - clazz: NgModelController, - set: function(object, property) { - object[property] = true; - }, - unset: function(object, property) { - delete object[property]; - } -}); - - -/** - * @ngdoc directive - * @name ngModel - * @restrict A - * @priority 1 - * @param {expression} ngModel assignable {@link guide/expression Expression} to bind to. - * - * @description - * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a - * property on the scope using {@link ngModel.NgModelController NgModelController}, - * which is created and exposed by this directive. - * - * `ngModel` is responsible for: - * - * - Binding the view into the model, which other directives such as `input`, `textarea` or `select` - * require. - * - Providing validation behavior (i.e. required, number, email, url). - * - Keeping the state of the control (valid/invalid, dirty/pristine, touched/untouched, validation errors). - * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`, `ng-touched`, - * `ng-untouched`, `ng-empty`, `ng-not-empty`) including animations. - * - Registering the control with its parent {@link ng.directive:form form}. - * - * Note: `ngModel` will try to bind to the property given by evaluating the expression on the - * current scope. If the property doesn't already exist on this scope, it will be created - * implicitly and added to the scope. - * - * For best practices on using `ngModel`, see: - * - * - [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes) - * - * For basic examples, how to use `ngModel`, see: - * - * - {@link ng.directive:input input} - * - {@link input[text] text} - * - {@link input[checkbox] checkbox} - * - {@link input[radio] radio} - * - {@link input[number] number} - * - {@link input[email] email} - * - {@link input[url] url} - * - {@link input[date] date} - * - {@link input[datetime-local] datetime-local} - * - {@link input[time] time} - * - {@link input[month] month} - * - {@link input[week] week} - * - {@link ng.directive:select select} - * - {@link ng.directive:textarea textarea} - * - * ## Complex Models (objects or collections) - * - * By default, `ngModel` watches the model by reference, not value. This is important to know when - * binding inputs to models that are objects (e.g. `Date`) or collections (e.g. arrays). If only properties of the - * object or collection change, `ngModel` will not be notified and so the input will not be re-rendered. - * - * The model must be assigned an entirely new object or collection before a re-rendering will occur. - * - * Some directives have options that will cause them to use a custom `$watchCollection` on the model expression - * - for example, `ngOptions` will do so when a `track by` clause is included in the comprehension expression or - * if the select is given the `multiple` attribute. - * - * The `$watchCollection()` method only does a shallow comparison, meaning that changing properties deeper than the - * first level of the object (or only changing the properties of an item in the collection if it's an array) will still - * not trigger a re-rendering of the model. - * - * ## CSS classes - * The following CSS classes are added and removed on the associated input/select/textarea element - * depending on the validity of the model. - * - * - `ng-valid`: the model is valid - * - `ng-invalid`: the model is invalid - * - `ng-valid-[key]`: for each valid key added by `$setValidity` - * - `ng-invalid-[key]`: for each invalid key added by `$setValidity` - * - `ng-pristine`: the control hasn't been interacted with yet - * - `ng-dirty`: the control has been interacted with - * - `ng-touched`: the control has been blurred - * - `ng-untouched`: the control hasn't been blurred - * - `ng-pending`: any `$asyncValidators` are unfulfilled - * - `ng-empty`: the view does not contain a value or the value is deemed "empty", as defined - * by the {@link ngModel.NgModelController#$isEmpty} method - * - `ng-not-empty`: the view contains a non-empty value - * - * Keep in mind that ngAnimate can detect each of these classes when added and removed. - * - * @animations - * Animations within models are triggered when any of the associated CSS classes are added and removed - * on the input element which is attached to the model. These classes include: `.ng-pristine`, `.ng-dirty`, - * `.ng-invalid` and `.ng-valid` as well as any other validations that are performed on the model itself. - * The animations that are triggered within ngModel are similar to how they work in ngClass and - * animations can be hooked into using CSS transitions, keyframes as well as JS animations. - * - * The following example shows a simple way to utilize CSS transitions to style an input element - * that has been rendered as invalid after it has been validated: - * - *
    - * //be sure to include ngAnimate as a module to hook into more
    - * //advanced animations
    - * .my-input {
    - *   transition:0.5s linear all;
    - *   background: white;
    - * }
    - * .my-input.ng-invalid {
    - *   background: red;
    - *   color:white;
    - * }
    - * 
    - * - * @example - * ### Basic Usage - * - - - -

    - Update input to see transitions when valid/invalid. - Integer is a valid value. -

    -
    - -
    -
    - *
    - * - * @example - * ### Binding to a getter/setter - * - * Sometimes it's helpful to bind `ngModel` to a getter/setter function. A getter/setter is a - * function that returns a representation of the model when called with zero arguments, and sets - * the internal state of a model when called with an argument. It's sometimes useful to use this - * for models that have an internal representation that's different from what the model exposes - * to the view. - * - *
    - * **Best Practice:** It's best to keep getters fast because AngularJS is likely to call them more - * frequently than other parts of your code. - *
    - * - * You use this behavior by adding `ng-model-options="{ getterSetter: true }"` to an element that - * has `ng-model` attached to it. You can also add `ng-model-options="{ getterSetter: true }"` to - * a `
    `, which will enable this behavior for all ``s within it. See - * {@link ng.directive:ngModelOptions `ngModelOptions`} for more. - * - * The following example shows how to use `ngModel` with a getter/setter: - * - * @example - * - -
    - - - -
    user.name = 
    -
    -
    - - angular.module('getterSetterExample', []) - .controller('ExampleController', ['$scope', function($scope) { - var _name = 'Brian'; - $scope.user = { - name: function(newName) { - // Note that newName can be undefined for two reasons: - // 1. Because it is called as a getter and thus called with no arguments - // 2. Because the property should actually be set to undefined. This happens e.g. if the - // input is invalid - return arguments.length ? (_name = newName) : _name; - } - }; - }]); - - *
    - */ -var ngModelDirective = ['$rootScope', function($rootScope) { - return { - restrict: 'A', - require: ['ngModel', '^?form', '^?ngModelOptions'], - controller: NgModelController, - // Prelink needs to run before any input directive - // so that we can set the NgModelOptions in NgModelController - // before anyone else uses it. - priority: 1, - compile: function ngModelCompile(element) { - // Setup initial state of the control - element.addClass(PRISTINE_CLASS).addClass(UNTOUCHED_CLASS).addClass(VALID_CLASS); - - return { - pre: function ngModelPreLink(scope, element, attr, ctrls) { - var modelCtrl = ctrls[0], - formCtrl = ctrls[1] || modelCtrl.$$parentForm, - optionsCtrl = ctrls[2]; - - if (optionsCtrl) { - modelCtrl.$options = optionsCtrl.$options; - } - - modelCtrl.$$initGetterSetters(); - - // notify others, especially parent forms - formCtrl.$addControl(modelCtrl); - - attr.$observe('name', function(newValue) { - if (modelCtrl.$name !== newValue) { - modelCtrl.$$parentForm.$$renameControl(modelCtrl, newValue); - } - }); - - scope.$on('$destroy', function() { - modelCtrl.$$parentForm.$removeControl(modelCtrl); - }); - }, - post: function ngModelPostLink(scope, element, attr, ctrls) { - var modelCtrl = ctrls[0]; - modelCtrl.$$setUpdateOnEvents(); - - function setTouched() { - modelCtrl.$setTouched(); - } - - element.on('blur', function() { - if (modelCtrl.$touched) return; - - if ($rootScope.$$phase) { - scope.$evalAsync(setTouched); - } else { - scope.$apply(setTouched); - } - }); - } - }; - } - }; -}]; - -/* exported defaultModelOptions */ -var defaultModelOptions; -var DEFAULT_REGEXP = /(\s+|^)default(\s+|$)/; - -/** - * @ngdoc type - * @name ModelOptions - * @description - * A container for the options set by the {@link ngModelOptions} directive - */ -function ModelOptions(options) { - this.$$options = options; -} - -ModelOptions.prototype = { - - /** - * @ngdoc method - * @name ModelOptions#getOption - * @param {string} name the name of the option to retrieve - * @returns {*} the value of the option - * @description - * Returns the value of the given option - */ - getOption: function(name) { - return this.$$options[name]; - }, - - /** - * @ngdoc method - * @name ModelOptions#createChild - * @param {Object} options a hash of options for the new child that will override the parent's options - * @return {ModelOptions} a new `ModelOptions` object initialized with the given options. - */ - createChild: function(options) { - var inheritAll = false; - - // make a shallow copy - options = extend({}, options); - - // Inherit options from the parent if specified by the value `"$inherit"` - forEach(options, /** @this */ function(option, key) { - if (option === '$inherit') { - if (key === '*') { - inheritAll = true; - } else { - options[key] = this.$$options[key]; - // `updateOn` is special so we must also inherit the `updateOnDefault` option - if (key === 'updateOn') { - options.updateOnDefault = this.$$options.updateOnDefault; - } - } - } else { - if (key === 'updateOn') { - // If the `updateOn` property contains the `default` event then we have to remove - // it from the event list and set the `updateOnDefault` flag. - options.updateOnDefault = false; - options[key] = trim(option.replace(DEFAULT_REGEXP, function() { - options.updateOnDefault = true; - return ' '; - })); - } - } - }, this); - - if (inheritAll) { - // We have a property of the form: `"*": "$inherit"` - delete options['*']; - defaults(options, this.$$options); - } - - // Finally add in any missing defaults - defaults(options, defaultModelOptions.$$options); - - return new ModelOptions(options); - } -}; - - -defaultModelOptions = new ModelOptions({ - updateOn: '', - updateOnDefault: true, - debounce: 0, - getterSetter: false, - allowInvalid: false, - timezone: null -}); - - -/** - * @ngdoc directive - * @name ngModelOptions - * @restrict A - * @priority 10 - * - * @description - * This directive allows you to modify the behaviour of {@link ngModel} directives within your - * application. You can specify an `ngModelOptions` directive on any element. All {@link ngModel} - * directives will use the options of their nearest `ngModelOptions` ancestor. - * - * The `ngModelOptions` settings are found by evaluating the value of the attribute directive as - * an AngularJS expression. This expression should evaluate to an object, whose properties contain - * the settings. For example: `
    - *
    - * - *
    - *
    - * ``` - * - * the `input` element will have the following settings - * - * ```js - * { allowInvalid: true, updateOn: 'default', debounce: 0 } - * ``` - * - * Notice that the `debounce` setting was not inherited and used the default value instead. - * - * You can specify that all undefined settings are automatically inherited from an ancestor by - * including a property with key of `"*"` and value of `"$inherit"`. - * - * For example given the following fragment of HTML - * - * - * ```html - *
    - *
    - * - *
    - *
    - * ``` - * - * the `input` element will have the following settings - * - * ```js - * { allowInvalid: true, updateOn: 'default', debounce: 200 } - * ``` - * - * Notice that the `debounce` setting now inherits the value from the outer `
    ` element. - * - * If you are creating a reusable component then you should be careful when using `"*": "$inherit"` - * since you may inadvertently inherit a setting in the future that changes the behavior of your component. - * - * - * ## Triggering and debouncing model updates - * - * The `updateOn` and `debounce` properties allow you to specify a custom list of events that will - * trigger a model update and/or a debouncing delay so that the actual update only takes place when - * a timer expires; this timer will be reset after another change takes place. - * - * Given the nature of `ngModelOptions`, the value displayed inside input fields in the view might - * be different from the value in the actual model. This means that if you update the model you - * should also invoke {@link ngModel.NgModelController#$rollbackViewValue} on the relevant input field in - * order to make sure it is synchronized with the model and that any debounced action is canceled. - * - * The easiest way to reference the control's {@link ngModel.NgModelController#$rollbackViewValue} - * method is by making sure the input is placed inside a form that has a `name` attribute. This is - * important because `form` controllers are published to the related scope under the name in their - * `name` attribute. - * - * Any pending changes will take place immediately when an enclosing form is submitted via the - * `submit` event. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit` - * to have access to the updated model. - * - * ### Overriding immediate updates - * - * The following example shows how to override immediate updates. Changes on the inputs within the - * form will update the model only when the control loses focus (blur event). If `escape` key is - * pressed while the input field is focused, the value is reset to the value in the current model. - * - * - * - *
    - *
    - *
    - *
    - *
    - *
    user.name = 
    - *
    - *
    - * - * angular.module('optionsExample', []) - * .controller('ExampleController', ['$scope', function($scope) { - * $scope.user = { name: 'say', data: '' }; - * - * $scope.cancel = function(e) { - * if (e.keyCode === 27) { - * $scope.userForm.userName.$rollbackViewValue(); - * } - * }; - * }]); - * - * - * var model = element(by.binding('user.name')); - * var input = element(by.model('user.name')); - * var other = element(by.model('user.data')); - * - * it('should allow custom events', function() { - * input.sendKeys(' hello'); - * input.click(); - * expect(model.getText()).toEqual('say'); - * other.click(); - * expect(model.getText()).toEqual('say hello'); - * }); - * - * it('should $rollbackViewValue when model changes', function() { - * input.sendKeys(' hello'); - * expect(input.getAttribute('value')).toEqual('say hello'); - * input.sendKeys(protractor.Key.ESCAPE); - * expect(input.getAttribute('value')).toEqual('say'); - * other.click(); - * expect(model.getText()).toEqual('say'); - * }); - * - *
    - * - * ### Debouncing updates - * - * The next example shows how to debounce model changes. Model will be updated only 1 sec after last change. - * If the `Clear` button is pressed, any debounced action is canceled and the value becomes empty. - * - * - * - *
    - *
    - * Name: - * - *
    - *
    - *
    user.name = 
    - *
    - *
    - * - * angular.module('optionsExample', []) - * .controller('ExampleController', ['$scope', function($scope) { - * $scope.user = { name: 'say' }; - * }]); - * - *
    - * - * ### Default events, extra triggers, and catch-all debounce values - * - * This example shows the relationship between "default" update events and - * additional `updateOn` triggers. - * - * `default` events are those that are bound to the control, and when fired, update the `$viewValue` - * via {@link ngModel.NgModelController#$setViewValue $setViewValue}. Every event that is not listed - * in `updateOn` is considered a "default" event, since different control types have different - * default events. - * - * The control in this example updates by "default", "click", and "blur", with different `debounce` - * values. You can see that "click" doesn't have an individual `debounce` value - - * therefore it uses the `*` debounce value. - * - * There is also a button that calls {@link ngModel.NgModelController#$setViewValue $setViewValue} - * directly with a "custom" event. Since "custom" is not defined in the `updateOn` list, - * it is considered a "default" event and will update the - * control if "default" is defined in `updateOn`, and will receive the "default" debounce value. - * Note that this is just to illustrate how custom controls would possibly call `$setViewValue`. - * - * You can change the `updateOn` and `debounce` configuration to test different scenarios. This - * is done with {@link ngModel.NgModelController#$overrideModelOptions $overrideModelOptions}. - * - - - - - - angular.module('optionsExample', []) - .component('modelUpdateDemo', { - templateUrl: 'template.html', - controller: function() { - this.name = 'Chinua'; - - this.options = { - updateOn: 'default blur click', - debounce: { - default: 2000, - blur: 0, - '*': 1000 - } - }; - - this.updateEvents = function() { - var eventList = this.options.updateOn.split(' '); - eventList.push('*'); - var events = {}; - - for (var i = 0; i < eventList.length; i++) { - events[eventList[i]] = this.options.debounce[eventList[i]]; - } - - this.events = events; - }; - - this.updateOptions = function() { - var options = angular.extend(this.options, { - updateOn: Object.keys(this.events).join(' ').replace('*', ''), - debounce: this.events - }); - - this.form.input.$overrideModelOptions(options); - }; - - // Initialize the event form - this.updateEvents(); - } - }); - - -
    - Input: -
    - Model: {{$ctrl.name}} -
    - - -
    -
    - updateOn
    - - - - - - - - - - - -
    OptionDebounce value
    {{key}}
    - -
    - -
    -
    -
    - * - * - * ## Model updates and validation - * - * The default behaviour in `ngModel` is that the model value is set to `undefined` when the - * validation determines that the value is invalid. By setting the `allowInvalid` property to true, - * the model will still be updated even if the value is invalid. - * - * - * ## Connecting to the scope - * - * By setting the `getterSetter` property to true you are telling ngModel that the `ngModel` expression - * on the scope refers to a "getter/setter" function rather than the value itself. - * - * The following example shows how to bind to getter/setters: - * - * - * - *
    - *
    - * - *
    - *
    user.name = 
    - *
    - *
    - * - * angular.module('getterSetterExample', []) - * .controller('ExampleController', ['$scope', function($scope) { - * var _name = 'Brian'; - * $scope.user = { - * name: function(newName) { - * return angular.isDefined(newName) ? (_name = newName) : _name; - * } - * }; - * }]); - * - *
    - * - * - * ## Programmatically changing options - * - * The `ngModelOptions` expression is only evaluated once when the directive is linked; it is not - * watched for changes. However, it is possible to override the options on a single - * {@link ngModel.NgModelController} instance with - * {@link ngModel.NgModelController#$overrideModelOptions `NgModelController#$overrideModelOptions()`}. - * See also the example for - * {@link ngModelOptions#default-events-extra-triggers-and-catch-all-debounce-values - * Default events, extra triggers, and catch-all debounce values}. - * - * - * ## Specifying timezones - * - * You can specify the timezone that date/time input directives expect by providing its name in the - * `timezone` property. - * - * - * ## Formatting the value of `time` and `datetime-local` - * - * With the options `timeSecondsFormat` and `timeStripZeroSeconds` it is possible to adjust the value - * that is displayed in the control. Note that browsers may apply their own formatting - * in the user interface. - * - - - - - - angular.module('timeExample', []) - .component('timeExample', { - templateUrl: 'timeExample.html', - controller: function() { - this.time = new Date(1970, 0, 1, 14, 57, 0); - - this.options = { - timeSecondsFormat: 'ss', - timeStripZeroSeconds: true - }; - - this.optionChange = function() { - this.timeForm.timeFormatted.$overrideModelOptions(this.options); - this.time = new Date(this.time); - }; - } - }); - - -
    - Default: -
    - With options: - -
    - - Options:
    - timeSecondsFormat: - -
    - timeStripZeroSeconds: - -
    -
    - *
    - * - * @param {Object} ngModelOptions options to apply to {@link ngModel} directives on this element and - * and its descendents. - * - * **General options**: - * - * - `updateOn`: string specifying which event should the input be bound to. You can set several - * events using an space delimited list. There is a special event called `default` that - * matches the default events belonging to the control. These are the events that are bound to - * the control, and when fired, update the `$viewValue` via `$setViewValue`. - * - * `ngModelOptions` considers every event that is not listed in `updateOn` a "default" event, - * since different control types use different default events. - * - * See also the section {@link ngModelOptions#triggering-and-debouncing-model-updates - * Triggering and debouncing model updates}. - * - * - `debounce`: integer value which contains the debounce model update value in milliseconds. A - * value of 0 triggers an immediate update. If an object is supplied instead, you can specify a - * custom value for each event. For example: - * ``` - * ng-model-options="{ - * updateOn: 'default blur', - * debounce: { 'default': 500, 'blur': 0 } - * }" - * ``` - * You can use the `*` key to specify a debounce value that applies to all events that are not - * specifically listed. In the following example, `mouseup` would have a debounce delay of 1000: - * ``` - * ng-model-options="{ - * updateOn: 'default blur mouseup', - * debounce: { 'default': 500, 'blur': 0, '*': 1000 } - * }" - * ``` - * - `allowInvalid`: boolean value which indicates that the model can be set with values that did - * not validate correctly instead of the default behavior of setting the model to undefined. - * - `getterSetter`: boolean value which determines whether or not to treat functions bound to - * `ngModel` as getters/setters. - * - * - * **Input-type specific options**: - * - * - `timezone`: Defines the timezone to be used to read/write the `Date` instance in the model for - * ``, ``, ... . It understands UTC/GMT and the - * continental US time zone abbreviations, but for general use, use a time zone offset, for - * example, `'+0430'` (4 hours, 30 minutes east of the Greenwich meridian) - * If not specified, the timezone of the browser will be used. - * Note that changing the timezone will have no effect on the current date, and is only applied after - * the next input / model change. - * - * - `timeSecondsFormat`: Defines if the `time` and `datetime-local` types should show seconds and - * milliseconds. The option follows the format string of {@link date date filter}. - * By default, the options is `undefined` which is equal to `'ss.sss'` (seconds and milliseconds). - * The other options are `'ss'` (strips milliseconds), and `''` (empty string), which strips both - * seconds and milliseconds. - * Note that browsers that support `time` and `datetime-local` require the hour and minutes - * part of the time string, and may show the value differently in the user interface. - * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. - * - * - `timeStripZeroSeconds`: Defines if the `time` and `datetime-local` types should strip the - * seconds and milliseconds from the formatted value if they are zero. This option is applied - * after `timeSecondsFormat`. - * This option can be used to make the formatting consistent over different browsers, as some - * browsers with support for `time` will natively hide the milliseconds and - * seconds if they are zero, but others won't, and browsers that don't implement these input - * types will always show the full string. - * {@link ngModelOptions#formatting-the-value-of-time-and-datetime-local- See the example}. - * - */ -var ngModelOptionsDirective = function() { - NgModelOptionsController.$inject = ['$attrs', '$scope']; - function NgModelOptionsController($attrs, $scope) { - this.$$attrs = $attrs; - this.$$scope = $scope; - } - NgModelOptionsController.prototype = { - $onInit: function() { - var parentOptions = this.parentCtrl ? this.parentCtrl.$options : defaultModelOptions; - var modelOptionsDefinition = this.$$scope.$eval(this.$$attrs.ngModelOptions); - - this.$options = parentOptions.createChild(modelOptionsDefinition); - } - }; - - return { - restrict: 'A', - // ngModelOptions needs to run before ngModel and input directives - priority: 10, - require: {parentCtrl: '?^^ngModelOptions'}, - bindToController: true, - controller: NgModelOptionsController - }; -}; - - -// shallow copy over values from `src` that are not already specified on `dst` -function defaults(dst, src) { - forEach(src, function(value, key) { - if (!isDefined(dst[key])) { - dst[key] = value; - } - }); -} - -/** - * @ngdoc directive - * @name ngNonBindable - * @restrict AC - * @priority 1000 - * @element ANY - * - * @description - * The `ngNonBindable` directive tells AngularJS not to compile or bind the contents of the current - * DOM element, including directives on the element itself that have a lower priority than - * `ngNonBindable`. This is useful if the element contains what appears to be AngularJS directives - * and bindings but which should be ignored by AngularJS. This could be the case if you have a site - * that displays snippets of code, for instance. - * - * @example - * In this example there are two locations where a simple interpolation binding (`{{}}`) is present, - * but the one wrapped in `ngNonBindable` is left alone. - * - - -
    Normal: {{1 + 2}}
    -
    Ignored: {{1 + 2}}
    -
    - - it('should check ng-non-bindable', function() { - expect(element(by.binding('1 + 2')).getText()).toContain('3'); - expect(element.all(by.css('div')).last().getText()).toMatch(/1 \+ 2/); - }); - -
    - */ -var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); - -/* exported ngOptionsDirective */ - -/* global jqLiteRemove */ - -var ngOptionsMinErr = minErr('ngOptions'); - -/** - * @ngdoc directive - * @name ngOptions - * @restrict A - * - * @description - * - * The `ngOptions` attribute can be used to dynamically generate a list of `` - * DOM element. - * * `disable`: The result of this expression will be used to disable the rendered `

    A4#LUp;Kkyn^o_4>0Duw$>Fp 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 RvakRE002ovPDHLkV1irJd2Ijy literal 0 HcmV?d00001 diff --git a/Patent2Net/media/graph-recipes/app/assets/doc/pixeldeluxe_halo100.png b/Patent2Net/media/graph-recipes/app/assets/doc/pixeldeluxe_halo100.png new file mode 100644 index 0000000000000000000000000000000000000000..65c3903b791579642432dab8374c355076c139ad GIT binary patch literal 115304 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 E2ktAxUH||9 literal 0 HcmV?d00001 diff --git a/Patent2Net/media/graph-recipes/app/assets/doc/voronoi_nosize_illimited.png b/Patent2Net/media/graph-recipes/app/assets/doc/voronoi_nosize_illimited.png new file mode 100644 index 0000000000000000000000000000000000000000..5aa8570095301cd663ef541e23a609f6213d4345 GIT binary patch literal 46144 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