From 93a5d0d86f9fe9b1f2bb6bf4010c3aa4738fcaa9 Mon Sep 17 00:00:00 2001
From: Orest Bida
+
+
+
+
+
+## Table of Contents
+
+- [**Key features**](#features)
+- [**Installation**](#installation)
+- [**Configuration options & API**](#configuration-options)
+- [**Configuration examples**](#configuration-examples)
+ - How to embed youtube video
+ - How to embed dailymotion video
+ - How to embed vimeo video
+ - How to embed twitch channel/chat
+- [**License**](#license)
+
+## Features
+- Lightweight
+- Complies with **GDPR**
+- **Multilanguage** support
+- Automatic/custom thumbnail [support *](#note)
+- Allows to integrate any service which uses iframes
+- Improves website **performance**:
+ - no `
+ + ```html +
+ ... + + + + + + ``` + ++ + ```javascript + // Example with youtube embed + manager.run({ + currLang: 'en', + services : { + youtube : { + embedUrl: 'https://www.youtube-nocookie.com/embed/{data-id}', + thumbnailUrl: 'https://i3.ytimg.com/vi/{data-id}/hqdefault.jpg', + iframe : { + allow : 'accelerometer; encrypted-media; gyroscope; picture-in-picture; fullscreen;', + }, + cookie : { + name : 'cc_youtube' + }, + languages : { + en : { + notice: 'This content is hosted by a third party. By showing the external content you accept the terms and conditions of youtube.com.', + loadBtn: 'Load video', + loadAllBtn: 'Don\'t ask again' + } + } + } + } + }); + ``` +
++ + ```javascript + // Example with youtube embed + manager.run({ + currLang: 'en', + services : { + dailymotion : { + embedUrl: 'https://www.dailymotion.com/embed/video/{data-id}', + + // Use dailymotion api to obtain thumbnail + thumbnailUrl: function(id, callback){ + + var url = "https://api.dailymotion.com/video/" + id + "?fields=thumbnail_large_url"; + var xhttp = new XMLHttpRequest(); + + xhttp.onreadystatechange = function() { + if (this.readyState == 4 && this.status == 200) { + var src = JSON.parse(this.response).thumbnail_large_url; + callback(src); + } + }; + + xhttp.open("GET", url, true); + xhttp.send(); + }, + iframe : { + allow : 'accelerometer; encrypted-media; gyroscope; picture-in-picture; fullscreen;', + }, + cookie : { + name : 'cc_dailymotion' + }, + languages : { + 'en' : { + notice: 'This content is hosted by a third party. By showing the external content you accept the terms and conditions of dailymotion.com.', + loadBtn: 'Load video', + loadAllBtn: 'Don\'t ask again' + + } + } + } + } + }); + ``` +
+(#6lu3(Fp=PZE|du!^fHYuqz z#LXP)uwzW!#FThcs80+AZYiNlh|XH!8aUxn6)s67r95+StL0h>E)$#+DxKJ>uzH9z z(NR)z5%5*XPJz_Mo6L_L+-Q_Qq5FN+66x(oGQX_kX#!--iee(n@gUb6P?N*kx(&ls zW~@SJCfcP30YanML?4;~7nX(~_Hh=9PM}1nhAhQ5fJC>5v|6s2=T-bBN=m=5@Lbyz zV*%mR(m9w&j$|six}6gsz@=Q$4-g|^O6?>p&&9za!_UZ%hoV<>9;B8PC8teU)*g5$ zmF1_7QX!h<>GnsPo`0{)Op?f&u^Z^I@rNTy4Kxd*Le{S53WOrmz`&j5- 4?fbrNJ z&p_8+tCB&wT0an}G)S&j-NW;UGK!G!@kXDH(ulw|TN3kWc$cn8I>r#;wxbzuL?zwU zFFB#8W%Ijq1hW(7NR3)WEp&Hyz#>9~lT&tUR&tt|6lbVbFK#zaKD4kd4HC5kNAI!F zLM2bLtlju9Y}bzn2`%b2QS)COs2HeFy{t&7V9D&~kQCbR7)wL`_{VgVY+clxVZ>-* z>5ca`YS-?Sn
_$NM|`Bs9xgLH{C;9-zPt*YH v~X?l#b^88bgH z-|hLBfSylc0T=|PFqJ~U8oiI;<8x`Dm)yWo7oObKD~mstEhIZTkJ!|4^zOp+@o(Gi zqWWXrJUGK|(0KTVI4&^* zu^Xu{l;6`Fzgu^Npo@gh B|Uq#3llr+1?>|7aTj2A8spp3_rmyd|6rjR#>Vqz6GF&i|c zhNYO*$;#zvLX`*2V*~Q8n%ezZ)%2;}*dfPEI@Sm6q0LLJuu?Ch#zkOb!xfuOi=w<> zSF2f|qMI?4zq!>eTKG#L_?Dnm!Mg0J3~Ad!c&DX7igl&wFsNu;9Y7galRs>Puu?-d zSthxBcll|m{Ct%b5rtH?jy 7aV^ z4WOAfD_5~e3ycg~H9H|W>DpksaD6o56Xr)&QbtKOQk$W`;c0u! w3pN^e4g!@$gh zFj&!644JsK%GsG3r4| Qh3 `cIv>+Vn>sfU zsPtx6icb3l7h;gQq%4;p$w;x3=er 5I@P$eCdFOv`t zTtEXv15ZbMl{Y~@BPBvy+5u^=O}&IyCNCH#x=S~<{9aFDGyP4}KDEBIE|V~JZ001$ zPD n%O*qSxWC^G8UT=HdiVutt ziE)z LoL%wHR<7(u zbmb%XR?X%0(JC%NdWOOM#UnMxr>x!3#S9vYNx{3?kI2r~IiKi2?GFsN5&ygKFiCv+ zyZQB+pNll9qHo`vw)Peex6?olK`K9ZyO?LG$f-?z+!|ZEQ3yE%I{yD1 lqds(W@)wPD#Ql+Q8uI#RNCe5neAvi%e(eh@>L!?tFjTG{G41KxTIq*&dj%o%}* zx~H}e2Mv!H-9?rn?{4WMdyO5;2PsP$^bM2fdF>K9zMkv5u~E_!a7^^#gRhwu$@Ht8 zswGnbPN7q9&2;|$2h73yI}5Up>DwwR9CCTNc2Zjt!D31m3v)>S&djIhn-!W`n~jvq z(-e^#>p*LwW#k y!k=44eIvCnd PgYb ztE#KVM8~c|#4OzZnHA4?2Fm{xOa*W<@c+bIXX4a>d^t`X&WC97FO?O)R0R6v{}-Tk zDa`as_seuC3{b;Q1=#v-T)$(sehj!dFFp2tY@U$xIU|$D%hDAzHkKAQR^=uqo5i~Q z*D;O)qR5rq_I#~_R5)KMU}dSek_;(}E#V|5yvoexay)fdep7jAev3_0UlER-;N)eQ zJDQ+oFw5w3wfzT+%reM%^5-1vml-gLT-n`h)}_iNJefcz7Kn7>+<2bRXU1H4Cgm|E z$}4Z`DXndt25j=Q*0FVR-)U)8Wh|b#xx`UzPzq9#O}Q)DF=k;~Me7V}S >l#a}V1>pKoxOPS z+ocIPoNL!|I0=cIjHgdI8PookfLNHp5(%Xs1(A@IAr?Xy8OEYDVBK^vl(fQZTQy`` z?KSr5KNQzI E9+W+k7zD>7}t*a|skr%d 6kAD2?6o-w*|-l7BFFB{zZ&B9J~P>woeE}oDmXQjq-i =7RL)S<(`Hs)<^DAH9J!mx(u&cfEJit`J1W{J{S%BlCX0pVh)3fx^@hT5Xy@w@UsgGuj_zam` z?F+iVHulTF$kFvf>rXCUq?p^-yrQ+Gc}3$~u#KHiRX>!eWdBqv!8UeKRrGtNDl;Bx z$%AW-k8EChVxW7V$Fb5(;#za{EL}{T%H5LMR<^pK)ZSirTuEmQtQv*jBZe^pr;=kB zGelN`ZOk|ZzmW@T8!g6kHn%yQ$Nt;+cd@+@!t1$Zc%`ViW}_s?;#c7JafX^))jYQR z_fc%@wscGrkG(&HzdwQ{Uf$Ef(kLuiKUP#4fklE7IdRpQ?4dKOhGd%c>$bN1RI%oz zbkoE(M#m~WEU9g|mxoZ*)ov~A?yTJYS+QQMkO;UciEuq^DL87g6imYlx%p$NA!T18 zX@C4wT`OLgrpyx0Z&RsSuM-@bc*GqqJjfVzH;lPgw6x^QRTYvHhi`NEysS(Cj|1uC z?zt@ln+fHZ#p>-Hac?e_x-Xvpw3w!rHPz2)gnUz^il 72`iEv6mXW_@pOx(i6NxJ}tmYPI9pm z+#>wrf)EIoFZRafsoyCVd11>{5WlAHLiRM5-Yf{8Ngd9|< YUL`AjFSUzLolN(NT3@U9S+37Y2MP0~3yJSVG*Oguq_sj4S1W;-i+fTR}Jm~@2| zR+&*q6k@TeB7U|~nHJU4lOJ9LQgT(S62k@J7uqN+R#{b1w-{QWv$3yHA{A6>HG)d1 zNL)1{t_E*%Lu+4WM{9q5No6Tft!3t p21Q3vCh>ZM5qOtwxzPt7l4<*dX@;ZAFQt#8~k~3rcX0*_m#Tgyo3M zT9ZU5mVxQH_J#JC|1Aby{KWt66DzK7h8Hl;L7QhYpf(L`u1@ZQk@($x5vRnWjn#FL z#+C*%IbW}}n9sIm3)Wk~i`>){4fEOk!Tr{}q(LGTl ;(Y5cXik&VO(sCI()&{2OyC18!bq#mdQ;_YZ0f)-AZYH z V9Ul5uFk1oy z2QP<7wV9T8FtF-gz@u|-B3`{3TejMOpMJxpMdy>1_F-*(`q9KrN;-Vu8^iHV?dSs> z-}~ |9Sai9 z5(L&_AwuYhz)ViI(bV0ko*dsig-X9hpO319ow8n;r&W2r9M8Z?j@rOFZ-!(B_-}i~ zOirpE2BzJM^||+*Px6Pkv6jNP`}dAb!2JqAyU1Q+x5|qc-Lc-?MeqlaBsE%84jP`O z$k8^hvA(pg&@rEvuO=HxFtL`X*V0-wZe%?*SC(uYY8^_pL4;a?D3+_lsu}8*rjnwT zHkB@cC+_0%l4g7qe_WM@V6zoa<1#9ehGypoB(lR2d2S{ n)?avh1OlqEM#3&--7LTpa@wAcgf~4b~Bt-@iyX%5i z(y0SWWoa=PkW^7VD8l aeL=D^ R!#4N>^8;w71BSt363c`^$fKOGSh z>b5FOm7WZjIh$_cW2FrL>Pj`>L)gy1i`d=Jv|qAcJ5dCE8r?EvUtfq~;x&C>uU~9Y zoR}09BMz1{MEIxrM?g@8nyQ9`x@E=1gUG&ic^GKv&hKtFgtOPToD`khqS|sybZiT) zzg_u1Gylt4xk9(Y&zlz%D)N=4s?|9lkjWD!g>WC%R-)$waP{4SR+%BB{Hz!Zp13h0 zk(VIhc&UQIv=c=W yZ#9D)S6bWRiAGzadNpI6k{SJ&1m#C-n$ z(*N!ML-t#HjU5K=$7RPvv4avB>)l)%7y h;o7aAlHA zRWhWuN@XhRkg{ZiwY#}xcMHtn#Au(gO*iqZo7kypz6hD`aoZj_zH85^!YlHFo<$Qg z1Q~^wMtaX ;?Ab7*Z9t%`4IO<(Vub5AL8}O#; lQ#*Aj&;3CS< zEnS>Xco5h(jvL!#g&WtcIy+P=Nn+>9$&XbqvVQ2yD!V9=rM}WzA0bHGn5tChI+%iq zNgKq #+`2lC`C6)9Y)Fi@-vdT#vUo9=|3{;^!Ipev!9W-E;i3VY=EzYe{t} zFFL=*R^Z_}d|kM0C(kpRpUf>+!RMY`Ua1n%`x^zvY ouaa&KLzmZpm{WxcQAPMf@O z+XUw)s<2kg!UOJ5+yWlAmIIq8p-LjtmTkFN g7uRAlR^JXJ{Zu0CX%N(+tHWt(v{2!%nOxBsEVJic2;C({hi(gM5T$V zuoOh44z-8k^V+Bf=ya(}XQ?xpT`BA&C%kS`Q`JWfM_goXj==F7@cIzlxg@?!ktIg6 z=cC!;Y>C`WECX>B5p!$+>AUx7C#8A) #qCg_48{pq~uQvaBxH=Cl{q6ft^)xip1$SxpqF;8dH8SoWF42o5W;ln`FW zN+iEkh%Co6$mvNRCYAQ$nwdGZ_?a}c_sopXL|kT{(jjiBY#VO-NC zgVyQaV|Ee7);rHy!QmQfRwuT;fzu$>N}ua_AJ t#?moI!9#ko-6 zRNi0RqAadTH9vrRk&V>XKN=X<91h7n=AyB`Rn{oA7=WH`aj=0DY!>r)eNAOyy$cF{ z$rFTW-rNk-3>FAQW0#SuCyPS3X^ <@{LKzqO%X7X9zP&3?-F(0{XMlE2o3pf#rf)V-6=rs+Bf!8n 90EtBt}*P!;c@GlJQylWi#Uzp24{LYXuO8OJgq`+XpPi zUQ@nvqm *XqHRtG zaXH_&$dI{Dh%1kZfqhz89M9MKNWyTrcJdUh%n%KXIj*J$X+!2m9U}h;a)6mO%4zNA z5Js *@x7glTq+w<7*uJ ~M&k?HNFdRWvbU8OG zh9}J_!}I4z|F(qQM9r`*0$TlsEUlbFsM#XhPN?L@{vGB(zuaJ_kEb=sNt^sPr4A67 z$}S?u^b9rUpZlFw*)(65F43R(Ye;4O!N{_ez?OY#y47q~ubjFk7ug |s>JOLfscbo7ctW%yTSJ)(P~}M_ z^VBmsG}*_DU6nP&s`?RA>Dbsn$e-PzflKoX?_0h~}9N+^j_h_u>B) zaM>I Ts9C>URr-Xh^oGSZjW@2$!Jo_x!vx- z7vQ4zQB JpiVkejN| zWDOka+FthnJ(3p@ECKI^f&o}pIo4uY_@SC=2N}*19~yfV!KW!fU0?fl5hAyi5AFqY zT~q2vPR}FBW0qG;FLaZKClyNj+*U*GnpH0Wfwz^8TJvNgKg>?$p9W|H9>u0pFzHqv zihp`N)%A;JP@SpvYr|$J&8x5lap( zCXd0Hf__~(c%2MNrsbFGVZdEA97}qPIN(iGZnO``xU0oI!a!N95N{?qK}&4?DLq7w z9A%*c8EsIRi9xM>^bf<)Z*$D3-x{P1a+zC8IU3wb1F}(wpBr99PuyXMNaj%m_$fSi zS@HluHif|4wZmXPFuEaJ^UYzgXDf!KcYQ~_zBK9;lnBCqppQb37xTl0fW~|ib~ $ImCci6W$?t= znF0wrlP|ql-LdiaXdKj!V_1h=?BFF=!S7SBgHWZw;`~FEjSd1wD?VYkLtff@J7A*_ zWq!MzZOeMR>#}5tz7#K~1X+e>)5_i{)#*-Jn~5%^jGf3%UKHOC`dW9Q*8qE5zB#vC ztI<@9VEJa&^#jH5vwgp~;N{`Alqc4cLZ%SrHoKIilhaFG)(ClJI|%q0xx)0{2$g&A zs=b8Y0b_`6h~Q4cT4BpiB6^%sgh%olM1!5+&eV~EHf&MbmSLktu8B5@Abx5`)C5Y3 zGv(msWt_;B^-G%D>XuXj 6$ >lXiW`x>T0ah$`^^c#Y(dLn&hL=VO;4v=5hq zPM?8JtxuBER4B|b3EPT(BGN}~B>uTt>_7JvQrK_F68eic4tMdz!YOM5d6Xn^lO008ArX(JwS)72Pt6(FbPwDiRwW>cnBQ$1EfeTFp*j?BR_#O zI`sphmm<4C Voa7PDX}BwSg6Ge9-heL*k?FqjVAW4VfL9WXMk{OS@W5nVM-Rv zek9*ZvzhyH@4AH#pK4rzF)uNC4j+mxy_3?;SeC|yR`X @g4!G;GeENw6 zff9ql1#p(-$@^{!j`Nxde@z TnwLO6we1~O&ij{J*V z$M0wAEhxbPUjizQkvYN2Ft;`Xf@PdY;7za^FhC-hmN%Th$IB|Gy*^ avUGOSk zfAo0^-3Vtt8-K 75k7S<~
;-fk_;mO46T${E1F1?Q-$!fp|TYVmsu*Nlcl>#51Q9}J!6*s(7K zEAEJN)TRx6$#&~Aun!KLYd=AH;puUE^nEw)v9DQd^GNV60PiD5NU*D5l?B32+D_pR z;EgN}00;mffO%ltn9!0dAkgqpMT%T}tppA(D4B`TlpOagN*=qHNbZN(pgVaXB m`8bo!Osu^mSPSi;_1Whfzkdrq3$XIoF~qqk;3ZOR0aTO{ z`z*e#vAr3e-ft|iL1(F-!2vwEY@adJM5CQf_jHMb(%@5of=Arv%!^EHRF2Epi zS}DXd$Qys=BJljm4x8Ej+vBKZelc6WudK1nd=K;*h=8E5z+5Li4uiEuz4gXB8|`r3 zSv!@mTEym}Qs-Q7)g_l*@vAa7U31+o<^HnR9k<+8;dg(Ur%I)2wQAU{SEoU}Mon5Y zYt`mAQ*>z8sauyrHkhi%G}HazrNagg(J&oOSO5E*TW-5W6pszsYiIA^=!C)I@C0HX zeC&}kkjNA&jm}`Q*c>jePwrME5Q@YSsZ6d=s?-{7&pfYDZ!iKN1S2R0i^CIg>`6u< zQ>ZjLgURacKQH_k;&6F XJ_Br67Q}+ADX)~NK$989Y=a{kPnpdA!78 1}*igE|XgBXGLjg>5zV=D}meRZTFM10)pTZDqYMpHDo>R&4jL0S-pfF zTdaR--72L5sxG4FAz1jn)_9>65r+($m&vH9)-#!q2;)!{B!Oy`B0+4Z)U4K>V5Nc* z^D4P&iRoNq6Tvhz&1L2#!dhlzvucT@i)bseY{1^xcA6PEapqBsotc)n5rw)SXLnN= z;)30^rnynNyOj90BKp X6_7 literal 0 HcmV?d00001 diff --git a/demo/assets/fonts/basier-square-semibold.woff2 b/demo/assets/fonts/basier-square-semibold.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..4f905d34404055e519a70a0639e786512a79a28f GIT binary patch literal 16224 zcmV-mKcB#NPew8T0RR9106$;=4*&oF0KbF)06zf$0RR9100000000000000000000 z0000#Mn+Uk92zzo#&8^j8U|nhhCUGp3W51VfxaCJhA;pDHUcCAj9dgD1&L+{l1Uq* zohO)Xy0cRhlsCZKtZ(g0Q>kFbUc~Ky5=nY^!j1WGJCKUX@U6lB|DTZDkRdV;x>l|J zL&VipWFB2{Irzj?@jh{5_Z2#nvCyGTYMU$=4$q5vsl)^^K};}HkL?@}uMCqrcu(@Y zyMiVvP2(E)(tFJ#ICTCu&)snReVm664L_n1l}4t1LJjoi?*A)CVam~5wumHtRViih z7h-~lf|#JJD?@23eG%YJ4>2l3P6%p0_PckOdS<8$kxC_bqtyRH5z!{D$^HFAr~P|_ zo!NDgf|s S=jYa&yy5sLQpQO*x(6aIV2RX<5eqiDHbQ6zB5fm*N{W4g ziefcsl6pp+(IBc@IcD+?|M!0GbKex29;`s2cr6qzm4X#~Qu_K7u?P=fz?)`W3^vvc zKrFM5urcwHuTq0~Jy?wp(QwJqXD6_gz?rtJ<;E5!2ks8E=Wx@~6*`uX5vI)lt>_rb zT_J^hQ&Lv>CCv+?o`-iALS$jfEWk8)acOdEJC6ULyYv|gCjWeYvHNys7lIE|qya@u zM2#1a7r}XU1axbyEwq+UNOjLAa>7Svc&efn05FVA$!gxt*IhT}3V|5#`*N05lC_)s zl7fugY7>qoQGh)YU*sI^m)jz-W$PHi|FdP5cB!Wqj9OzK!7OCn3nFPLy5sCppdjl0 zzq+LAn%2zpjPx`k$uMiu${>xNO!7T46z}`t(IADkb2CZzCeMA)bT|^O3iX4ZR z5oZp<;CT4wzNYV j4@v^>Ij?Z2g{u6~^(Jqi+CrYz0z<_KF1F18}0fU4> z|8XhbyoqP+3Fg4kR7(GNJz$w&KpMt^R;n?F`j6ZA83us8Xo0>!{^zu$6
8>k;P(qMSf{3_Kvi$?CImVnk%8LwRGycmfS65Ej0F_h_(CzjAhk8^9xv0!zSX1Z| z7!bgNyYmMC?)-Rh34pt&fAk j>8ryrcpBe5mm{pp&_|}qI?s6_Hvfe1Vqv9~#Q0NYMWf7qg z+P?EmhpIpQU`no}io A?rA- zOZWRdS=5(){ke8j&tv4c6HYqqs_SmL?XLSqjhpn)V^2++jrn2{fQV4Wg{-KWZkSf= zhY_aqHAXK3J;>85zm~>M$^o_jw%TU99krc+U3S}NzXJ|B 6JI$`QX!k`UP+cz#RbhfCs=!z$?IOzxiNws;+2mM%P_{`B>)5cdAbF9Wvix^L3f8 z+k8D)+GJx82jrOJc_KLJw5zVW>9)J>8#QjyLytW*ZPt9_|GrN#KL8P-j0;&&HQg|+ z*rVWA3_ru9 S002;yWup#AWMwzYa2@8S z&SIP|#w7%!>!9{3*UoA@b!X{c@7^w3UPT*cqx$mH;qp#(>`gK3mN~;oMv@<;uvM_s zXEn3QtZ6n!M_ux1d|t#TBsKKM=xV#4I<4EwK7YU7d>3j+<>HqpNt$#Saug_3q}Z+W zX9DVKpt0s!YO9?NW|?EIdFESdo%J@@$PV`B-~Y@Due{+cU;5g&zW1XqzWL>kr3Qmq z{9>tGsn+U^W{b_?!x1P*2)=A1DR0^38Vnrw4^zt|;InJtYiCU9@WfTm-LO9uM~vJL zl&emEEb QirT4Yf4s80s4qe?q2HMs(;spVjkgyz9GryZLs?v@tc+l@f~nJOd`{ zdu|Dk!mO9W?tn(8WO@_u${mfVIBq|cZl Ry+t(4xn^Bv T$)Ih8^? z5@;1L|B*mBlU1okDOL^ur5yQP)NN9F{>r>fS9K~vRn3Eo5!9W3&A|pMk{289vAD`! zbhaG1^5pNdmp8>!(@ZzROtZ}1W Lnr@J`9BO%NHtwuG9GUB5yN(`n+`2 zS>B448zvu2-kD@Js@@qy1s>)_-}gz}6q v%sG~w9t~S8bfvcNF_0-2SglP1OYN9EondZ0_2bh*9S|PMWYKN*lnhxkXV%nTG z?6x0wG|e1y3U>zXBDza(m(ksZy9;+8?jhV`n5Qt$;a JeTo2#)~vjw28bXiZM~1sTG)Bv6+>c zS-F{27_YXm>YAv5ky@KtTT^RqY8{Q&`3JrEHDHJi>;s$&Q!GRPs-p3z48hz?tfbzm zKI73K+|GvZH1VvOQPRBS8KaR}L)g@fG8)Zb+IQJv7m9u6fWzGW$|EKwO`b+`m7%Uf z-3;oun3!09CMG5(HawH3@%WN(`x>`zar+*(A45G3Qjg_9kVhVQ iQESy;qt(i|L(#=Xdr&{dn1>N!wbsyJdLzt9wkgdkxFfSg{RNmxwWDsf zHw`rk!6eVS7Fufc7n*;-_B!Zjvn{sTX1g7B+HH@$_Sx^KV~#uFq*Kng=#tB>y6&di z?z-=x$DVrbrPto{ws*bnLm&Ip=YICpccp)X8K%RsJw800$>JDHR=d-~3k8igE}mea z1S(Y8uF4M8YSgMzk4_tqB@6?sagD+NN!QK%`254*`6&Gzcd2 30DBcPh4}2kGR20I5G+}d~?#YwNA3O z+)3G1d@`9#CX-1Lw?$9-h9^K0hgU!+YOND zQ7V{wln_QArG@E7$sv!wUn>brdMPHoG?QM2NiWN!mt)eaUO=M| C6@{}8m&jbjTQ|13yhznn3BpUr^3pss=hrn*HKSLJKec1 z *O6yt;8;%b~vGXNIrbdNB2D z;q}LU@81ieF(c;163q_tc0PZ)A15R%Dj`j}wY0K!S5sTpk&{Cg&t19o;F* ObO-1{lV{R54 zjRDpHU~d4dFF;cO)(T)L0P6~{)&R=^SUA8s0c<(IBmm|Dm<@o211tfcwE+DLpw9tz z0%(a^$x79@HB9NNE7aK9{7siopF zpbN*_Vy9%g9hSLVi=riZ;bK=jRPLE~G*})*>xEIYSrUKVZ|e&`3G$oo!u=Tlvniko zgVW5&s7!M(CwwF;B1g6+Y7A=&Db&W~HP{ScEg>Kc&g}sLvLqUD-;F+&F?{CAqenbK z@&DJ9=S1nh6x&0&Z_Vdl{HCgQp!$pW7NW}gas>UMGo3TamoB+Qh?Oi`selHUUd=ae zO0~CuidaVh!V>R2h|D)X4=m(+vpT}hHr8+>3^2~PYN~8U4OLfPZQHAZY(avB@XOXL zWTrv!HAfaC5d*4#Pyk_|4GbYlY56D>q46OUmWe30U=x0d&;iI!s^Y}$g>dOP10~Yy z@1$P H4R_URd)ECFZ1XF}{T?0T#&Rv&AOwZ*z&J+T68kF!QkUte8cs2^_h=l`#0 zu*E^As_k}Oblq?nS2}gZC%1wj@QDB%tBPHR)y876##kGyE3G!kZvy+f=z?LrLPEBG z#ig>P%q5$-iMi&vxLM(B@ND2Lca}5DoMp_CX5D77Gh;KcGs5ZQX~Su~#}y0*^yzwO zLxY(`^>C4`3A&DP7l?fRHPPq{CX3DC;^tBJZ!bfI2^S$!lxS6W`NW7-m0w&g_6uL8 zTs76zP*bh=Ry25P)cEazTWb^NPVS_$F1mtz?s8_EYpGQ>*lLSycGw>M9=g{axCg~T zJ>T@OqmF;?IN_9&&N=J63uPFpho1VDWt7bZ>tCUf`c-U}HGt(xD%IO3$jbj&z$Rx* z)*XQ705E5K*}9oxx|OM?Q9_BOmR3^9P6LjHE3d8PlncN&Mwe20GSkd6)qHa-w8&x$ zEVlx%$~x<<^<%cgG$h~r@;4?{0r>!&e;oi<0OA=C7l5`8fT2GC07gKByL+GFC`^)? z5J87nQzr&hutByIX`d|35Kp8TXwnH`idO( C}55GKp8TINRBQIAY0YeoQ}Dn?Qi z(hw`_uq`7&=8&5N2~%}4ixdZ8_9W X@d0 zbON`}kcSB19oGM3;k5)o?r<_Nh`@1VPK%Wjpet{$Z8+R{UYl fc z;Ft<0kMLCMlrK|No!t|Yz^$sSYVKn@j0V684qIW38gVf<)mr=*$4hWM9Bq6DJP3$s z-YRE=VuXideZdLK>?!9=8!|T+v;hYcC`jl6AXpOq;e}3@15OYEfJN!fh+31@a{yjB zU!}y#stQ#4BE4}d(xmkqK&vc`y&rYQK9Z&!KwZ*fkJuXvS(Dat0QV ? RKI-ky(gbz1*GhhYcSjsvtG zkoLf+He=hd5D+Uj)FO8(uF@nc)T}6AR|X7hH5_y{atUO$XZ^oJ1PU#>*2!YvZJt%^ zkK~jY=^T|b-RdPTbg7HKpZODKDh=~=*lTCt*k;u@mufT{S%=&Hk!mcv%AD9lK(uj_ zpsfTe52$dMOJDMW` {1RhLG z>9hHgi90P4!$N)k(*pwz-8_E#K4NpsqXZQ@B6l%g*b}6^s^@n*5F85qzqO(ux}HyT z-gT)$Y7qRG`N5eM=F$n{!=BWA|2S;f<9!pGbFs-_KPq-0oVN{_*CqKE-D=!=n~Ql% zqIm3kToVQy+CF(p(jSM%6gZjuneYRcOIRGkzR{O*l-0#twj$mAi^K?ng@uHm!A7XI z&7OcogIhwmnEY{^%!+?GgNOD+XN)}Fo%HBHfsLH&vgsXn7u-RfBDNDLP5de=@+uw9 zplSMPsUF7}kfnQ)J6Oz DIpjQYm7MI|9owu3 zIAP>-GfsqZOrikWc(X6CyO5AWcG;r ;K|*4hSo zF~H}NXpuWB<986}q#{c}N n4U?nE7DQC2HVTJ2UwQ *GWEg#sPeOl^4 QX^?ud)Y^V%KC@z+Y6F5&q`(6i0=>?s-`b>e#4VK-PMv%p@l;W_!dEeGDv zg-Nxv 9>%z1>Hbd VV^!{Nh*<=(P#1?L#-Q5s&3`T#zw zEMkAg_6}#%shz0N bs~wCn^<{4U09J3JK(BVzS(`?U`Ji4G+1;~blmdfc^L zxgKO68MBqBv_pZ!%P3nu!FkO0hINz^vF&)(E|aEm14ikytw moizhhOVA&(O@O8X6o_i)I$sfDl2Nrt&-p?iX=u4~`nYKaM zL&YfAM9q2_RX`TOv6{eZkRHGP?gA~{E{4zJ)}w!ch1m_1uY4w$a#lWVmj0o|bzc g0FtLDXasT 3A_f)pOFEEy?TV8V#!N$-IyDwF%8eg zKRc+k7u6&*tK4>|2awLO?%=n`4cDu=*l$rA!|GP!y+ 0ENPhniS@o;!NAIls_v8=rcN+AbX? zf&>xHHObL%K!j2t*En2G`vA3GOM9dvow>w_GY4u;1*2lC3>zU>SRy#Dcp2}+<)a%8 zSYt$x$tVvZ6EcnJN6 t%&*xrnTJX&u{%(Bg=}IXhkk5KBEtrzqV)oNK# W#7dNLiz0Z-r|T+5M^bGr_=V`8R@iYr(R zTq%N1`ltes9+lYG)o6t4%Km90*558$7#ji9^MY>1xr{7iOPn 0%S{22tOfffT5zV06>hR#p)#2Hi=qB8{+h<%Ty2=$D5?pDssUPoTBvyoB9Zjxn> zOii9dHAS2U;&rGcc}2B)7~hu wJBAG|jP+Q_%0r+|mmOT<%6! zZH&$+B~YCw3VMFE%MAnvGEPGhM(qwT1u>dHC95IvIB7Fn({P&Yl^O~r5MLxSskcN+ z%!*_RD88^Tgstv5@=&W!aYI;JCY)5nLnDb`d3tE!2nd)D=q;EHR40EL8@WWRM< @!`C!IdIcKI zYGzw8jyShkPZJR%6|`2%(n8a$AU+f%;|6+|=hvLB-E^LUc>DreU15QEaNUD7s&FMK zV7;&z5oZ8hCNDR@YSoR13j$3F0Q~JPBhh=O*i^ba1dB4N8_f9rEhwpxvvepsk)ti! zrt*Cxt&d722p-LM+c_N+a#@)}p6ap@&%nbmV8Du=bc*SRrghpXdx|hjdrO71 zH4A^GoMW^cH SF*X zUiirnY8r&bw=~ort;vR!6S_X6RovwUGhBDF8#O?M+L!DIzk+T&z;)1EVWOLqOwVKM zKt>xx6ssa>9PNi_W gh*=|*6QUSZaBqYhB)CT1yFi>uGjcVkTiQjTzX#RYYpzB zDT;Re3I%^}>K4^gkla!8%$8Dy?rm{4KtLv;9mh@JxU_YXlIq;qlqifNujWGkciW(o z(yoH|l+g~h%U*679On@-u=iVsEilxCn|F9i(JAh8;CtUEcrOaw7kRS?X?VenBHYqW zWar$}_O{RxPPJLyad+e_5?IhoqQM4?DpDEL!N`wPd84yyNrT~H9qqU~!HshoqGc5= zg&l}SI*P_b=kw~*%Jci;sYo+dSS ^*ic8%i*9kyR*u(x_1AZ9h57lWoTptrp0M@ zNox`Pqdz1q>DH)#v CxdzOdd #z0M5 z%>cu@rn#fwTnh4VAPI3L43!Q&CBqz6-BF#NKaxK>fbsTfWdC?$D{_!PW%y?VKOg5u z$ruf^06N`I#9kJH7tq{}kB?ZeL)wq2g)SRdtE;NFY* 0!u zcQoS3W4^)ER=Wri&0yJP*=APBLq7s1L(Vr)K2v#x_$w^{cu`<3j9!&v7e=)S$ _E51uyNh?7_%H zELvHdhp5$s @6q< zE2raMyeY>Ed~B@j%AAX0^Rwe4@i@E-&&gRtAa-;>3t)*!qu?lR(WNV=JaEUYtiO0{ zO5f-ZZ*H{3CK@Fv1CrwOL~&VkK$6f9`Vs=&`1nnKz~iz~T#@F{uJhbXuA3Ad*M-0Y zlR)0& <$BOk0HVwIVFT~U&HYiqnX6u5j z)z_q?uU57TzyK2|i$_=;Xd{nuB1>XCh{+6&B$2%Ic3Pu3XF@o^8IO1A&{%MhQoo~q z5@|&*Sv+N<=2P;|e~GS_&Uf#GU_msKGDDt8odNSNujLNGu08gK0fZ-osvFHnUw>Q? zuQzyOB@QbW4BkqKxxB#SGhC~KM~1OVZ&`c{+!p_v7L^)x@u)OOntY;t{QQBflClu9 zwpe(UN$14{@+Mz;>)(3>g*?m;w5^$CXh6CT)tg#c6BHU0yseh&ALv(;&D7`m8P;#G z{^Me|+Sv4ulS4azgMD8IkexQQ>h=272-%2laPf}}*i9eWEJzZuBvf-4W+fA3#F!DA z4q81l*%H{QaiZ73*TU4_9wcE7u)^4qrUPsVOMIZfpYBgzo?OWfU{FIuvcv?DEX2!? ze6~V4!H?!k0UjTQKI|0;1%mwzd`YNS8GkiADlt7FJ~2HCI6fbGE(_VaNxJE12$ x`g-}3m7*(41Bm1hq3oGZ8baeRwl_%iXxk4T28tc4 zcQ|gFrHv)Mo>qg0@*z3+9}_#&8(NCug;+nZej$Gmo}CQ}25dbyh9RwL&Mq59Yh$zy z0 5*Y`IK!BW;|7SAm%#V7n(I=A#EA)b@3y=8Q6z9jOm2R^DbU{anI?{LKh422$x z6!FWD3Rh+wiQEO!OIIHc%tz$*)P0e~J1J2p1 m z`w$S?)iQw8ME-=bpN+Y~IxSv}v<`HozJlOXCo;o?lfL{%e(w_8v($_{@PlIkNXOnq z2=>X>qjn-qo$Fxhx+dgrV~!eG!Vwsl1EqqCFaoG`zd!UYD(7J?=qS!pYYjp2)#^fk zP4|b$+=n?)??IbW9&$;RJ|aW%@|HoMT=G2jIrv7Fq*fvIq$)6uVTpKD?-*8OnvTJg zrRjoh-j?K=TN&ZZz|01?gpanLFw>6VdT1X691PzM4=1x0N;RP!o-a;r$dtNLakR2@ zH=G}tg7Zx)e=faT{ecc9tE5IIB~S^p%$Tf1G{4Nn);z^J#oU8Zh7Qe20ADd-ZZsTK znwi`n3AMvR&C-ReNoa@fT0wU8OL6t9#QCM+e8GB5I+0Ffyxz>fduJtYrr@dZj$xPs zE=-FeCF=jv_wiGzTsx;s@S}8RaB{FECsEABr`r2cEOU}`z?yfFpFaU+kxit9OS_dH zw8Mu=k{dFzaWq%DIJ8IaIDNjSo0r>g(Y1~4hfbHDK9h0gv?mFSlrEI6h4v&NH$uW? zm)b;$?A!^?;HrOhWi@ K&aAHix+tI7!v=e&*zvf1o{Es>*wZE<*KY`&DNJ E4d)9~98GnGVFpI>0Q@W;%Eu%t`9Kqnz&OXoov?)hP?)$>5sF=k zRkSd>zQ%ZvxoW3&0V#>i7giteF4jF}te?Hwkj_`7t9aAA7>{p&v@n1F0LBk?O3=1~ zZMiAAkBvSWxP$MQ{;|u;0>aw+7ZG`85lky8M}T`*@gh>fN`}njp85?1*~vvn(P9@n z34-QYr0rMJ52QM(4@UJ>BL}{>{YGkIk3z75&M(w5D3etqE9R;ZpT}5myDe!+4=$w~ zOkTu70GiBTfO2TBCD+U{ipJow>2226|Bw6sx^)|!%VyA`EX}x OW$ z<&cjn3sP>_te-l!-ZhYHW61DuvU@dkSKDdV>K}V=4{$T9en&lOuv(~@EBYrF XV`ENv2atUX(&7B8g5T zdgi*gZ;Z2kZ*S{?x3>M;*e`*_!6xMB20`S30~-%V9G1$Z0}%sm%^i`FQyY*&&Fdhz zSd$i!R){Y*F#Qq|7X?^Jif_%0FYB7$@5?u|px6iU?5jLzv4WtXK6YYp)I(CXHN%0; zbNp_m^L;z-?oTtcvN^ve#oo>e91D?3rNi0T(roZO6xAdM6G lvcniOQohHr% zcWXN`&ePac+tzLUq&mxifhQ4th|Y6<0SZ4%$$BEKX*19!Xz(a(Mz=D$dVzD>FPOV MVHwY$nL-;Skr2(4n-pbU@_3IXObnS$)O+$B+^u85tgo%#uE=NBf4-n`3 z=gR|K)k0M_q8;=hKV-AveZ=Kq(hRU(j7Ap9$dJhZZ_x%)J!0w*{lLMe@48084GzU2 z0(reqj>I?OVW*>7s;RCqa}{oft#;ji+gE6t2CT}8GW_&k+=f`RMJp64q!qiMSCKg^ z!08zD)}G)IM%ZlcfcLPs!+SXFJD3oEa3D7?>F)C*G*=^E286OQmp!&p^yYyDDU()} z?h_bXsy&dD5_;~7L{i9JUMYx=x@ho{bi*DMt5F1G(GCxGKG^vy*hnaiphMJB@-L-L zz {nFIZw(W!X7b8p% zqgeU$04#Nl=4-}h;%X1PleIlzBX@(Tew~x+4czilrO0i$DT#UEO!oW_qSiN6HPJ)A z^`5Ie$S#x^I^cWncFK7L$ITFSCZ3@Nr>Fw6<57igqA=ub#(rfx4_Tz#Prielr_;zL z4V(r11d#@E^9Bwk#OoFDep(D$TbGP-P( qPSfy#@1_@=Xk#%Fls>DdCPLUzAT zjD`KvXXge#V!2<;#M?S6*yEMNvnzs7a?Ry8Btj<6OV>dZD&BFk*FbNpSVIrbbkz0Y z7|TdTNcky?INJ?gH0(gj^2;csY}vYKFfus=u#7d96WLvm&Wp7;feUcgGg!^+@E#)q z;Ky*s;9eH4`+JbU1JlrN-E+&6Oy+oU$m*>#2{SG$J-x^rJ$)`2XqtM6h*a6Iz9-zh z*f@j`;pMe8tEeG+<3-JcSR1pJ?av(5(o(I`8m;zKJ{|!H;sG*vu^Xp~2DtPLj=U5L zU|9w1F6$p~bNbAQ?97KJS9%7H>dM#CDZQSVFm|n60lR u=)c7)%n0XV6h{7kJLw>w3To$J6N|1K iNQWGpy?1lBls#$txy(#yJ2QW>DV}lH7Be;_P{r^U*mizrHae3n~?7 zSyh8lt5q>oW36s4D;Aa0i9>(E;#W5Gr(PgO;)dW*Jc5kYFbc#{NyO=U(%fuvaK1e0 zdu*w+tKx~gu2N*(ctY*?{oJioS~mu5q!ZJGHgQ#HN>B>EG-8_e)pS0u!A4-w%p9+r zb(xQa9rqRtvh$pP$LIu!*k~;5ZXzuH5lccsX}*>s6OFV5@(W58he3Rk6dK-!s3Cx; zpHIzZa`39A`7xe&Yrd)j*^w5J&a5n?&{ua&Z$hE9yql^-O)PXhX|K-FwEW8RlZWMa z0FAU{DLFHRW2H30>_|vJC2=BJiyzBcbw=-38(3&L4lwl=YyUP>9#nLjhiL3BMZn7E zzl;ZLbz>h|OUf#QIP8s@1QhGUxqwDc5_^;5369B*OYSDyU6!1aowsb;VvAQjt!c}( z1w2)hdv7SEy9K%7OYtc|DY-N9V6H`xg8O#`J(y#mjR<6fbV5DVRY*9WgTmBYgz&jq zPo|YfqKoKY Cmm3jUvZ4?6{!OD5bkbqfBwSQ!v&Zw-o z`O+rVEWiuxO6eCCD;l;euOHg-HK9+~CN>J9K-vQ%R9#9a9!sNgl>ISpZEBqwMB#Vu z6$GizU}nC0tn{$|Ugl%+Zymq651d?}=dDtZZ?Vls9JC@(LF(FLn4@*QJnOG;{UghK zXfRmW1+-k&7})hHiVy$ReHN77++as3t_@YZGaa*jlI+&klSq=6R=_r$ZW59T@S{j< zfDx$_l5~;iEr!XZ_MoqADVn45+y{^I3jm$*pqoyhRd)T`_M?~O V&kWj%6hQ@4M!2?fQvt)P>J&Y zuqbUaokY(p3+bd4ma+&wh%BH@s&efdGb_RwR&?v~uXuUU<}Uvsm&POGTU*DoEj(Xo zew|?+Wml}MIWC_YH;k4G `+Ac+y1#HZIG&kbf=FVrkb~=z$Y)nVU zW!pHMJ34dS?CZf9acLMq=48qBB&FP2oP2EEg#piYkwnY@+86&3ODTwtVstbN%6#*Y zsS%axtqwN3pFH;5aWEf>*Q(;tH(bkk3@A0T_45@+%Be_D;<`$R^murz0k=Wpo$5MM zJKf}N2U8E$IkyDSsYp_e8_w!5b}-wsEQ!z1LY`K8rU$2cxihT;JCn@7h*B1HFx-3% zaFvx1C~gqDTfm@%EIVOifwT8$==y@yV<1Hm94c_Ni6kO^n{CX18o`lA3~-phsv=fe zBa1zl`INTqxr-i*Qc9-qYvtC1;uGZ}P2UUJ0n@f#e-c*Y??@+J2NnNqBZ>jlls-OI zr3+>V>~t8}mZ!Si(h>~uM8HA{w)Tl0;Z%irw~RWOb1Y`HvMi3Gu`!gYs8K UoQ2bi8slsv`kYg8DQH{FIix)?7{@x7Zgb_G%+-CegjSG>7 z#jmr?X8}^v(gQ$GV?^icWVq@C_~%{BLCe MF5?0Akw&_*a=BQ0taFFf(HT)&+*! z1g~-k2mtY&31qpT`9LzkwWG6Fmu-ax+D??`h`?Bfw~gT6wYW+3*yuG4b;4p_?w5+z z24*%jam9t3>dOd(-o4)sPOWTR?55HGrgU2I7T#Xi%}VcNJGZp8kub;B8%2hhIXJ*2 z;+-t=kIS-q`7P@kAYfljWKDpG!TX ~e2OfA(w!Nkb&!(0x7+1lkDqr!0wp3~>RXH7d e{$!9XC`4*{j8oU|wTJ7ccHF$^2 zV}XPH 3azI^1A~e z8!jcf NgHJOBI#!>0d$MIK%>X$3RIv5@@GYUz1fgWo}Na^nF7>66{TE0ZPq zd}Z~q9N)-JJRiPe^YcPUUgN$KoClitiA_$j#|T+DEUB(i8!V~bq8cErk+P~ItU*#+ zFa{EpV!$s4^_XsuaCx?UpXPLr#^bVt4r@HZkO=rKU7KE=3EyBPJ8x#L@sdRT;|syt zR%=Z#!y@$)+#4#!NzNU{)$JlZ)od|g@@uz4smAd3&SftlYk9kYPcN0#h&d58i%Rwh zZNc$8euwklo@|D&!m2A;U8?6gt`Rp#iL(6N*Fh2WR8k%0lEjql)=0fZ{l+YP{887q zJ~akbm a90UxkD_irRCq9&K0As;fmWNLUbNCM4AP`JPVuwY`<&Lnw~R2qlOpFM@>N zGH>~SGTW8B>JpF}SitoAK7$AOJtXnme&$0Mfi+O07eNM8MjK@eGvnD|gch`D1c)ej z4mJRzO*?4;jB~3*@M-&K@A+sqRz|a+CCr(A-%Yui;GcBzgUo9otDp)R#j%>KabMvw z0x^Z0KvbcGyg;v0x0&X%(Rm<|E|OFZ=l2sW4W*+)XL}3$MQg)&)k9fzdm)36gD`Sa za|zjqM37m`4I_gCu>tRDL6CRI900&_57`T?Pt3Ro-_H}1`L5qLH6Qw-& -kbdTjcf9FG7zz^uFrVg-UOu45{uEx>;5vB9@m>)A_B>K={q%Db;v9=3OOhEh7c4 zhzdWr+ENpGP2CX#fhz$500AHbjQezIT@qmH@P1v=G95?<(t~v5%i45`;7HP`yg8Fj z6I{h~I&VYL8Tgn(GL3cVY{oc8a*Pkt1 `o<$o99ZqNq>Tw&C1X)q7uIHC7+2Gdh`vv|IJfSnp !9%EDnD|8`&KiP=KaFT> zEsHJI=rj-Qm~AOdR>?0(&W(WGNV_%KPheHoR7OLWM6jjiz&t8tV1pqvzw{oQa26J} zZ1Pj5;7(m(7tVAgBvCJcs+5LEQgt!`6gC&_i;5!L8#HWw-xspT$eNJuGWrD33TcVE z^l#A-^9Q&qfQUr1?Ja}tHosV|Tlm5(i_Evt-V|V75T;um8WmV*PRrrFFtEu!zxv{v z76;vR+acX_w?q&3^>oKQk3I0vBVX#}xhI}FthXQ3c;$tc`uN(n=IW=f{stOgkSzuq zYKUQm8)<}5M*GSb BL#8a*q-1jB%9C%a0) tDHPyV|F6`?I4^c*IdYigB-M|kH(<`FrgjdPD-aC3x0<|BTC$F_f0Yla@ zxnjp>+J)w)ms;lpXZJBUrDT;=7hAT7z`7W6)-o!%Z2@XwXKmFC1Vj@<4xuY`$Qv}( z(dm?82X-a3ybe<-Y7xaCXm)C;$6`mPLvN+iSMHsq+bQhmOfB`{I=ExA{SyRPx0#Fw z5#u(+% yhb7-&(E$GwJl0*Qn9fy;?zcu{oLlraegk&O|NW**D3CmHjD4Yzn_k~WK!1g z(BZ3yj|0`erxcHZyz-j{y{&fM=%l&_wpBwL)NyYbbZ1(5HRXC3gdfs1Q%^PbH=fVe z(4X+m3E)m~Vq|s<>&cTAb~dB8e9~7)VhB#qI?Yxv*v1D0;>&|tIIf?g8=9dThVfuL z8c)Wv@nXED%mX#Gs1^4{=h}ZkSXI=!TKTb?J<$V();NW?dVVYW;GIjRTgw8Ixv= @IMJ|+Jz)l$o2dZ9qKG2_1hb6^|zAB81g8)Z?s?I;KQ%F}1s(ul~%^`?FN>$&2 KZdEHT?r;G_%@36T literal 0 HcmV?d00001 diff --git a/demo/assets/iframemanager_logo.svg b/demo/assets/iframemanager_logo.svg new file mode 100644 index 0000000..8871420 --- /dev/null +++ b/demo/assets/iframemanager_logo.svg @@ -0,0 +1,11 @@ + diff --git a/demo/index.html b/demo/index.html new file mode 100644 index 0000000..a1c672e --- /dev/null +++ b/demo/index.html @@ -0,0 +1,85 @@ + + + + +
+Test youtube videos cookie blocker + + + + + + + +++ + + + \ No newline at end of file diff --git a/dist/iframemanager.css b/dist/iframemanager.css new file mode 100644 index 0000000..63e7a80 --- /dev/null +++ b/dist/iframemanager.css @@ -0,0 +1 @@ +div[data-service] *,div[data-service] :after,div[data-service] :before{-webkit-box-sizing:border-box;box-sizing:border-box;float:none;font-style:inherit;font-variant:normal;font-weight:inherit;font-family:inherit;line-height:1.2;font-size:1em;margin:0;padding:0;text-transform:none;letter-spacing:unset;color:inherit;background:0 0;border:none;box-shadow:none;text-decoration:none;text-align:left}div[data-service] .c-ld{bottom:2em;right:2.5em;opacity:0;visibility:hidden;transform:translateY(10px);transition:opacity .3s ease,visibility .3s ease,transform .3s ease}div[data-service] .c-ld,div[data-service] .c-ld:after{position:absolute;z-index:1;border-radius:100%;width:20px;height:20px}div[data-service] .c-ld::after{content:'';border:4px solid #fff;border-top:4px solid transparent;animation:spin 1s linear infinite}div[data-service].c-h-n .c-ld{opacity:1;visibility:visible;transform:translateY(0)}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}div[data-service]{display:inline-block;max-width:100%;min-height:150px;min-width:300px;font-family:inherit;position:relative;background-color:#0b1016}div[data-service] button,div[data-service] h1,div[data-service] h2,div[data-service] h3,div[data-service] input,div[data-service] label{transition:none;animation:none}div[data-service]::before{padding-top:56.25%;display:block;content:""}div[data-autoscale]{height:auto;width:100%}div[data-service] .c-nt{color:#fff;max-width:100%;height:100%;width:100%;transition:opacity .3s ease,visibility .3s ease;position:absolute;top:0;left:0;bottom:0;right:0;z-index:2}div[data-service] .c-bg{position:absolute;top:0;right:0;bottom:0;left:0;opacity:.5;z-index:1;transition:opacity .3s ease,visibility .3s ease,transform .3s ease}div[data-service] .c-bg::before{content:'';position:absolute;top:0;left:0;right:0;bottom:0;z-index:1;transition:opacity .3s ease,visibility .3s ease;background:#1e3861;background:linear-gradient(14deg,rgb(12 15 23 / 95%) 10%,rgb(0 0 0 / 51%) 100%,rgba(68,77,125,.1082983535210959) 0);background:-moz-linear-gradient(14deg,#1e3861 0,rgba(206,220,233,.1181022750897234) 100%);background:-webkit-linear-gradient(14deg,#1e3861 0,rgba(206,220,233,.1181022750897234) 100%);background:linear-gradient(14deg,#1e3861 0,rgba(206,220,233,.1181022750897234) 100%)}div[data-service] .c-bg-i{background-size:cover;background-position:center;background-repeat:no-repeat;position:absolute;top:0;left:0;right:0;bottom:0;opacity:0;transition:opacity .5s ease,transform .5s ease}div[data-service] .c-bg-i.loaded{opacity:1}div[data-service] .c-tl{display:block;margin-bottom:10px;font-size:1.2em;font-weight:700;text-align:center}div[data-service].c-h-n .c-bg{opacity:1;transform:scale(1)}div[data-service].c-h-n .c-nt{opacity:0;visibility:hidden}div[data-service] .c-n-c{display:table;height:100%;width:100%;position:relative;z-index:1;margin:0;font-size:.9em;transition:background-color .3s ease,opacity .3s ease}div[data-service] .c-n-t{display:block;font-size:.95em;position:relative;z-index:1;line-height:1.4em;color:#fff;max-width:420px;margin:0 auto;margin-bottom:20px}div[data-service] .c-n-a,div[data-service] .c-n-t{text-align:center}div[data-service] .c-t-cn{display:table-cell;vertical-align:middle;padding:0 12px;transition:opacity .3s ease,transform .3s ease,visibility .3s ease}div[data-service] .c-n-c .c-l-b,div[data-service] .c-n-c .c-la-b{display:inline-block;position:relative;padding:1em;vertical-align:middle;background:rgba(0,102,219,.84);border:none;border-radius:.25em;font-size:.85em;padding-left:2.8em;color:#fff;margin:0 auto;font-weight:700;cursor:pointer;transition:opacity .3s ease,transform .3s cubic-bezier(.25,1,.5,1),visibility .3s ease,box-shadow .3s ease,background-color .3s ease;box-shadow:rgba(0,0,0,.19) 0 4px 12px}div[data-service] .c-n-c .c-l-b::before{content:'';display:block;position:absolute;top:12px;left:1.1em;z-index:2;height:0;border-left:12px solid #fff;border-top:7.5px solid transparent;border-bottom:7.5px solid transparent}div[data-service] .c-n-c .c-la-b{margin-left:1em;padding:1em;background:rgba(225,239,255,.8);color:#0d1f34}div[data-service] .c-n-c .c-la-b:hover{background:rgba(225,239,255,.95)}div[data-service] .c-n-c .c-l-b:hover{background:rgba(9,80,161,.89)}div[data-service] .c-n-c .c-la-b:active{transition:none;background:rgba(225,239,255,.6)}div[data-service] .c-n-c .c-l-b:active{transition:none;box-shadow:0 0 0 4px rgba(24,104,250,.24)}div[data-service].c-h-n .c-t-cn{opacity:0;visibility:hidden;transform:translateY(-10px)}div[data-service] iframe{position:absolute;top:0;left:0;right:0;bottom:0;height:100%;border:none;max-width:100%;width:100%;background:#000;display:block;visibility:hidden;opacity:0;z-index:1;transition:opacity .5s ease}div[data-service].c-h-b iframe{opacity:1;visibility:visible;transform:scale(1);transition-delay:.1s}div[data-service] .c-n-t a{color:#5fb3fb;text-decoration:none;border-bottom:1px solid #5fb3fb}div[data-service] .c-n-t a:hover{border-color:transparent} \ No newline at end of file diff --git a/dist/iframemanager.js b/dist/iframemanager.js new file mode 100644 index 0000000..b7cc7bf --- /dev/null +++ b/dist/iframemanager.js @@ -0,0 +1,17 @@ +/* + iframemanager v1.0 + Author Orest Bida + Released under the MIT License +*/ +(function(){var e={o:{},S:[],T:[],u:null,i:null,v:null,l:null,W:function(a){return{D:a.dataset.id,I:a.dataset.title,m:a.dataset.thumbnail,ba:a.dataset.params,K:a.hasAttribute("data-thumbnailpreload"),j:a,J:null,s:!1,R:!1,A:!0}},X:function(a,b){var c=this.o[a];a=c.length;if("IntersectionObserver"in window)for(var d=new IntersectionObserver(function(g){g.forEach(function(k){k.isIntersecting&&(e.O(b,c[k.target.dataset.index]),d.unobserve(k.target))})}),f=0;f -1){ + _acceptService(service_name, this.services[service_name]); + } + } + + function _acceptService(service_name, service){ + if(!module._getCookie(service['cookie']['name'])){ + module._setCookie(service['cookie']); + } + module._hideAllNotices(service_name, service); + } + }, + + /** + * 1. set cookie + * 2. hide all notices + * 3. how iframes (relative to the specified service) + * @param {String} service_name + */ + rejectService : function(service_name){ + if(service_name === 'all'){ + this.iframeObserver = null; + var length = this.serviceNames.length; + for(var i=0; iThis is a test page
+
+Demo with youtube & dailymotion config.
+
+
+ +Simple example
+
+++ +
+
+Example with autoscale width (fill width of parent container)
+
+++
+
+Example with custom thumbnail + params (video starts muted at 21s)
+
+++
+
+Daily motion video
+
+++ +
+
+Twitch channel embed
+
+ +-1){ + _rejectService(service_name, this.services[service_name]); + } + } + + function _rejectService(service_name, service){ + if(module._getCookie(service['cookie']['name'])){ + module._eraseCookie(service['cookie']); + } + module._showAllNotices(service_name, service); + } + }, + + /** + * Set image as background + * @param {String} url + * @param {Object} video + */ + _loadThumbnail: function(url, video){ + + // Set custom thumbnail if provided + if(typeof video.thumbnail === 'string'){ + video.thumbnailPreload && this._thumbnailPreload(video.thumbnail); + video.thumbnail !== "" && _loadBackgroundImage(video.thumbnail); + }else{ + + if(typeof url === "function"){ + + url(video._id, function(src){ + module._preconnect(src); + video.thumbnailPreload && this._thumbnailPreload(src); + _loadBackgroundImage(src); + }); + + }else if(typeof url === "string"){ + var src = url.replace('{data-id}', video._id); + this._preconnect(src); + video.thumbnailPreload && this._thumbnailPreload(src); + _loadBackgroundImage(src); + } + } + + function _loadBackgroundImage(src){ + video.backgroundDiv.style.backgroundImage = "url('"+src+"')"; + + var img = new Image(); + img.onload = function(){ + video.backgroundDiv.classList.add('loaded'); + } + + img.src = src; + } + }, + + /** + * Create iframe and append it into the specified div + * @param {Object} video + * @param {Object} service + */ + _createIframe: function(video, service) { + + // Create iframe only if doesn't alredy have one + if(video.hasIframe) return; + + video.iframe = this._createNode('iframe'); + var iframeParams = video.params || (service['iframe'] && service['iframe']['params']); + + // Replace data-id with valid resource id + var src = service['embedUrl'].replace('{data-id}', video._id); + + video.iframe['loading'] = 'lazy'; + video._title && (video.iframe.title = video._title); + + // Add allow attribute to iframe + if(service['iframe'] && service['iframe']['allow']){ + video.iframe.allow = service['iframe']['allow']; + } + + // Add parameters to src + if(iframeParams){ + if (iframeParams.substring(0, 3) === "ap:"){ + src += iframeParams.substring(3); + }else{ + src += "?" + iframeParams + } + } + + video.iframe.src = encodeURI(src); + + // When iframe is loaded => hide background image + video.iframe.onload = function(){ + video.div.classList.add('c-h-b'); + video.iframe.onload = undefined; + service['iframe'] && typeof service['iframe']['onload'] === 'function' && service['iframe']['onload'](video._id, this); + } + + video.hasIframe = true; + video.div.appendChild(video.iframe); + }, + + /** + * Remove iframe HTMLElement from div + * @param {Object} video + */ + _removeIframe: function(video){ + video.iframe.parentNode.removeChild(video.iframe); + video.hasIframe = false; + }, + + /** + * Remove necessary classes to hide notice + * @param {Object} video + */ + _hideNotice : function(video){ + if(video.showNotice){ + video.div.classList.add('c-h-n'); + video.showNotice = false; + } + }, + + /** + * Add necessary classes to show notice + * @param {Object} video + */ + _showNotice : function(video){ + if(!video.showNotice){ + video.div.classList.remove('c-h-n', 'c-h-b'); + video.showNotice = true; + } + }, + + /** + * Get cookie by name + * @param {String} a cookie name + * @returns {String} cookie value + */ + _getCookie : function(a) { + return (a = document.cookie.match("(^|;)\\s*" + a + "\\s*=\\s*([^;]+)")) ? a.pop() : ""; + }, + + /** + * Set cookie based on given object + * @param {Object} cookie + */ + _setCookie : function(cookie) { + + var date = new Date(); + var path = cookie['path'] || "/"; + var expiration = cookie['expiration'] || 182; + var sameSite = cookie['sameSite'] || "Lax"; + var domain = cookie['domain'] || location.hostname; + + date.setTime(date.getTime() + (1000 * ( expiration * 24 * 60 * 60))); + var expires = " expires=" + date.toUTCString(); + + var cookieStr = cookie.name + "=1;" + expires + "; Path=" + path + ";"; + cookieStr += " SameSite=" + sameSite + ";"; + + // assures cookie works with localhost (=> don't specify domain if on localhost) + if(domain.indexOf(".") > -1){ + cookieStr += " Domain=" + domain + ";"; + } + + if(location.protocol === "https:") { + cookieStr += " Secure;"; + } + + document.cookie = cookieStr; + }, + + /** + * Delete cookie by name & path + * @param {Array} cookies + * @param {String} custom_path + */ + _eraseCookie : function(cookie) { + var path = cookie['path'] || "/"; + var domain = cookie['domain'] || location.hostname; + var expires = 'Expires=Thu, 01 Jan 1970 00:00:01 GMT;'; + + document.cookie = cookie['name'] +'=; Path='+ path +'; Domain=' + domain + '; ' + expires; + }, + + /** + * Get all prop. keys defined inside object + * @param {Object} obj + */ + _getKeys : function(obj){ + if(typeof obj === "object"){ + var keys = [], i = 0; + for (keys[i++] in obj) {}; + return keys; + } + }, + + /** + * Add link rel="preconnect" + * @param {String} url + */ + _preconnect: function(url){ + var url = url.split("://"); + var protocol = url[0]; + + // if valid protocol + if( + protocol == 'http' || + protocol == 'https' + ){ + var domain = (url[1] && url[1].split("/")[0]) || false; + + // if not current domain + if(domain && domain !== location.hostname){ + if(this.preconnects.indexOf(domain) === -1){ + var l = this._createNode('link'); + l.rel = 'preconnect'; + l.href = protocol + "://" + domain; + document.head.appendChild(l); + this.preconnects.push(domain); + } + } + } + }, + + /** + * Add link rel="preload" + * @param {String} url + */ + _thumbnailPreload : function(url){ + if(url && this.preloads.indexOf(url) === -1){ + var l = this._createNode('link'); + l.rel = 'preload'; + l.as = 'image'; + l.href = url; + document.head.appendChild(l); + this.preloads.push(url); + } + }, + + /** + * Create and return HTMLElement based on specified type + * @param {String} type + * @returns {HTMLElement} + */ + _createNode : function(type){ + return document.createElement(type); + }, + + /** + * Create all notices relative to the specified service + * @param {String} service_name + * @param {Object} service + * @param {Boolean} hidden + */ + _createAllNotices : function(service_name, service, hidden){ + + // get number of iframes of current service + var iframes = this.iframes[service_name]; + var n_iframes = iframes.length; + + // for each iframe + for(var i=0; i create it + if(!videos[i].showNotice){ + if(videos[i].hasIframe){ + module._removeIframe(videos[i]); + } + module._showNotice(videos[index]); + } + })(i); + } + }, + + /** + * Validate language (make sure it exists) + * @param {String} lang + * @param {Object} all_languages + * @returns {String} language + */ + _getValidatedLanguage : function(lang, all_languages){ + if(all_languages.hasOwnProperty(lang)){ + return lang; + }else if(this._getKeys(all_languages).length > 0){ + if(all_languages.hasOwnProperty(this.currLang)){ + return this.currLang ; + }else{ + return this._getKeys(all_languages)[0]; + } + } + }, + + /** + * Get current client's browser language + * @returns {String} browser language + */ + _getBrowserLang : function(){ + var browser_lang = navigator.language || navigator.browserLanguage; + browser_lang.length > 2 && (browser_lang = browser_lang[0]+browser_lang[1]); + return browser_lang.toLowerCase() + }, + + run : function(_config) { + /** + * Object with all services config. + */ + var services = _config['services']; + this.services = services; + + /** + * Array containing the names of all services + */ + var service_names = this._getKeys(services); + this.serviceNames = service_names; + + /** + * Number of services + */ + var n_services = service_names.length; + + // if there are no services => don't do anything + if(n_services === 0){ + return; + } + + // Set curr lang + this.currLang = _config['currLang']; + var languages = services[service_names[0]]['languages']; + + if(_config['autoLang'] === true){ + this.currLang = this._getValidatedLanguage(this._getBrowserLang(), languages); + }else{ + if(typeof _config['currLang'] === "string"){ + this.currLang = this._getValidatedLanguage(_config['currLang'], languages); + } + } + + // for each service + for(var i=0; i go to next service + if(n_iframes === 0){ + continue; + } + + // add each iframe to array of iframes of the current service + for(var j=0; j show notice + if(cookie){ + this._createAllNotices(service_name, curr_service, true); + this._hideAllNotices(service_name, curr_service); + }else{ + this._createAllNotices(service_name, curr_service, false); + } + + this._lazyLoadThumnails(service_name, curr_service['thumbnailUrl']); + } + } + }; + + var fn_name = 'iframemanager'; + + window[fn_name] = function(){ + window[fn_name] = undefined; + return module; + }; + +})(); \ No newline at end of file