From f194f2d53c0fd362b872573a922b1833c9f287cf Mon Sep 17 00:00:00 2001
From: Jeremy Ashkenas
+
+
Change Log
@@ -354,27 +365,6 @@
— when the model changes, the views simply update themselves.
- How is this different than - SproutCore or - Cappuccino? - -
- -- This question is frequently asked, and all three projects apply general - Model-View-Controller - principles to JavaScript applications. However, there isn't much basis - for comparison. SproutCore and Cappuccino provide rich UI widgets, vast - core libraries, and determine the structure of your HTML for you. - Both frameworks measure in the hundreds of kilobytes when packed and - gzipped, and megabytes of JavaScript, CSS, and images when loaded in the browser - — there's a lot of room underneath for libraries of a more moderate scope. - Backbone is a 4 kilobyte include that provides - just the core concepts of models, events, collections, views, controllers, - and persistence. -
-Many of the examples that follow are runnable. Click the play button to execute them. @@ -550,16 +540,16 @@ new Book({ Get the current value of an attribute from the model. For example: note.get("title")
- +
escapemodel.escape(attribute)
Similar to get, but returns the HTML-escaped version
of a model's attribute. If you're interpolating data from the model into
- HTML, using escape to retrieve attributes will prevent
+ HTML, using escape to retrieve attributes will prevent
XSS attacks.
var hacker = new Backbone.Model({
name: "<script>alert('xss')</script>"
@@ -1833,6 +1823,127 @@ var DocumentView = Backbone.View.extend({
+ F.A.Q.
+
+
+ Catalog of Events
+
+ Here's a list of all of the built-in events that Backbone.js can fire.
+ You're also free to trigger your own events on Models and Views as you
+ see fit.
+
+
+
+ Nested Models & Collections
+
+ It's common to nest collections inside of models with Backbone. For example,
+ consider a Mailbox model that contains many Message models.
+ One nice pattern for handling this is have a this.messages collection
+ for each mailbox, enabling the lazy-loading of messages, when the mailbox
+ is first opened ... perhaps with MessageList views listening for
+ "add" and "remove" events.
+
+var Mailbox = Backbone.Model.extend({
+
+ initialize: function() {
+ this.messages = new Messages;
+ this.messages.url = '/mailbox/' + this.id + '/messages';
+ this.messages.bind("refresh", this.updateCounts);
+ },
+
+ ...
+
+});
+
+var Inbox = new Mailbox;
+
+// And then, when the Inbox is opened:
+
+Inbox.messages.fetch();
+
+
+
+ How does Backbone relate to "traditional" MVC?
+
+ Different implementations of the
+ Model-View-Controller
+ pattern tend to disagree about the definition of a controller. If it helps any, in
+ Backbone, the View class can also be thought of as a
+ kind of controller, dispatching events that originate from the UI, with
+ the HTML template serving as the true view. We call it a View because it
+ represents a logical chunk of UI, responsible for the contents of a single
+ DOM element.
+
+ Binding "this"
+
+ Perhaps the single most common JavaScript "gotcha" is the fact that when
+ you pass a function as a callback, it's value for this is lost. With
+ Backbone, when dealing with events and callbacks,
+ you'll often find it useful to rely on
+ _.bind and
+ _.bindAll
+ from Underscore.js. _.bind takes a function and an object to be
+ used as this, any time the function is called in the future.
+ _.bindAll takes an object and a list of method names: each method
+ in the list will be bound to the object, so that it's this may
+ not change. For example, in a View that listens for
+ changes to a collection...
+
+var MessageList = Backbone.View.extend({
+
+ initialize: function() {
+ _.bindAll(this, "addMessage", "removeMessage", "render");
+
+ var messages = this.collection;
+ messages.bind("refresh", this.render);
+ messages.bind("add", this.addMessage);
+ messages.bind("remove", this.removeMessage);
+ }
+
+});
+
+// Later, in the app...
+
+Inbox.messages.add(newMessage);
+
+
+
+
+ How is Backbone different than
+ SproutCore or
+ Cappuccino?
+
+
+ This question is frequently asked, and all three projects apply general
+ Model-View-Controller
+ principles to JavaScript applications. However, there isn't much basis
+ for comparison. SproutCore and Cappuccino provide rich UI widgets, vast
+ core libraries, and determine the structure of your HTML for you.
+ Both frameworks measure in the hundreds of kilobytes when packed and
+ gzipped, and megabytes of JavaScript, CSS, and images when loaded in the browser
+ — there's a lot of room underneath for libraries of a more moderate scope.
+ Backbone is a 4 kilobyte include that provides
+ just the core concepts of models, events, collections, views, controllers,
+ and persistence.
+
@@ -1841,7 +1952,7 @@ var DocumentView = Backbone.View.extend({ jQuery, as a framework for DOM manipulation and Ajax support. Implemented Model#escape, to efficiently handle attributes intended for HTML interpolation. When trying to persist a model, - failed requests will now trigger an "error" event. The + failed requests will now trigger an "error" event. The ubiquitous options argument is now passed as the final argument to all "change" events.
From 06a150627d98de9f7c75a80be41ae3a2928c2f21 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas
+ Loading Bootstrapped Models
+
+ When your app first loads, it's common to have a set of initial models that
+ you know you're going to need, in order to render the page. Instead of
+ firing an extra AJAX request to fetch them,
+ a nicer pattern is to have their data already bootstrapped into the page.
+ You can then use refresh to populate your
+ collections with the initial data. At DocumentCloud, in the
+ ERB template for the
+ workspace, we do something along these lines:
+
+<script> + Accounts.refresh(<%= @accounts.to_json %>); + Projects.refresh(<%= @projects.to_json(:collaborators => true) %>); +</script>
From 0c033312b32198edcf735af32976591a8b1fd42b Mon Sep 17 00:00:00 2001
From: Jeremy Ashkenas BM>}cc6$>WsPHp^`@w%2n|*lS)zW2bKt
z_S)Lg$cbaesTY3C($Ol 3z!NCERo0Ettwr^5mmWQzg<~rNb)Z
zr$Jk(G
zSW2giV7xMf8+w=a`kvfAE{_SAS=yaRf3_<`1mZ38(okgZhS8ad&NaiS6dN#a*_?t!
zX-@xN+F$E5ypn$N9<9B+c*S^jr4yqqCD`^726pKFP9WN`X-zg7l*xsg8AXW%giukA#@|4y?l@bRM
zf-z%|pi*;3V?X#${&*vk&5tcI6XKT_gA%ia=;-Yjd;UcqxNb3)_>rLt(xV~D>^oxo
z;mKg++(>_MRr8*O)iBd`Xh!R|`elKOXbGQv#1sT>$=DBNl0@Hb+^8_K4F#JdOY^jB
z0RQ@K$a;X8{u%@uuRE(n`%C_ql5`dJwtgi*!nBFUcvbXG=F=vRvh#SpbP*G&xbSHS
z7s)t^NnVq4^2ZNismb6iDXb5mGKj$
Cy3q1&i>`p!}+A@FH3AtcW0=60c#%v|mi2A*|>PGUSez?Ssd6
z_<8c6fSL|l6NJOEh#O)t_={Cs^6eG26U0tjKIJlweLy$Rpe?%QAM1?dVK0>C3msIb
zuhWi-SFEU3Kd?SaCNZKz!P4LJUDm&}EaJX#*b{bdXFKekXd`J++~4GA{d`4D05!DU
z$QM@=Rb|O_
kzVQ1^;Z5rHR8z#G`?gddM4v#Rg$3n52B{>&_Oy=R?
zlT6{WO<+k7Itm`e^6cQxVscu6$*fG!E-WZpE`z!2*t5+A
naVTNm>^aS#!C@!Y7
ztdiz-(|OymQC(Gy>EE2`>6
aS_bR?xzaNc91k3Kck<`dI;^QKzlx~O>->WG&MP`|m>63 lZ^_s8uLM@VJ6*Xq$~)tw2D-UCN#1;>wMQ&LdMzP
kYj6bW3 zUV0`VI+u1knP8nfCa#RGxQu0o%lEj**m2sG@qAf2y0f-gTpY8-#jnzd5ml``i-Q;v1^XvDX zv7nRr^_S0Ov-tA<^3KgD@A zUse}KZgTmZGqB+TNN{nA^!QG1^|}TJTpX0S$KUBuc29l*!$taGaH-F=uAc33b^5rp z !r9Fy^$j-G-^!QG1ubz7A?enG{{pgLs)!0KfJ 14Ow7cu6nugT~Nm&%j{yXT^hyh!vouwU=>V?Irm09Ws#K zxA*e7o^p`dvE-JU@rm@1>$Y o2J<79Oq+H`AY_X?Zx%S)Iqijnr z`nUA*JxM #|*ZDbm$ic>Uv$p `F7zSyFW>$PPev`m6; ioMyS^9o`eI0E^>vxtVXYGbYGP4Tgjc|&K7;Q^K z1!r^1e)f%Q3gJStv(D1gZuuV_EKVI{{zN+XKDMR&k?m|~sHgRN==S@(?B{2%43_{U z@;Imv P$j-?Cj6ie0qpsD^8E_5F z C~-jz q2X{BG}cP)*z*fm}#&21<=d{LWQDXnWj=iQH~^WwWU(6u#*3?$<$4!s`( zhon yP{*xJ0oU10K zCtaW@x3*D~TVIb?Kp>5Ejf8~wQ(e}^oaNKeYo#?#E4B5_C>>_ fu4Ee0#T9%>rfRV2rUcePF4WL#c`-aiy?Hw_L^Z)rt65s_gOW*w)p zNx|STLnL8huq&x8%)#mvN?Jk~XEXB{KW7?IF+N?J8=LCN$;m0fH@qK#em-=xHDa); zaaUOcl<+1YGT=M2ZAn%|xfxV880nXgfV)C`L+>rxuc4-@8m)&L)x{OeSUi&eKh60K zr8c4KQ`FSA5s}oNxN!gO_1G=cHngCy87U|zBXQ_(LiB2i3bV*BYb15(NFuy6G`BTy z^yC>VY7hDk8G@h6#L+Dq@ESCYNKdVNjJ2-5UHsclUVbUjDQUv~On3$bqq25TF6s{r z3l^DwBL|M3p}eG$$O*~|Y*`926(!js`)wqB)MzxuN@@*yQbfCJ>nnx*xf2`gLr&%~ zs+&~|8a)^{hl#o-BQ|3lMP>CQ4jf9TyPCY5Q 5{fKVlP-FgKiI-{u_*pE*ko?iC_aSL#EVaYcOB23|v3 zEeDTf;oUEZLGfYK)YYLBe<;YxAuMeW5q_TC+aPpMEyjmWSO^MJ8^w(VMoyTANyvO_ zQJY+@S7-{i+`WQ_9(q@dt !E|*==7_q)o?i;62n+Z^W-5gH~-IrMq_EH(?ofEF6Wgy_$C) ze+Xs5SiH4v#3sj6k$0LeR_|u~t@m=ph$uQPDBH@$4`1hCkpXXG4P}k<38>Ft)w%=3 zBt%kgP;%q1e?ius%^WVV^V=tWPq3kyH=lS!1W^kLH$CPSJ2yV^1mluJx;FbsXNq=y z{toMQ S3R>lqYX2Y&rLNy&^6`x~hh=n&_ zT}kx7RO)J5SaR1rG#=m2mP4i7{Kz8=4$@MTb%2+iUrAVW5QQS$9h?-xsiVi`wO5r$ zDSY~k;^9Ys+0C(Es9!tVKYNFbdvXc#chKU~pTU7f+|p)nC|h7VSLLq8EX zwtl^p+kbZl+g^Tz2ERcBiQpF+63oGUpOIJIK>Hj2BD4Q6u39va_x}C|stul~nrn%g zu>f5|F*9zv3-6k iMFikrrvrAZU%}Abo@DHeb!e}ikXYy|zA*N{; zpRCU!F)56yRtM=}O1^r3HDOb);kGMAcH1Z|Gu5_L@x_PlQ(Rfk=g eKf=W!dlVMOAu=S3f$ G zq)RH5%C5}aY&3QKERFZfLz{W?tqnxR`BP92gJbj@Kb9#k^{5mMVuoMAoZ;@g^Ug*R z`^U=nPAP;gK3Tb*i10|Ztlh|+kN$xpYhGpJzDgoItvKSxk*Y0c@2Mg}{8TikBDn82 zxA4_luh5|jpsnmn48M91xAJZL _ zi?En@GB Q)!&N`UU`Qp%dY0=drxAE9fOyqT==5?G-qw)rB}Zqp?{)~bq(4v zY3y1335`L+c;N0O0x34|(*3{35*UHKsf=UA*D)>KOV)wk_$A!Ec$@%$d-!_uA MeLlPA)hyn2Hm- zC~Aem{ksrJhsYupFn88Ckxh2GVuwnFLgPt`$S{+Kj3B_%gYh#KF>!dJaD3)oGX`@< zCEt9#7ysY@`~ozb%*dmm)j;I%**yB#;{ d_{<)ri(T zmc@%_lbAk^`B#iW lnptw)Z6t?z%9mDYMT@>!yO!j+xAMma9~J@EhlZLK z#>`yI@YHzb+;B7Deij)F_FOu0l~qSm0pIL6%Zk4~$*n7{LTNH%a@b_jDv6iWY_XvB zis0(oRuC@fplipZ$j*ffRqhcC8 W?UgFk wBBcqq!!-Ee9 zaHBDD=x_l#FMnE_+KEXWLR3@)6Xz}_DLRDd*RJ5IdDG=t3kh(}x&1zV_m@W)Gcb}i zi9t-7#?@)0dkxsN;Y+khGx_tM9%4XRtgKr_H}K_P`?`%7gzmy3d?_r*!4^7<8?Twd z-|zk{0W+^=N|G;YKl=uEZ*PJ^J;)L|Xb>5+%EOao_x*wUA9;WT-!{Jd;wV@D{xN?2 zt9w{Fe-eX7Okm!uF+vuGUdNM40JB+(7RmRn%(>+bu9|TfCpNF5BWx^>Kk^{MQ=-8q zp4sze5ET>0(mU>8+@Ms_294#4d6Q(~Kq+I(-oF8ZX!8TVxr=L-Ok(dB+o>1EG-BRO zJp8xcV{2%nzSZ7c&q4@hp-bssl};_}#&*f9T_N9LV-S7Zz_^?47kavvKsOCd^+u*% zv5fxlaa?)J&G;(Mv3lh;rrq{C?!NPGZeKo^!`r`R;FWjq;P37w$y>pJeOcJWxEV43 zS{``n@64Yzls1Ebfite*iNC)@gsp?^n>KR%R4M)X1q$!q!SS;dSgjpI4WGzw9)F4( zubq!x*>j_}Xth>AU12lfiGxWD^~GQ@W0$UskZu?fZ)^_fGo8LDW!M<{dBVDn*E4*{ zuej&VyI6745>it7v*g-E=xoMLAm^}R)_Jq&?gs^!zmKBbM~ECamWA^r9T? 63>On?8i=1TY+u81bV)N#EX*A0acvd4e@zrxNq4M6lM!{Q7@%Nk --FCsm>E54m)bCx>w~oY<3(z z{v-?-%H#z%aOX9% G$1WPCJxcpPMO;= z3TGM`A3;UgA&SqPL!)yiz}*L}n?F$ks90^CfvTmkj=JWy3j>h^q+055h|Duc1e2`8 z2LuRkpp?F+(ok2OEwcCu;Q-V^2PRoJlGr3CJ@E4Dxci %ysJ~%qe7VIh!^zVL{g;NKy AMUs#Zh<|hx!v;nPKx>uPl?zWEp+f|__Vy-1QetRruOhFoP?nFQM;NeZv?8z! zWXRa*{O0~&6YUOVm5qcXBvVnGPmAc4T>wK_2UCR(?p!WFk(r=KX&F#Yztm&_GDENl zWM=3vbn^2^#}{S&+vGY`7ny!`_wW+`Xz&g2#aq~IM|%qa36Y}hwVXM98lCvNyN8DW z20Hw`Ja89)OFkAXjV~vCyVPN!7ny`X$V4f1(A|&ln0Oo}BMu?k3%4vdq(;hm$v<{j zKFJ`@4vKb5Hm&Mm4brlULs)=Wtso>Ogo4anRMys_)p_FY=7F0>FyTJ#^2~`^j7?L! z;r!-Qn@kgKKYtI7L+DtVfKlswNgo`GUdVOqz%&`;4H`F^=Egjl94dSRz0rh5kven~ zOK<-T3&$tYA&_+X@Kp2~6(cVjhG&l@TC+pV!n+>gn)zcn^3~hC`uP^o7p-W!mYT9m zDk{p+c!aXzp~sj$JeDtC{X47nX9=0Q$*k4RW8|{ltmdw %lp#q1XlSJAi}Rb+6!L#c;hfFY znY{Ddhg@@cs&IG;5ulaweK*q3b~qH>G7)$GXhIe3{Npzd;$f@9BVstosZp$Y{qGcp zdDGEmN2^g>0LN`AyX@fQdvqL1xm=Z2M?>x&-g-5Vo3FbJjQ}1tn@#?_(_l4PErt6( z;k}SB(!E7cQH$@JRH7W4Tu#rIbhpTaSu *q!)l^vs_ 6x*w(W7BUYuf65cTeF#l!Il9ytgob#r_KkmX+Q)&>tQ3w}(t#FJ zm864rx&4l-Iq=yF6u0||wkz-s^pdj{M~^&1CHgNlLm~dB)Oa#+>TFhh@GO=4f~ocL zWlEZk7yj~R0#gPHThQU<>n?ieMr3>-pFjT;2V)YLD>Byq$KH8>S9M+a{&%bHRqv>G ziQap!28@k+iS4+?PMrEOnY5YY%}d6a#CBZcZextW*ch-422Afw6akWukWlZvx7+XA z=SWu^T_lPV5>KM@efj`#&Ms@Oz1Dy2@?X-%j09*L9vV@q5ntMQ{nx+2qrDRCkjX+X zhw||UuTZutfYuhfy!YH!-fEWJx{!BQ?_i&^jt-NP;R${mJYC5jUVnuzpZiZ%ZHVUX zyJoX)+jbn~;j}sfx%ZBVGI(~81Zs65EW2kaAOG>cI5#>5L-YimxObtfOJ_H&X1%8e z%Ws}|86&FRE10lw18bgtj+o@(3{9NK?$sag%;`WnEJC(U6MmryVoufb=JPKSmOPGc z-MJ7C(cjEnAG6xum*umTvwz1Qc;UqsnoDz7^yI&jwRIy7yRCP->auM*4?m2S244Bq zZ&5duU _vC+$p^3Vr!x^$tF-)J#z+pY+b71& z*2}%3HFdD{t>@V)0A%cp2U)gg1m$N_`D)89{OnC6%)JkPDFubu*2^X1?wIVRYTp0z zYxpLP6>`<#6&OI6=;x-_p5>&M6{p6N_NsJV|6nT-BgSG7dS&zuVCJ`%^Xwnrpz*>m z@EO9xPkmd?JydaK2P@Zva{nD8=q$V- bB zF`A|wt9bS0Mxw{f=l1zy2Uku0&OS=ADHiFvuubAKkpSim21J9*um8ZkI|gQcRSDD5 zT;C*&K#+)Z+vu{X@%Q$^($z*)c_k`O;YcF`s4gj_x~38D;3yIkB6_amHBen$FTg?s zVIh5UmdH15L`{Vk&ePQC5DqB`qsE3!ZNT440D^`F;jjYm)T?NyDwUV2BO=3u)3wRb zid9%kjfiTUI#0X|x;~WSrnWi}J=YMIoQ%V2#>dZx(%fu;T0#gC#!79JB2(?9eu@ac zrL7BtUW3IUoUt%BPOT9y4>fh=CA64z#Kc92{xoCs4-$aOOmlOmkXL|+5WA=;D-)5X zzv!bER=bE^9U{{5@Q|Z4Pe1?5mKz0}qPeyjuaIygKPoA2SwRjpjh*toxu2&7lPD*^ z*Hg~8sxtWCW7N@7TS2XOCp0=<$jHgXtP6OC#t|qGN2l2;)AHLbX7s}7c6FHK1F>he ztzh-xW}f-u&+$_Cy?QD&tE;u1k}^?8M-i*OEaLzD_jjnsy@1|73V)*pt%&HQ!)A?@ z(iqr@N{AC5HBwSoirJ|ne&{g#J#~E#ze?Gf8=CPJI-{|hXl^kR8tf Wde z+wm8UyX4{p0bBwJ_A>}s_0 #$5DunWa z3t|jRgvG{-_IlIO+>URcfA6Z7oDsS>kE;3>LSqt%3Jq|Z2SJxPobF_P&E)6gqYH>6 zSvdakf^1CMAfiLPF$p~m@G{WWR84+CIRQ}#M27`pHMLV+UV&5eD=s=j=u#6o=kxK7 zh$BU`wZ5?dy|+I`om0$}R(t{j ;dE*=4i&gZurm_l$&X1Vb zA@W!?R94W`W+fs%0dH*=IoWvxMkV2`v(aU7U^E)Bnk_=V^mKGt3Gw%#R>-roq7MJ? zSdyYbsjVoYxU!Kr;k?7V^wc*uq4V^`sF&cTlNB#LgD!D4v&Ii2A|||>Dc9U4boe4p zy| =y~wLdF;DblT6x(?`~&>ra4f>u$c>*}78 zTHfLIj*@*+Nr>g%AD!ZTyP~a5MY--1pucimbz8YabMCr+XrnK;ft}0QPaOk9M_RXb z=z8jL%^0;puCDVbN(z4`eJS}}b-DiRzD8+c%g5^oo3N0H!=n2g1J{+!s-kmzvA39q zpS(l98RBr0l~N8$-VN7GX8@g1%1TKUZyP{oREiY !Oth9x0Zgj54pP$p^RJfm^E CD~h8YrKOvaIVh0IqtK zeX$I%XX#E^@BY}X^7kt_BxPOBeq^frowc7nD2=qsG1#xrr_0-I;N}M(yCO5Ki%Q%- zejML@a-3YI`6_a7UZw7VWM%8;_qKj?!qSiKDckGbzH13OYy;?#Qm3s~=)*vDU5hN- z=Rv>Q6mETWFV{i;)cvX}%#Z%a+4^hmKotF4!4_O?EbVUFmrL*Yw%mt~e&+x6IOqQQ z+F!~9+W@lYZ_a7GBY8l861$sj4J0eu4Yaj`&%na6+nrd2b1>VxN!Fyp_!j#h!P-Cd zqjLMRzsO5 S#^0BQzk$KRqqS8DIo`gE=By_Wa2f1`eW9bzZPH9GEVaj^gB$mxG; z^rE?radSoYUOhkBYnZeD$o5_jpl}Q@2mhY-ZJ@_`gJpVogH(fuU$1ij)$*+z&`Vc^ zHFW>nU ^yjKzyx0dI!#L# zwe=0XbxQkhna8&C@#+HuvRPisqZe_{$8W#Kx%0J`F`&w1a5cHCeB}k+S^Wjg=4%HV zPMew9y83IT2-gX7cWBF6UVi>1j$~EzW^Qe7$m8voR@2tyyk^B$)5-_0zDr(l>vgfZ z{xdvMf6u1wW8dk*|8;$rZYb5&)nRoyuTf{9@O&B{uUXC74WCn7*WT}3khb4;Zdl8n zy%+jr82&37OnqIgh(;YZ%yCM-q&EMgeAsl&ru{-TH`W12Csww6^dSci7YryXDR1 TZ%X4}ngkbA}SZnod2KE9YNs#iW~yA%wY$W{`V2jk*?V zAKGZw`Gk&!QnIoNdTFa&D+D^lyDkUgqT!a)pVwru?wz+~M{nqfs3H?bF=292uk&}6 zp=MxqS{Kc<>s^QV&BR$Vi46DYUGml|41&Qwl38=dk$(IXEdm^922e;Py|!%7T1)x# z%~xb1E#no8uD-X;I>t?zhu%_0dS+R#gE9JqF=PG|Jam`#+C3Dq>W>y)CF19)^JWno zXz1O;chP(62be%=`qGN46z}S or^t^gif`~S+rUmC@?9&Tghq0k9s`D! B@plU7RFaPr*RYFG%iZOMav5^>bQ&Pfuw-#J&xY}G%wqNU} zD+W~;U%vG`741&By()#Al=E4ykfFMtdUS4oS1a^NDkCsFg~=1*IC1DSmMi4x@o*bI zty{S|H@)g_F5AW1qozzFDKWTLR!Upc{f!q>=FTKE*w{P2+{e~M)vs0Py2n*?ad5@t zZwL}(ay7MlVZcSOrW>TB|JQij(WhExBr# C5h7d_n-W z`qO;y%AY8#>g0+4{J;1#X0mGa=d^X`S@h7u%o!8HrgdM@-daOeb}94jdkC-EGn5pS zabV9r5{3@PTAjn*9jT01dJm(ewm7Y%?)a2Lr}A;?0=VbN?~)i|>~j#UA~%i0M>A=z zDW=ik$74Tvg7i)6$ZycF{L#ej)BkN1tY7mnrM0aDCQRe;M{Xf`_)z?PQt2;|yHsxZ zg;Qi#t5`OF5~mOCpw1CYfH_yRw~E6%cFTlV!-pmIVOEulQ)T`cK3%nmPL++6Id}2s zO_PX?j-X7VmSxvclgDQtY`~B-nW5u{$-lF-*RuBA6_nMt6FPb(6JveoG(@mqLK3^T ze2z!#2x?C6rQGbtUCF~`<9KxUHt~KFIVX=1GI24FK6r xyUilF cw?HKNZql5swtx|1)r9KfdWVBteQB+8u0n)SP}IsL`BJwQ`l8mT8F`tcZA zE31f29)_u idlEw%dIm sEYB zli4B4T}G6u6|a=3Oo%nI@#9TQy!Ae;1qa! To(T(<6YeabsJMn>U+theK8_Ki zhxHz)9BBS&^hSnFTga2kMo{-3zheKFUlA7K&%6aQDM&j=LAw_|rV>t`Eo0vO4|h9O za~oUNe@Iqg9Ug&6Jo3G7 4k*O>AGcmQ&~QFh<0%VE$}sE9zNr^L)zAALCrH zm6Rc7@{4LP?A%66N+RRNjo{?oP3+urnvl40+;-bU4sG8_QF%QPQ9+beIC%OOKOoSc z?mc9leQX=~9f90-({yZ|wL&&~nR(A*4zB-*i+S}-y!j4pUoes6p-Fh}s~b=jI){m! zo7Qve_yrQi&E@vn$8%`+85Z1mGi^oZIC8oSFOM!V&t(x96-!lq3AcRbCqk!#dbcH| z`(k@Ht|g e%%8UfC9%&n{!> (eG)TAjiOHc+hpp*?yv|0(MEfR ziMV0o86N3NW=28x?USy0wtcjL&{1=_@4 q_|Y(@l(8ayKEGdUhWv zV(!AF*sF^vsp*i7Oxc+O96FN2ygR?eElXx}g8_?mAnF#m+~$T-E)(PSM`BcDlMOmnpERxrDd=`~k^}?qcrLBu<^U(0%C6-t8Ww6(O&HNM_HQO8(hQ z+NHEK!i0YG{L3^MM{)myH<6#2LqSPCMOAgO!_Udeq_Eb({F|22T9`{!lSS@R(Yd4S z-k-r8k3UY~kzJh5YwWX3ElFzqE3Z;+31-IBA*_05CBDfM=*-y3uYdFdO1eBrj_I3A zNBaKgrnT%nS Ip-1PtxQi3^k`eL8SDraFWIm4 )C2p`7(4}#I*Ct!51IQmP*~HBqc)ey4lT}_6TI=4 zHwhYZ3r~M%8M{}1$ex4yS-oNp^B#DJS+mB|S((ksmFq=Yp5mUHQds@+3hGUlR=i|* zX=!Hli!b9pW+~tQ@ei3kJcLi)c@2Hi0)F(}yV$>G6{)ArvuooQ#LQSqa >N!4q?p;DA-NNE|Bgi bN7>`cb z`DJG0kahYXE8p45ockYQc(gaC&J IyF87m<@+Aj?h44Rbo97_;17E1jL~0{qzpKu_g^_rGGwf(0~O+{e04zalsLBHpx; zonMR5UMm29OYay+IzA*agoB@Lq()5EoFiK)?67hAv(=m`u(DvmC^oNNL2j#4rXp}& zVFfPx@K!c%KFfl|^T|B0o}D59$t%3rePFw}TIgan8OIJ|@bn<_)ERtz)D#pHx{(^H znJ{YsKAjEZl{WOOesr-%jCY%HC^Lo)rCxy3*}`UYmgG^ RL@?pW4pZLOY8W+$83D0~_CdgQ9jnX3vb`la(u}=yd*7ThN2gRaW$!-8Y)#ZJobU z62w7Z@(o)lxqRhOfD(y~lXhwwTA8urCSf#3k`fq5X<-?|Z~r#;&z;8T;UnlMxk#7V zi&=9=Gjh^wh6qbiQ` +87#4qG 94 zbTi6oJ;QnQSHGn8#CF!a_c3`Tb(bxzSsV_AEqRDrCyXW}Bm`@hoydq-!bAP>&}n7k z96#d@?zw9=Ti;v3mM{0xYH^^ESp(HFiBiAYAZiT;qp|xcqRos~a2#_NEh0KHmgV=} z$-?o&FH11iSaAVcOfq-O8%Jo6w?OlnOHr_kK~nEYoQOmNeGKy9Es2`H#OC0h@83pz zbf{>LM*dE!Thn9e^?CzQ(TNNR@ jIC?mqzMeFe=A-f* z!i@0=j1}ejwsp#s|H^I1uJ&3g8~s^y>r7(9qe&3}p|PclSvSoUbxk1N%ZsYYI^q}J z%k9%A5FQamXPcR&PyB);&n7;6V+E(qUZA9^8l9i`wy~O#vzOxCUP5bFH1{u?D(jY3 zqn24g4W8ZOB<1L-Dagck;!Ku~8;+m19uMCzW(z N8i= z;;oBC`AiicZ%lF$9^yNx4<0?`N; h08NBIet|5BN zERrJqiA$cxxKTq{xa3X};sSBl?Ft|ufJy8WCZ~9?b@LAP9LZ<#?Ke?bU4xIWmb%6c zX56$G9|<@~d3%ID>C~5R<;dJV ;N+#xSt?f7dtl}CiUPZ8jT*pDSBfyStVjuX-%%%>1y;eH&t^w zGn>;nh20m (MqM?b{Rna`e+7cK)PPMcL;y^ycDc6MR0J7nX~ z)z-*`jC1mGe#ylweB#FQ*mv&~5!N;eYOOMJZD(y2nQ7-~?y~k#KzUzTtEEh|Yv r(`cn4n-NVOkeSlfjbIsRcrZg*E^r^m^ z2SUuI=9*H@XBNtYa+>y54sG7en!mh5tLTeFxu1XL99y=0$e{x#&}gNY+%BTTI `y6h`3OE{R3z!y2$puyV$Vm6YN^`WoZkdh7O0?Q*79M zoV4__)Tl!7XsBfO(X$-cu?a^+Fb1t1Q)h<&j!tY{T_Q5?#M0G)smq3=qYH;;5Wz+R zyEpD2_2f1xoOY6i##4OqINSDY ^v(gh#{(Ir!31TFlNpd->$Ok3dS&Xt9ue{3z>Jyh6r>LVN>5XvoiI z+urSL`uKAk8mG{AF?THOoH>@x$?P1Y)JbiX7g_nnJ5+Yq`@OAYx0)!)I?d;sR&l0A z&G<>fsW_j*{sVjXe9Z>z>h45^=B{=Mvd&S_)Jbib&_~@6zVm;+Lw){X((-C9i{8Bi z*t>ZA02@DkMd)y*&{qLK3yU~-a4#D^_*g!mE3IMJoo3D+J0W!ZA_n1%gM4&EjhxQp zaYOOaOSJr*qHZ&GlU>NKQ_fY>XSGNCEWB+w``-8+Rr(Yr#f1?gK(|Wo%cR*0Nr?^V zoo_7_#bjpW(`D^@*jCcTnD}@M0zeIw#~@CCY&}h- >13E-|3Zd~t0fkFS|lvnK~U?PpN zz$S9K4x8h~R;&5l?|#?&kKh0P_x%y94Meu)PP*p$Q3=!=_`RS0^mZRFFTG=MXs@_T z*3s4`qCZa&g Nv1-ANfU9jGVEUnUhjvy8DjmGKx#8iB29ajIX{gU3)+fb@^v0thFDThADS$) zQFb(zlABvbWXf