PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB`Mini Shell

HOME


Mini Shell 1.0
DIR:/home/amritharmonium.com/www/wp-content/themes/porto/js/
Upload File :
Current File : /home/amritharmonium.com/www/wp-content/themes/porto/js/plugins.js
/*!
 * Bootstrap v3.3.5 (http://getbootstrap.com)
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under the MIT license
 */

if (typeof jQuery === 'undefined') {
  throw new Error('Bootstrap\'s JavaScript requires jQuery')
}

+function ($) {
  'use strict';
  var version = $.fn.jquery.split(' ')[0].split('.')
  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
    throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
  }
}(jQuery);

/* ========================================================================
 * Bootstrap: transition.js v3.3.5
 * http://getbootstrap.com/javascript/#transitions
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
  // ============================================================

  function transitionEnd() {
    var el = document.createElement('bootstrap')

    var transEndEventNames = {
      WebkitTransition : 'webkitTransitionEnd',
      MozTransition    : 'transitionend',
      OTransition      : 'oTransitionEnd otransitionend',
      transition       : 'transitionend'
    }

    for (var name in transEndEventNames) {
      if (el.style[name] !== undefined) {
        return { end: transEndEventNames[name] }
      }
    }

    return false // explicit for ie8 (  ._.)
  }

  // http://blog.alexmaccaw.com/css-transitions
  $.fn.emulateTransitionEnd = function (duration) {
    var called = false
    var $el = this
    $(this).one('bsTransitionEnd', function () { called = true })
    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
    setTimeout(callback, duration)
    return this
  }

  $(function () {
    $.support.transition = transitionEnd()

    if (!$.support.transition) return

    $.event.special.bsTransitionEnd = {
      bindType: $.support.transition.end,
      delegateType: $.support.transition.end,
      handle: function (e) {
        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
      }
    }
  })

}(jQuery);

/* ========================================================================
 * Bootstrap: alert.js v3.3.5
 * http://getbootstrap.com/javascript/#alerts
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // ALERT CLASS DEFINITION
  // ======================

  var dismiss = '[data-dismiss="alert"]'
  var Alert   = function (el) {
    $(el).on('click', dismiss, this.close)
  }

  Alert.VERSION = '3.3.5'

  Alert.TRANSITION_DURATION = 150

  Alert.prototype.close = function (e) {
    var $this    = $(this)
    var selector = $this.attr('data-target')

    if (!selector) {
      selector = $this.attr('href')
      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
    }

    var $parent = $(selector)

    if (e) e.preventDefault()

    if (!$parent.length) {
      $parent = $this.closest('.alert')
    }

    $parent.trigger(e = $.Event('close.bs.alert'))

    if (e.isDefaultPrevented()) return

    $parent.removeClass('in')

    function removeElement() {
      // detach from parent, fire event then clean up data
      $parent.detach().trigger('closed.bs.alert').remove()
    }

    $.support.transition && $parent.hasClass('fade') ?
      $parent
        .one('bsTransitionEnd', removeElement)
        .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
      removeElement()
  }


  // ALERT PLUGIN DEFINITION
  // =======================

  function Plugin(option) {
    return this.each(function () {
      var $this = $(this)
      var data  = $this.data('bs.alert')

      if (!data) $this.data('bs.alert', (data = new Alert(this)))
      if (typeof option == 'string') data[option].call($this)
    })
  }

  var old = $.fn.alert

  $.fn.alert             = Plugin
  $.fn.alert.Constructor = Alert


  // ALERT NO CONFLICT
  // =================

  $.fn.alert.noConflict = function () {
    $.fn.alert = old
    return this
  }


  // ALERT DATA-API
  // ==============

  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)

}(jQuery);

/* ========================================================================
 * Bootstrap: button.js v3.3.5
 * http://getbootstrap.com/javascript/#buttons
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // BUTTON PUBLIC CLASS DEFINITION
  // ==============================

  var Button = function (element, options) {
    this.$element  = $(element)
    this.options   = $.extend({}, Button.DEFAULTS, options)
    this.isLoading = false
  }

  Button.VERSION  = '3.3.5'

  Button.DEFAULTS = {
    loadingText: 'loading...'
  }

  Button.prototype.setState = function (state) {
    var d    = 'disabled'
    var $el  = this.$element
    var val  = $el.is('input') ? 'val' : 'html'
    var data = $el.data()

    state += 'Text'

    if (data.resetText == null) $el.data('resetText', $el[val]())

    // push to event loop to allow forms to submit
    setTimeout($.proxy(function () {
      $el[val](data[state] == null ? this.options[state] : data[state])

      if (state == 'loadingText') {
        this.isLoading = true
        $el.addClass(d).attr(d, d)
      } else if (this.isLoading) {
        this.isLoading = false
        $el.removeClass(d).removeAttr(d)
      }
    }, this), 0)
  }

  Button.prototype.toggle = function () {
    var changed = true
    var $parent = this.$element.closest('[data-toggle="buttons"]')

    if ($parent.length) {
      var $input = this.$element.find('input')
      if ($input.prop('type') == 'radio') {
        if ($input.prop('checked')) changed = false
        $parent.find('.active').removeClass('active')
        this.$element.addClass('active')
      } else if ($input.prop('type') == 'checkbox') {
        if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
        this.$element.toggleClass('active')
      }
      $input.prop('checked', this.$element.hasClass('active'))
      if (changed) $input.trigger('change')
    } else {
      this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
      this.$element.toggleClass('active')
    }
  }


  // BUTTON PLUGIN DEFINITION
  // ========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.button')
      var options = typeof option == 'object' && option

      if (!data) $this.data('bs.button', (data = new Button(this, options)))

      if (option == 'toggle') data.toggle()
      else if (option) data.setState(option)
    })
  }

  var old = $.fn.button

  $.fn.button             = Plugin
  $.fn.button.Constructor = Button


  // BUTTON NO CONFLICT
  // ==================

  $.fn.button.noConflict = function () {
    $.fn.button = old
    return this
  }


  // BUTTON DATA-API
  // ===============

  $(document)
    .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
      var $btn = $(e.target)
      if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
      Plugin.call($btn, 'toggle')
      if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault()
    })
    .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
      $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
    })

}(jQuery);

/* ========================================================================
 * Bootstrap: carousel.js v3.3.5
 * http://getbootstrap.com/javascript/#carousel
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // CAROUSEL CLASS DEFINITION
  // =========================

  var Carousel = function (element, options) {
    this.$element    = $(element)
    this.$indicators = this.$element.find('.carousel-indicators')
    this.options     = options
    this.paused      = null
    this.sliding     = null
    this.interval    = null
    this.$active     = null
    this.$items      = null

    this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))

    this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
      .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
      .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
  }

  Carousel.VERSION  = '3.3.5'

  Carousel.TRANSITION_DURATION = 600

  Carousel.DEFAULTS = {
    interval: 5000,
    pause: 'hover',
    wrap: true,
    keyboard: true
  }

  Carousel.prototype.keydown = function (e) {
    if (/input|textarea/i.test(e.target.tagName)) return
    switch (e.which) {
      case 37: this.prev(); break
      case 39: this.next(); break
      default: return
    }

    e.preventDefault()
  }

  Carousel.prototype.cycle = function (e) {
    e || (this.paused = false)

    this.interval && clearInterval(this.interval)

    this.options.interval
      && !this.paused
      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))

    return this
  }

  Carousel.prototype.getItemIndex = function (item) {
    this.$items = item.parent().children('.item')
    return this.$items.index(item || this.$active)
  }

  Carousel.prototype.getItemForDirection = function (direction, active) {
    var activeIndex = this.getItemIndex(active)
    var willWrap = (direction == 'prev' && activeIndex === 0)
                || (direction == 'next' && activeIndex == (this.$items.length - 1))
    if (willWrap && !this.options.wrap) return active
    var delta = direction == 'prev' ? -1 : 1
    var itemIndex = (activeIndex + delta) % this.$items.length
    return this.$items.eq(itemIndex)
  }

  Carousel.prototype.to = function (pos) {
    var that        = this
    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))

    if (pos > (this.$items.length - 1) || pos < 0) return

    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
    if (activeIndex == pos) return this.pause().cycle()

    return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
  }

  Carousel.prototype.pause = function (e) {
    e || (this.paused = true)

    if (this.$element.find('.next, .prev').length && $.support.transition) {
      this.$element.trigger($.support.transition.end)
      this.cycle(true)
    }

    this.interval = clearInterval(this.interval)

    return this
  }

  Carousel.prototype.next = function () {
    if (this.sliding) return
    return this.slide('next')
  }

  Carousel.prototype.prev = function () {
    if (this.sliding) return
    return this.slide('prev')
  }

  Carousel.prototype.slide = function (type, next) {
    var $active   = this.$element.find('.item.active')
    var $next     = next || this.getItemForDirection(type, $active)
    var isCycling = this.interval
    var direction = type == 'next' ? 'left' : 'right'
    var that      = this

    if ($next.hasClass('active')) return (this.sliding = false)

    var relatedTarget = $next[0]
    var slideEvent = $.Event('slide.bs.carousel', {
      relatedTarget: relatedTarget,
      direction: direction
    })
    this.$element.trigger(slideEvent)
    if (slideEvent.isDefaultPrevented()) return

    this.sliding = true

    isCycling && this.pause()

    if (this.$indicators.length) {
      this.$indicators.find('.active').removeClass('active')
      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
      $nextIndicator && $nextIndicator.addClass('active')
    }

    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
    if ($.support.transition && this.$element.hasClass('slide')) {
      $next.addClass(type)
      $next[0].offsetWidth // force reflow
      $active.addClass(direction)
      $next.addClass(direction)
      $active
        .one('bsTransitionEnd', function () {
          $next.removeClass([type, direction].join(' ')).addClass('active')
          $active.removeClass(['active', direction].join(' '))
          that.sliding = false
          setTimeout(function () {
            that.$element.trigger(slidEvent)
          }, 0)
        })
        .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
    } else {
      $active.removeClass('active')
      $next.addClass('active')
      this.sliding = false
      this.$element.trigger(slidEvent)
    }

    isCycling && this.cycle()

    return this
  }


  // CAROUSEL PLUGIN DEFINITION
  // ==========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.carousel')
      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
      var action  = typeof option == 'string' ? option : options.slide

      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
      if (typeof option == 'number') data.to(option)
      else if (action) data[action]()
      else if (options.interval) data.pause().cycle()
    })
  }

  var old = $.fn.carousel

  $.fn.carousel             = Plugin
  $.fn.carousel.Constructor = Carousel


  // CAROUSEL NO CONFLICT
  // ====================

  $.fn.carousel.noConflict = function () {
    $.fn.carousel = old
    return this
  }


  // CAROUSEL DATA-API
  // =================

  var clickHandler = function (e) {
    var href
    var $this   = $(this)
    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
    if (!$target.hasClass('carousel')) return
    var options = $.extend({}, $target.data(), $this.data())
    var slideIndex = $this.attr('data-slide-to')
    if (slideIndex) options.interval = false

    Plugin.call($target, options)

    if (slideIndex) {
      $target.data('bs.carousel').to(slideIndex)
    }

    e.preventDefault()
  }

  $(document)
    .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
    .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)

  $(window).on('load', function () {
    $('[data-ride="carousel"]').each(function () {
      var $carousel = $(this)
      Plugin.call($carousel, $carousel.data())
    })
  })

}(jQuery);

/* ========================================================================
 * Bootstrap: collapse.js v3.3.5
 * http://getbootstrap.com/javascript/#collapse
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // COLLAPSE PUBLIC CLASS DEFINITION
  // ================================

  var Collapse = function (element, options) {
    this.$element      = $(element)
    this.options       = $.extend({}, Collapse.DEFAULTS, options)
    this.$trigger      = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
                           '[data-toggle="collapse"][data-target="#' + element.id + '"]')
    this.transitioning = null

    if (this.options.parent) {
      this.$parent = this.getParent()
    } else {
      this.addAriaAndCollapsedClass(this.$element, this.$trigger)
    }

    if (this.options.toggle) this.toggle()
  }

  Collapse.VERSION  = '3.3.5'

  Collapse.TRANSITION_DURATION = 350

  Collapse.DEFAULTS = {
    toggle: true
  }

  Collapse.prototype.dimension = function () {
    var hasWidth = this.$element.hasClass('width')
    return hasWidth ? 'width' : 'height'
  }

  Collapse.prototype.show = function () {
    if (this.transitioning || this.$element.hasClass('in')) return

    var activesData
    var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')

    if (actives && actives.length) {
      activesData = actives.data('bs.collapse')
      if (activesData && activesData.transitioning) return
    }

    var startEvent = $.Event('show.bs.collapse')
    this.$element.trigger(startEvent)
    if (startEvent.isDefaultPrevented()) return

    if (actives && actives.length) {
      Plugin.call(actives, 'hide')
      activesData || actives.data('bs.collapse', null)
    }

    var dimension = this.dimension()

    this.$element
      .removeClass('collapse')
      .addClass('collapsing')[dimension](0)
      .attr('aria-expanded', true)

    this.$trigger
      .removeClass('collapsed')
      .attr('aria-expanded', true)

    this.transitioning = 1

    var complete = function () {
      this.$element
        .removeClass('collapsing')
        .addClass('collapse in')[dimension]('')
      this.transitioning = 0
      this.$element
        .trigger('shown.bs.collapse')
    }

    if (!$.support.transition) return complete.call(this)

    var scrollSize = $.camelCase(['scroll', dimension].join('-'))

    this.$element
      .one('bsTransitionEnd', $.proxy(complete, this))
      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
  }

  Collapse.prototype.hide = function () {
    if (this.transitioning || !this.$element.hasClass('in')) return

    var startEvent = $.Event('hide.bs.collapse')
    this.$element.trigger(startEvent)
    if (startEvent.isDefaultPrevented()) return

    var dimension = this.dimension()

    this.$element[dimension](this.$element[dimension]())[0].offsetHeight

    this.$element
      .addClass('collapsing')
      .removeClass('collapse in')
      .attr('aria-expanded', false)

    this.$trigger
      .addClass('collapsed')
      .attr('aria-expanded', false)

    this.transitioning = 1

    var complete = function () {
      this.transitioning = 0
      this.$element
        .removeClass('collapsing')
        .addClass('collapse')
        .trigger('hidden.bs.collapse')
    }

    if (!$.support.transition) return complete.call(this)

    this.$element
      [dimension](0)
      .one('bsTransitionEnd', $.proxy(complete, this))
      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
  }

  Collapse.prototype.toggle = function () {
    this[this.$element.hasClass('in') ? 'hide' : 'show']()
  }

  Collapse.prototype.getParent = function () {
    return $(this.options.parent)
      .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
      .each($.proxy(function (i, element) {
        var $element = $(element)
        this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
      }, this))
      .end()
  }

  Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
    var isOpen = $element.hasClass('in')

    $element.attr('aria-expanded', isOpen)
    $trigger
      .toggleClass('collapsed', !isOpen)
      .attr('aria-expanded', isOpen)
  }

  function getTargetFromTrigger($trigger) {
    var href
    var target = $trigger.attr('data-target')
      || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7

    return $(target)
  }


  // COLLAPSE PLUGIN DEFINITION
  // ==========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.collapse')
      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)

      if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.collapse

  $.fn.collapse             = Plugin
  $.fn.collapse.Constructor = Collapse


  // COLLAPSE NO CONFLICT
  // ====================

  $.fn.collapse.noConflict = function () {
    $.fn.collapse = old
    return this
  }


  // COLLAPSE DATA-API
  // =================

  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
    var $this   = $(this)

    if (!$this.attr('data-target')) e.preventDefault()

    var $target = getTargetFromTrigger($this)
    var data    = $target.data('bs.collapse')
    var option  = data ? 'toggle' : $this.data()

    Plugin.call($target, option)
  })

}(jQuery);

/* ========================================================================
 * Bootstrap: dropdown.js v3.3.5
 * http://getbootstrap.com/javascript/#dropdowns
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // DROPDOWN CLASS DEFINITION
  // =========================

  var backdrop = '.dropdown-backdrop'
  var toggle   = '[data-toggle="dropdown"]'
  var Dropdown = function (element) {
    $(element).on('click.bs.dropdown', this.toggle)
  }

  Dropdown.VERSION = '3.3.5'

  function getParent($this) {
    var selector = $this.attr('data-target')

    if (!selector) {
      selector = $this.attr('href')
      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
    }

    var $parent = selector && $(selector)

    return $parent && $parent.length ? $parent : $this.parent()
  }

  function clearMenus(e) {
    if (e && e.which === 3) return
    $(backdrop).remove()
    $(toggle).each(function () {
      var $this         = $(this)
      var $parent       = getParent($this)
      var relatedTarget = { relatedTarget: this }

      if (!$parent.hasClass('open')) return

      if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return

      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))

      if (e.isDefaultPrevented()) return

      $this.attr('aria-expanded', 'false')
      $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
    })
  }

  Dropdown.prototype.toggle = function (e) {
    var $this = $(this)

    if ($this.is('.disabled, :disabled')) return

    var $parent  = getParent($this)
    var isActive = $parent.hasClass('open')

    clearMenus()

    if (!isActive) {
      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
        // if mobile we use a backdrop because click events don't delegate
        $(document.createElement('div'))
          .addClass('dropdown-backdrop')
          .insertAfter($(this))
          .on('click', clearMenus)
      }

      var relatedTarget = { relatedTarget: this }
      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))

      if (e.isDefaultPrevented()) return

      $this
        .trigger('focus')
        .attr('aria-expanded', 'true')

      $parent
        .toggleClass('open')
        .trigger('shown.bs.dropdown', relatedTarget)
    }

    return false
  }

  Dropdown.prototype.keydown = function (e) {
    if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return

    var $this = $(this)

    e.preventDefault()
    e.stopPropagation()

    if ($this.is('.disabled, :disabled')) return

    var $parent  = getParent($this)
    var isActive = $parent.hasClass('open')

    if (!isActive && e.which != 27 || isActive && e.which == 27) {
      if (e.which == 27) $parent.find(toggle).trigger('focus')
      return $this.trigger('click')
    }

    var desc = ' li:not(.disabled):visible a'
    var $items = $parent.find('.dropdown-menu' + desc)

    if (!$items.length) return

    var index = $items.index(e.target)

    if (e.which == 38 && index > 0)                 index--         // up
    if (e.which == 40 && index < $items.length - 1) index++         // down
    if (!~index)                                    index = 0

    $items.eq(index).trigger('focus')
  }


  // DROPDOWN PLUGIN DEFINITION
  // ==========================

  function Plugin(option) {
    return this.each(function () {
      var $this = $(this)
      var data  = $this.data('bs.dropdown')

      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
      if (typeof option == 'string') data[option].call($this)
    })
  }

  var old = $.fn.dropdown

  $.fn.dropdown             = Plugin
  $.fn.dropdown.Constructor = Dropdown


  // DROPDOWN NO CONFLICT
  // ====================

  $.fn.dropdown.noConflict = function () {
    $.fn.dropdown = old
    return this
  }


  // APPLY TO STANDARD DROPDOWN ELEMENTS
  // ===================================

  $(document)
    .on('click.bs.dropdown.data-api', clearMenus)
    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
    .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)

}(jQuery);

/* ========================================================================
 * Bootstrap: modal.js v3.3.5
 * http://getbootstrap.com/javascript/#modals
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // MODAL CLASS DEFINITION
  // ======================

  var Modal = function (element, options) {
    this.options             = options
    this.$body               = $(document.body)
    this.$element            = $(element)
    this.$dialog             = this.$element.find('.modal-dialog')
    this.$backdrop           = null
    this.isShown             = null
    this.originalBodyPad     = null
    this.scrollbarWidth      = 0
    this.ignoreBackdropClick = false

    if (this.options.remote) {
      this.$element
        .find('.modal-content')
        .load(this.options.remote, $.proxy(function () {
          this.$element.trigger('loaded.bs.modal')
        }, this))
    }
  }

  Modal.VERSION  = '3.3.5'

  Modal.TRANSITION_DURATION = 300
  Modal.BACKDROP_TRANSITION_DURATION = 150

  Modal.DEFAULTS = {
    backdrop: true,
    keyboard: true,
    show: true
  }

  Modal.prototype.toggle = function (_relatedTarget) {
    return this.isShown ? this.hide() : this.show(_relatedTarget)
  }

  Modal.prototype.show = function (_relatedTarget) {
    var that = this
    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })

    this.$element.trigger(e)

    if (this.isShown || e.isDefaultPrevented()) return

    this.isShown = true

    this.checkScrollbar()
    this.setScrollbar()
    this.$body.addClass('modal-open')

    this.escape()
    this.resize()

    this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))

    this.$dialog.on('mousedown.dismiss.bs.modal', function () {
      that.$element.one('mouseup.dismiss.bs.modal', function (e) {
        if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
      })
    })

    this.backdrop(function () {
      var transition = $.support.transition && that.$element.hasClass('fade')

      if (!that.$element.parent().length) {
        that.$element.appendTo(that.$body) // don't move modals dom position
      }

      that.$element
        .show()
        .scrollTop(0)

      that.adjustDialog()

      if (transition) {
        that.$element[0].offsetWidth // force reflow
      }

      that.$element.addClass('in')

      that.enforceFocus()

      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })

      transition ?
        that.$dialog // wait for modal to slide in
          .one('bsTransitionEnd', function () {
            that.$element.trigger('focus').trigger(e)
          })
          .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
        that.$element.trigger('focus').trigger(e)
    })
  }

  Modal.prototype.hide = function (e) {
    if (e) e.preventDefault()

    e = $.Event('hide.bs.modal')

    this.$element.trigger(e)

    if (!this.isShown || e.isDefaultPrevented()) return

    this.isShown = false

    this.escape()
    this.resize()

    $(document).off('focusin.bs.modal')

    this.$element
      .removeClass('in')
      .off('click.dismiss.bs.modal')
      .off('mouseup.dismiss.bs.modal')

    this.$dialog.off('mousedown.dismiss.bs.modal')

    $.support.transition && this.$element.hasClass('fade') ?
      this.$element
        .one('bsTransitionEnd', $.proxy(this.hideModal, this))
        .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
      this.hideModal()
  }

  Modal.prototype.enforceFocus = function () {
    $(document)
      .off('focusin.bs.modal') // guard against infinite focus loop
      .on('focusin.bs.modal', $.proxy(function (e) {
        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
          this.$element.trigger('focus')
        }
      }, this))
  }

  Modal.prototype.escape = function () {
    if (this.isShown && this.options.keyboard) {
      this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
        e.which == 27 && this.hide()
      }, this))
    } else if (!this.isShown) {
      this.$element.off('keydown.dismiss.bs.modal')
    }
  }

  Modal.prototype.resize = function () {
    if (this.isShown) {
      $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
    } else {
      $(window).off('resize.bs.modal')
    }
  }

  Modal.prototype.hideModal = function () {
    var that = this
    this.$element.hide()
    this.backdrop(function () {
      that.$body.removeClass('modal-open')
      that.resetAdjustments()
      that.resetScrollbar()
      that.$element.trigger('hidden.bs.modal')
    })
  }

  Modal.prototype.removeBackdrop = function () {
    this.$backdrop && this.$backdrop.remove()
    this.$backdrop = null
  }

  Modal.prototype.backdrop = function (callback) {
    var that = this
    var animate = this.$element.hasClass('fade') ? 'fade' : ''

    if (this.isShown && this.options.backdrop) {
      var doAnimate = $.support.transition && animate

      this.$backdrop = $(document.createElement('div'))
        .addClass('modal-backdrop ' + animate)
        .appendTo(this.$body)

      this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
        if (this.ignoreBackdropClick) {
          this.ignoreBackdropClick = false
          return
        }
        if (e.target !== e.currentTarget) return
        this.options.backdrop == 'static'
          ? this.$element[0].focus()
          : this.hide()
      }, this))

      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow

      this.$backdrop.addClass('in')

      if (!callback) return

      doAnimate ?
        this.$backdrop
          .one('bsTransitionEnd', callback)
          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
        callback()

    } else if (!this.isShown && this.$backdrop) {
      this.$backdrop.removeClass('in')

      var callbackRemove = function () {
        that.removeBackdrop()
        callback && callback()
      }
      $.support.transition && this.$element.hasClass('fade') ?
        this.$backdrop
          .one('bsTransitionEnd', callbackRemove)
          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
        callbackRemove()

    } else if (callback) {
      callback()
    }
  }

  // these following methods are used to handle overflowing modals

  Modal.prototype.handleUpdate = function () {
    this.adjustDialog()
  }

  Modal.prototype.adjustDialog = function () {
    var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight

    this.$element.css({
      paddingLeft:  !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
      paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
    })
  }

  Modal.prototype.resetAdjustments = function () {
    this.$element.css({
      paddingLeft: '',
      paddingRight: ''
    })
  }

  Modal.prototype.checkScrollbar = function () {
    var fullWindowWidth = window.innerWidth
    if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
      var documentElementRect = document.documentElement.getBoundingClientRect()
      fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
    }
    this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
    this.scrollbarWidth = this.measureScrollbar()
  }

  Modal.prototype.setScrollbar = function () {
    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
    this.originalBodyPad = document.body.style.paddingRight || ''
    if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
  }

  Modal.prototype.resetScrollbar = function () {
    this.$body.css('padding-right', this.originalBodyPad)
  }

  Modal.prototype.measureScrollbar = function () { // thx walsh
    var scrollDiv = document.createElement('div')
    scrollDiv.className = 'modal-scrollbar-measure'
    this.$body.append(scrollDiv)
    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
    this.$body[0].removeChild(scrollDiv)
    return scrollbarWidth
  }


  // MODAL PLUGIN DEFINITION
  // =======================

  function Plugin(option, _relatedTarget) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.modal')
      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)

      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
      if (typeof option == 'string') data[option](_relatedTarget)
      else if (options.show) data.show(_relatedTarget)
    })
  }

  var old = $.fn.modal

  $.fn.modal             = Plugin
  $.fn.modal.Constructor = Modal


  // MODAL NO CONFLICT
  // =================

  $.fn.modal.noConflict = function () {
    $.fn.modal = old
    return this
  }


  // MODAL DATA-API
  // ==============

  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
    var $this   = $(this)
    var href    = $this.attr('href')
    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
    var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())

    if ($this.is('a')) e.preventDefault()

    $target.one('show.bs.modal', function (showEvent) {
      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
      $target.one('hidden.bs.modal', function () {
        $this.is(':visible') && $this.trigger('focus')
      })
    })
    Plugin.call($target, option, this)
  })

}(jQuery);

/* ========================================================================
 * Bootstrap: tooltip.js v3.3.5
 * http://getbootstrap.com/javascript/#tooltip
 * Inspired by the original jQuery.tipsy by Jason Frame
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // TOOLTIP PUBLIC CLASS DEFINITION
  // ===============================

  var Tooltip = function (element, options) {
    this.type       = null
    this.options    = null
    this.enabled    = null
    this.timeout    = null
    this.hoverState = null
    this.$element   = null
    this.inState    = null

    this.init('tooltip', element, options)
  }

  Tooltip.VERSION  = '3.3.5'

  Tooltip.TRANSITION_DURATION = 150

  Tooltip.DEFAULTS = {
    animation: true,
    placement: 'top',
    selector: false,
    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
    trigger: 'hover focus',
    title: '',
    delay: 0,
    html: false,
    container: false,
    viewport: {
      selector: 'body',
      padding: 0
    }
  }

  Tooltip.prototype.init = function (type, element, options) {
    this.enabled   = true
    this.type      = type
    this.$element  = $(element)
    this.options   = this.getOptions(options)
    this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
    this.inState   = { click: false, hover: false, focus: false }

    if (this.$element[0] instanceof document.constructor && !this.options.selector) {
      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
    }

    var triggers = this.options.trigger.split(' ')

    for (var i = triggers.length; i--;) {
      var trigger = triggers[i]

      if (trigger == 'click') {
        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
      } else if (trigger != 'manual') {
        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'

        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
      }
    }

    this.options.selector ?
      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
      this.fixTitle()
  }

  Tooltip.prototype.getDefaults = function () {
    return Tooltip.DEFAULTS
  }

  Tooltip.prototype.getOptions = function (options) {
    options = $.extend({}, this.getDefaults(), this.$element.data(), options)

    if (options.delay && typeof options.delay == 'number') {
      options.delay = {
        show: options.delay,
        hide: options.delay
      }
    }

    return options
  }

  Tooltip.prototype.getDelegateOptions = function () {
    var options  = {}
    var defaults = this.getDefaults()

    this._options && $.each(this._options, function (key, value) {
      if (defaults[key] != value) options[key] = value
    })

    return options
  }

  Tooltip.prototype.enter = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget).data('bs.' + this.type)

    if (!self) {
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
      $(obj.currentTarget).data('bs.' + this.type, self)
    }

    if (obj instanceof $.Event) {
      self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
    }

    if (self.tip().hasClass('in') || self.hoverState == 'in') {
      self.hoverState = 'in'
      return
    }

    clearTimeout(self.timeout)

    self.hoverState = 'in'

    if (!self.options.delay || !self.options.delay.show) return self.show()

    self.timeout = setTimeout(function () {
      if (self.hoverState == 'in') self.show()
    }, self.options.delay.show)
  }

  Tooltip.prototype.isInStateTrue = function () {
    for (var key in this.inState) {
      if (this.inState[key]) return true
    }

    return false
  }

  Tooltip.prototype.leave = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget).data('bs.' + this.type)

    if (!self) {
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
      $(obj.currentTarget).data('bs.' + this.type, self)
    }

    if (obj instanceof $.Event) {
      self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
    }

    if (self.isInStateTrue()) return

    clearTimeout(self.timeout)

    self.hoverState = 'out'

    if (!self.options.delay || !self.options.delay.hide) return self.hide()

    self.timeout = setTimeout(function () {
      if (self.hoverState == 'out') self.hide()
    }, self.options.delay.hide)
  }

  Tooltip.prototype.show = function () {
    var e = $.Event('show.bs.' + this.type)

    if (this.hasContent() && this.enabled) {
      this.$element.trigger(e)

      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
      if (e.isDefaultPrevented() || !inDom) return
      var that = this

      var $tip = this.tip()

      var tipId = this.getUID(this.type)

      this.setContent()
      $tip.attr('id', tipId)
      this.$element.attr('aria-describedby', tipId)

      if (this.options.animation) $tip.addClass('fade')

      var placement = typeof this.options.placement == 'function' ?
        this.options.placement.call(this, $tip[0], this.$element[0]) :
        this.options.placement

      var autoToken = /\s?auto?\s?/i
      var autoPlace = autoToken.test(placement)
      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'

      $tip
        .detach()
        .css({ top: 0, left: 0, display: 'block' })
        .addClass(placement)
        .data('bs.' + this.type, this)

      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
      this.$element.trigger('inserted.bs.' + this.type)

      var pos          = this.getPosition()
      var actualWidth  = $tip[0].offsetWidth
      var actualHeight = $tip[0].offsetHeight

      if (autoPlace) {
        var orgPlacement = placement
        var viewportDim = this.getPosition(this.$viewport)

        placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top'    :
                    placement == 'top'    && pos.top    - actualHeight < viewportDim.top    ? 'bottom' :
                    placement == 'right'  && pos.right  + actualWidth  > viewportDim.width  ? 'left'   :
                    placement == 'left'   && pos.left   - actualWidth  < viewportDim.left   ? 'right'  :
                    placement

        $tip
          .removeClass(orgPlacement)
          .addClass(placement)
      }

      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)

      this.applyPlacement(calculatedOffset, placement)

      var complete = function () {
        var prevHoverState = that.hoverState
        that.$element.trigger('shown.bs.' + that.type)
        that.hoverState = null

        if (prevHoverState == 'out') that.leave(that)
      }

      $.support.transition && this.$tip.hasClass('fade') ?
        $tip
          .one('bsTransitionEnd', complete)
          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
        complete()
    }
  }

  Tooltip.prototype.applyPlacement = function (offset, placement) {
    var $tip   = this.tip()
    var width  = $tip[0].offsetWidth
    var height = $tip[0].offsetHeight

    // manually read margins because getBoundingClientRect includes difference
    var marginTop = parseInt($tip.css('margin-top'), 10)
    var marginLeft = parseInt($tip.css('margin-left'), 10)

    // we must check for NaN for ie 8/9
    if (isNaN(marginTop))  marginTop  = 0
    if (isNaN(marginLeft)) marginLeft = 0

    offset.top  += marginTop
    offset.left += marginLeft

    // $.fn.offset doesn't round pixel values
    // so we use setOffset directly with our own function B-0
    $.offset.setOffset($tip[0], $.extend({
      using: function (props) {
        $tip.css({
          top: Math.round(props.top),
          left: Math.round(props.left)
        })
      }
    }, offset), 0)

    $tip.addClass('in')

    // check to see if placing tip in new offset caused the tip to resize itself
    var actualWidth  = $tip[0].offsetWidth
    var actualHeight = $tip[0].offsetHeight

    if (placement == 'top' && actualHeight != height) {
      offset.top = offset.top + height - actualHeight
    }

    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)

    if (delta.left) offset.left += delta.left
    else offset.top += delta.top

    var isVertical          = /top|bottom/.test(placement)
    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'

    $tip.offset(offset)
    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
  }

  Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
    this.arrow()
      .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
      .css(isVertical ? 'top' : 'left', '')
  }

  Tooltip.prototype.setContent = function () {
    var $tip  = this.tip()
    var title = this.getTitle()

    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
    $tip.removeClass('fade in top bottom left right')
  }

  Tooltip.prototype.hide = function (callback) {
    var that = this
    var $tip = $(this.$tip)
    var e    = $.Event('hide.bs.' + this.type)

    function complete() {
      if (that.hoverState != 'in') $tip.detach()
      that.$element
        .removeAttr('aria-describedby')
        .trigger('hidden.bs.' + that.type)
      callback && callback()
    }

    this.$element.trigger(e)

    if (e.isDefaultPrevented()) return

    $tip.removeClass('in')

    $.support.transition && $tip.hasClass('fade') ?
      $tip
        .one('bsTransitionEnd', complete)
        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
      complete()

    this.hoverState = null

    return this
  }

  Tooltip.prototype.fixTitle = function () {
    var $e = this.$element
    if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
    }
  }

  Tooltip.prototype.hasContent = function () {
    return this.getTitle()
  }

  Tooltip.prototype.getPosition = function ($element) {
    $element   = $element || this.$element

    var el     = $element[0]
    var isBody = el.tagName == 'BODY'

    var elRect    = el.getBoundingClientRect()
    if (elRect.width == null) {
      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
    }
    var elOffset  = isBody ? { top: 0, left: 0 } : $element.offset()
    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null

    return $.extend({}, elRect, scroll, outerDims, elOffset)
  }

  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :
           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }

  }

  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
    var delta = { top: 0, left: 0 }
    if (!this.$viewport) return delta

    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
    var viewportDimensions = this.getPosition(this.$viewport)

    if (/right|left/.test(placement)) {
      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
      if (topEdgeOffset < viewportDimensions.top) { // top overflow
        delta.top = viewportDimensions.top - topEdgeOffset
      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
      }
    } else {
      var leftEdgeOffset  = pos.left - viewportPadding
      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
        delta.left = viewportDimensions.left - leftEdgeOffset
      } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
      }
    }

    return delta
  }

  Tooltip.prototype.getTitle = function () {
    var title
    var $e = this.$element
    var o  = this.options

    title = $e.attr('data-original-title')
      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)

    return title
  }

  Tooltip.prototype.getUID = function (prefix) {
    do prefix += ~~(Math.random() * 1000000)
    while (document.getElementById(prefix))
    return prefix
  }

  Tooltip.prototype.tip = function () {
    if (!this.$tip) {
      this.$tip = $(this.options.template)
      if (this.$tip.length != 1) {
        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
      }
    }
    return this.$tip
  }

  Tooltip.prototype.arrow = function () {
    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
  }

  Tooltip.prototype.enable = function () {
    this.enabled = true
  }

  Tooltip.prototype.disable = function () {
    this.enabled = false
  }

  Tooltip.prototype.toggleEnabled = function () {
    this.enabled = !this.enabled
  }

  Tooltip.prototype.toggle = function (e) {
    var self = this
    if (e) {
      self = $(e.currentTarget).data('bs.' + this.type)
      if (!self) {
        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
        $(e.currentTarget).data('bs.' + this.type, self)
      }
    }

    if (e) {
      self.inState.click = !self.inState.click
      if (self.isInStateTrue()) self.enter(self)
      else self.leave(self)
    } else {
      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
    }
  }

  Tooltip.prototype.destroy = function () {
    var that = this
    clearTimeout(this.timeout)
    this.hide(function () {
      that.$element.off('.' + that.type).removeData('bs.' + that.type)
      if (that.$tip) {
        that.$tip.detach()
      }
      that.$tip = null
      that.$arrow = null
      that.$viewport = null
    })
  }


  // TOOLTIP PLUGIN DEFINITION
  // =========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.tooltip')
      var options = typeof option == 'object' && option

      if (!data && /destroy|hide/.test(option)) return
      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.tooltip

  $.fn.tooltip             = Plugin
  $.fn.tooltip.Constructor = Tooltip


  // TOOLTIP NO CONFLICT
  // ===================

  $.fn.tooltip.noConflict = function () {
    $.fn.tooltip = old
    return this
  }

}(jQuery);

/* ========================================================================
 * Bootstrap: popover.js v3.3.5
 * http://getbootstrap.com/javascript/#popovers
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // POPOVER PUBLIC CLASS DEFINITION
  // ===============================

  var Popover = function (element, options) {
    this.init('popover', element, options)
  }

  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')

  Popover.VERSION  = '3.3.5'

  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
    placement: 'right',
    trigger: 'click',
    content: '',
    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
  })


  // NOTE: POPOVER EXTENDS tooltip.js
  // ================================

  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)

  Popover.prototype.constructor = Popover

  Popover.prototype.getDefaults = function () {
    return Popover.DEFAULTS
  }

  Popover.prototype.setContent = function () {
    var $tip    = this.tip()
    var title   = this.getTitle()
    var content = this.getContent()

    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
    $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
    ](content)

    $tip.removeClass('fade top bottom left right in')

    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
    // this manually by checking the contents.
    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
  }

  Popover.prototype.hasContent = function () {
    return this.getTitle() || this.getContent()
  }

  Popover.prototype.getContent = function () {
    var $e = this.$element
    var o  = this.options

    return $e.attr('data-content')
      || (typeof o.content == 'function' ?
            o.content.call($e[0]) :
            o.content)
  }

  Popover.prototype.arrow = function () {
    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
  }


  // POPOVER PLUGIN DEFINITION
  // =========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.popover')
      var options = typeof option == 'object' && option

      if (!data && /destroy|hide/.test(option)) return
      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.popover

  $.fn.popover             = Plugin
  $.fn.popover.Constructor = Popover


  // POPOVER NO CONFLICT
  // ===================

  $.fn.popover.noConflict = function () {
    $.fn.popover = old
    return this
  }

}(jQuery);

/* ========================================================================
 * Bootstrap: scrollspy.js v3.3.5
 * http://getbootstrap.com/javascript/#scrollspy
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // SCROLLSPY CLASS DEFINITION
  // ==========================

  function ScrollSpy(element, options) {
    this.$body          = $(document.body)
    this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
    this.selector       = (this.options.target || '') + ' .nav li > a'
    this.offsets        = []
    this.targets        = []
    this.activeTarget   = null
    this.scrollHeight   = 0

    this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
    this.refresh()
    this.process()
  }

  ScrollSpy.VERSION  = '3.3.5'

  ScrollSpy.DEFAULTS = {
    offset: 10
  }

  ScrollSpy.prototype.getScrollHeight = function () {
    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
  }

  ScrollSpy.prototype.refresh = function () {
    var that          = this
    var offsetMethod  = 'offset'
    var offsetBase    = 0

    this.offsets      = []
    this.targets      = []
    this.scrollHeight = this.getScrollHeight()

    if (!$.isWindow(this.$scrollElement[0])) {
      offsetMethod = 'position'
      offsetBase   = this.$scrollElement.scrollTop()
    }

    this.$body
      .find(this.selector)
      .map(function () {
        var $el   = $(this)
        var href  = $el.data('target') || $el.attr('href')
        var $href = /^#./.test(href) && $(href)

        return ($href
          && $href.length
          && $href.is(':visible')
          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
      })
      .sort(function (a, b) { return a[0] - b[0] })
      .each(function () {
        that.offsets.push(this[0])
        that.targets.push(this[1])
      })
  }

  ScrollSpy.prototype.process = function () {
    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
    var scrollHeight = this.getScrollHeight()
    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
    var offsets      = this.offsets
    var targets      = this.targets
    var activeTarget = this.activeTarget
    var i

    if (this.scrollHeight != scrollHeight) {
      this.refresh()
    }

    if (scrollTop >= maxScroll) {
      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
    }

    if (activeTarget && scrollTop < offsets[0]) {
      this.activeTarget = null
      return this.clear()
    }

    for (i = offsets.length; i--;) {
      activeTarget != targets[i]
        && scrollTop >= offsets[i]
        && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
        && this.activate(targets[i])
    }
  }

  ScrollSpy.prototype.activate = function (target) {
    this.activeTarget = target

    this.clear()

    var selector = this.selector +
      '[data-target="' + target + '"],' +
      this.selector + '[href="' + target + '"]'

    var active = $(selector)
      .parents('li')
      .addClass('active')

    if (active.parent('.dropdown-menu').length) {
      active = active
        .closest('li.dropdown')
        .addClass('active')
    }

    active.trigger('activate.bs.scrollspy')
  }

  ScrollSpy.prototype.clear = function () {
    $(this.selector)
      .parentsUntil(this.options.target, '.active')
      .removeClass('active')
  }


  // SCROLLSPY PLUGIN DEFINITION
  // ===========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.scrollspy')
      var options = typeof option == 'object' && option

      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.scrollspy

  $.fn.scrollspy             = Plugin
  $.fn.scrollspy.Constructor = ScrollSpy


  // SCROLLSPY NO CONFLICT
  // =====================

  $.fn.scrollspy.noConflict = function () {
    $.fn.scrollspy = old
    return this
  }


  // SCROLLSPY DATA-API
  // ==================

  $(window).on('load.bs.scrollspy.data-api', function () {
    $('[data-spy="scroll"]').each(function () {
      var $spy = $(this)
      Plugin.call($spy, $spy.data())
    })
  })

}(jQuery);

/* ========================================================================
 * Bootstrap: tab.js v3.3.5
 * http://getbootstrap.com/javascript/#tabs
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // TAB CLASS DEFINITION
  // ====================

  var Tab = function (element) {
    // jscs:disable requireDollarBeforejQueryAssignment
    this.element = $(element)
    // jscs:enable requireDollarBeforejQueryAssignment
  }

  Tab.VERSION = '3.3.5'

  Tab.TRANSITION_DURATION = 150

  Tab.prototype.show = function () {
    var $this    = this.element
    var $ul      = $this.closest('ul:not(.dropdown-menu)')
    var selector = $this.data('target')

    if (!selector) {
      selector = $this.attr('href')
      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
    }

    if ($this.parent('li').hasClass('active')) return

    var $previous = $ul.find('.active:last a')
    var hideEvent = $.Event('hide.bs.tab', {
      relatedTarget: $this[0]
    })
    var showEvent = $.Event('show.bs.tab', {
      relatedTarget: $previous[0]
    })

    $previous.trigger(hideEvent)
    $this.trigger(showEvent)

    if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return

    var $target = $(selector)

    this.activate($this.closest('li'), $ul)
    this.activate($target, $target.parent(), function () {
      $previous.trigger({
        type: 'hidden.bs.tab',
        relatedTarget: $this[0]
      })
      $this.trigger({
        type: 'shown.bs.tab',
        relatedTarget: $previous[0]
      })
    })
  }

  Tab.prototype.activate = function (element, container, callback) {
    var $active    = container.find('> .active')
    var transition = callback
      && $.support.transition
      && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)

    function next() {
      $active
        .removeClass('active')
        .find('> .dropdown-menu > .active')
          .removeClass('active')
        .end()
        .find('[data-toggle="tab"]')
          .attr('aria-expanded', false)

      element
        .addClass('active')
        .find('[data-toggle="tab"]')
          .attr('aria-expanded', true)

      if (transition) {
        element[0].offsetWidth // reflow for transition
        element.addClass('in')
      } else {
        element.removeClass('fade')
      }

      if (element.parent('.dropdown-menu').length) {
        element
          .closest('li.dropdown')
            .addClass('active')
          .end()
          .find('[data-toggle="tab"]')
            .attr('aria-expanded', true)
      }

      callback && callback()
    }

    $active.length && transition ?
      $active
        .one('bsTransitionEnd', next)
        .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
      next()

    $active.removeClass('in')
  }


  // TAB PLUGIN DEFINITION
  // =====================

  function Plugin(option) {
    return this.each(function () {
      var $this = $(this)
      var data  = $this.data('bs.tab')

      if (!data) $this.data('bs.tab', (data = new Tab(this)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.tab

  $.fn.tab             = Plugin
  $.fn.tab.Constructor = Tab


  // TAB NO CONFLICT
  // ===============

  $.fn.tab.noConflict = function () {
    $.fn.tab = old
    return this
  }


  // TAB DATA-API
  // ============

  var clickHandler = function (e) {
    e.preventDefault()
    Plugin.call($(this), 'show')
  }

  $(document)
    .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
    .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)

}(jQuery);

/* ========================================================================
 * Bootstrap: affix.js v3.3.5
 * http://getbootstrap.com/javascript/#affix
 * ========================================================================
 * Copyright 2011-2015 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // AFFIX CLASS DEFINITION
  // ======================

  var Affix = function (element, options) {
    this.options = $.extend({}, Affix.DEFAULTS, options)

    this.$target = $(this.options.target)
      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))

    this.$element     = $(element)
    this.affixed      = null
    this.unpin        = null
    this.pinnedOffset = null

    this.checkPosition()
  }

  Affix.VERSION  = '3.3.5'

  Affix.RESET    = 'affix affix-top affix-bottom'

  Affix.DEFAULTS = {
    offset: 0,
    target: window
  }

  Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
    var scrollTop    = this.$target.scrollTop()
    var position     = this.$element.offset()
    var targetHeight = this.$target.height()

    if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false

    if (this.affixed == 'bottom') {
      if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
      return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
    }

    var initializing   = this.affixed == null
    var colliderTop    = initializing ? scrollTop : position.top
    var colliderHeight = initializing ? targetHeight : height

    if (offsetTop != null && scrollTop <= offsetTop) return 'top'
    if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'

    return false
  }

  Affix.prototype.getPinnedOffset = function () {
    if (this.pinnedOffset) return this.pinnedOffset
    this.$element.removeClass(Affix.RESET).addClass('affix')
    var scrollTop = this.$target.scrollTop()
    var position  = this.$element.offset()
    return (this.pinnedOffset = position.top - scrollTop)
  }

  Affix.prototype.checkPositionWithEventLoop = function () {
    setTimeout($.proxy(this.checkPosition, this), 1)
  }

  Affix.prototype.checkPosition = function () {
    if (!this.$element.is(':visible')) return

    var height       = this.$element.height()
    var offset       = this.options.offset
    var offsetTop    = offset.top
    var offsetBottom = offset.bottom
    var scrollHeight = Math.max($(document).height(), $(document.body).height())

    if (typeof offset != 'object')         offsetBottom = offsetTop = offset
    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)

    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)

    if (this.affixed != affix) {
      if (this.unpin != null) this.$element.css('top', '')

      var affixType = 'affix' + (affix ? '-' + affix : '')
      var e         = $.Event(affixType + '.bs.affix')

      this.$element.trigger(e)

      if (e.isDefaultPrevented()) return

      this.affixed = affix
      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null

      this.$element
        .removeClass(Affix.RESET)
        .addClass(affixType)
        .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
    }

    if (affix == 'bottom') {
      this.$element.offset({
        top: scrollHeight - height - offsetBottom
      })
    }
  }


  // AFFIX PLUGIN DEFINITION
  // =======================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.affix')
      var options = typeof option == 'object' && option

      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.affix

  $.fn.affix             = Plugin
  $.fn.affix.Constructor = Affix


  // AFFIX NO CONFLICT
  // =================

  $.fn.affix.noConflict = function () {
    $.fn.affix = old
    return this
  }


  // AFFIX DATA-API
  // ==============

  $(window).on('load', function () {
    $('[data-spy="affix"]').each(function () {
      var $spy = $(this)
      var data = $spy.data()

      data.offset = data.offset || {}

      if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
      if (data.offsetTop    != null) data.offset.top    = data.offsetTop

      Plugin.call($spy, data)
    })
  })

}(jQuery);


/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2008 George McGinley Smith
 * 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 the author nor the names of 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 THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS 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. 
 *
*/

// t: current time, b: begInnIng value, c: change In value, d: duration
jQuery.easing['jswing'] = jQuery.easing['swing'];

jQuery.extend( jQuery.easing,
{
	def: 'easeOutQuad',
	swing: function (x, t, b, c, d) {
		//alert(jQuery.easing.default);
		return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
	},
	easeInQuad: function (x, t, b, c, d) {
		return c*(t/=d)*t + b;
	},
	easeOutQuad: function (x, t, b, c, d) {
		return -c *(t/=d)*(t-2) + b;
	},
	easeInOutQuad: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t + b;
		return -c/2 * ((--t)*(t-2) - 1) + b;
	},
	easeInCubic: function (x, t, b, c, d) {
		return c*(t/=d)*t*t + b;
	},
	easeOutCubic: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t + 1) + b;
	},
	easeInOutCubic: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t + b;
		return c/2*((t-=2)*t*t + 2) + b;
	},
	easeInQuart: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t + b;
	},
	easeOutQuart: function (x, t, b, c, d) {
		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	},
	easeInOutQuart: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	},
	easeInQuint: function (x, t, b, c, d) {
		return c*(t/=d)*t*t*t*t + b;
	},
	easeOutQuint: function (x, t, b, c, d) {
		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	},
	easeInOutQuint: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
		return c/2*((t-=2)*t*t*t*t + 2) + b;
	},
	easeInSine: function (x, t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	},
	easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	},
	easeInOutSine: function (x, t, b, c, d) {
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	easeInExpo: function (x, t, b, c, d) {
		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	},
	easeOutExpo: function (x, t, b, c, d) {
		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	},
	easeInOutExpo: function (x, t, b, c, d) {
		if (t==0) return b;
		if (t==d) return b+c;
		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	},
	easeInCirc: function (x, t, b, c, d) {
		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	},
	easeOutCirc: function (x, t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	},
	easeInOutCirc: function (x, t, b, c, d) {
		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	},
	easeInElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	},
	easeOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
	},
	easeInOutElastic: function (x, t, b, c, d) {
		var s=1.70158;var p=0;var a=c;
		if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
		if (a < Math.abs(c)) { a=c; var s=p/4; }
		else var s = p/(2*Math.PI) * Math.asin (c/a);
		if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	},
	easeInBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*(t/=d)*t*((s+1)*t - s) + b;
	},
	easeOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158;
		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	},
	easeInOutBack: function (x, t, b, c, d, s) {
		if (s == undefined) s = 1.70158; 
		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	},
	easeInBounce: function (x, t, b, c, d) {
		return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
	},
	easeOutBounce: function (x, t, b, c, d) {
		if ((t/=d) < (1/2.75)) {
			return c*(7.5625*t*t) + b;
		} else if (t < (2/2.75)) {
			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
		} else if (t < (2.5/2.75)) {
			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
		} else {
			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
		}
	},
	easeInOutBounce: function (x, t, b, c, d) {
		if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
		return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
	}
});

/*
 *
 * TERMS OF USE - EASING EQUATIONS
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2001 Robert Penner
 * 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 the author nor the names of 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 THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS 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. 
 *
 */

/**

 * Project: Bootstrap Hover Dropdown

 * Author: Cameron Spear

 * Contributors: Mattia Larentis

 *

 * Dependencies: Bootstrap's Dropdown plugin, jQuery

 *

 * A simple plugin to enable Bootstrap dropdowns to active on hover and provide a nice user experience.

 *

 * License: MIT

 *

 * http://cameronspear.com/blog/bootstrap-dropdown-on-hover-plugin/

 */

;(function ($, window, undefined) {

    // outside the scope of the jQuery plugin to

    // keep track of all dropdowns

    var $allDropdowns = $();



    // if instantlyCloseOthers is true, then it will instantly

    // shut other nav items when a new one is hovered over

    $.fn.dropdownHover = function (options) {

        // don't do anything if touch is supported

        // (plugin causes some issues on mobile)

        if('ontouchstart' in document) return this; // don't want to affect chaining



        // the element we really care about

        // is the dropdown-toggle's parent

        $allDropdowns = $allDropdowns.add(this.parent());



        return this.each(function () {

            var $this = $(this),

                $parent = $this.parent(),

                defaults = {

                    delay: 500,

                    instantlyCloseOthers: true

                },

                data = {

                    delay: $(this).data('delay'),

                    instantlyCloseOthers: $(this).data('close-others')

                },

                showEvent   = 'show.bs.dropdown',

                hideEvent   = 'hide.bs.dropdown',

            // shownEvent  = 'shown.bs.dropdown',

            // hiddenEvent = 'hidden.bs.dropdown',

                settings = $.extend(true, {}, defaults, options, data),

                timeout;



            $parent.hover(function (event) {

                // so a neighbor can't open the dropdown

                if(!$parent.hasClass('open') && !$this.is(event.target)) {

                    // stop this event, stop executing any code 

                    // in this callback but continue to propagate

                    return true;

                }



                $allDropdowns.find(':focus').blur();



                if(settings.instantlyCloseOthers === true)

                    $allDropdowns.removeClass('open');



                window.clearTimeout(timeout);

                $parent.addClass('open');

                $this.trigger(showEvent);

            }, function () {

                timeout = window.setTimeout(function () {

                    $parent.removeClass('open');

                    $this.trigger(hideEvent);

                    //}, settings.delay);

                }, 200);

            });



            // this helps with button groups!

            $this.hover(function () {

                $allDropdowns.find(':focus').blur();



                if(settings.instantlyCloseOthers === true)

                    $allDropdowns.removeClass('open');



                window.clearTimeout(timeout);

                $parent.addClass('open');

                $this.trigger(showEvent);

            });



            // handle submenus

            $parent.find('.dropdown-submenu').each(function (){

                var $this = $(this);

                var subTimeout;

                $this.hover(function () {

                    window.clearTimeout(subTimeout);

                    $this.children('.dropdown-menu').show();

                    // always close submenu siblings instantly

                    $this.siblings().children('.dropdown-menu').hide();

                }, function () {

                    var $submenu = $this.children('.dropdown-menu');

                    subTimeout = window.setTimeout(function () {

                        $submenu.hide();

                    }, settings.delay);

                });

            });

        });

    };



    $(document).ready(function () {

        // apply dropdownHover to all elements with the data-hover="dropdown" attribute

        $('[data-hover="dropdown"]').dropdownHover();

    });

})(jQuery, this);

/*!
 * jQuery Cookie Plugin v1.4.1
 * https://github.com/carhartl/jquery-cookie
 *
 * Copyright 2006, 2014 Klaus Hartl
 * Released under the MIT license
 */
(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD (Register as an anonymous module)
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // Node/CommonJS
        module.exports = factory(require('jquery'));
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function ($) {

    var pluses = /\+/g;

    function encode(s) {
        return config.raw ? s : encodeURIComponent(s);
    }

    function decode(s) {
        return config.raw ? s : decodeURIComponent(s);
    }

    function stringifyCookieValue(value) {
        return encode(config.json ? JSON.stringify(value) : String(value));
    }

    function parseCookieValue(s) {
        if (s.indexOf('"') === 0) {
            // This is a quoted cookie as according to RFC2068, unescape...
            s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
        }

        try {
            // Replace server-side written pluses with spaces.
            // If we can't decode the cookie, ignore it, it's unusable.
            // If we can't parse the cookie, ignore it, it's unusable.
            s = decodeURIComponent(s.replace(pluses, ' '));
            return config.json ? JSON.parse(s) : s;
        } catch(e) {}
    }

    function read(s, converter) {
        var value = config.raw ? s : parseCookieValue(s);
        return $.isFunction(converter) ? converter(value) : value;
    }

    var config = $.cookie = function (key, value, options) {

        // Write

        if (arguments.length > 1 && !$.isFunction(value)) {
            options = $.extend({}, config.defaults, options);

            if (typeof options.expires === 'number') {
                var days = options.expires, t = options.expires = new Date();
                t.setMilliseconds(t.getMilliseconds() + days * 864e+5);
            }

            return (document.cookie = [
                encode(key), '=', stringifyCookieValue(value),
                options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
                options.path    ? '; path=' + options.path : '',
                options.domain  ? '; domain=' + options.domain : '',
                options.secure  ? '; secure' : ''
            ].join(''));
        }

        // Read

        var result = key ? undefined : {},
        // To prevent the for loop in the first place assign an empty array
        // in case there are no cookies at all. Also prevents odd result when
        // calling $.cookie().
            cookies = document.cookie ? document.cookie.split('; ') : [],
            i = 0,
            l = cookies.length;

        for (; i < l; i++) {
            var parts = cookies[i].split('='),
                name = decode(parts.shift()),
                cookie = parts.join('=');

            if (key === name) {
                // If second argument (value) is a function it's a converter...
                result = read(cookie, value);
                break;
            }

            // Prevent storing a cookie that we couldn't decode.
            if (!key && (cookie = read(cookie)) !== undefined) {
                result[name] = cookie;
            }
        }

        return result;
    };

    config.defaults = {};

    $.removeCookie = function (key, options) {
        // Must not alter options, thus extending a fresh object...
        $.cookie(key, '', $.extend({}, options, { expires: -1 }));
        return !$.cookie(key);
    };

}));

/**
 * Owl Carousel v2.1.4
 * Copyright 2013-2016 David Deutsch
 * Licensed under MIT (https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE)
 */
/**
 * Owl carousel
 * @version 2.1.0
 * @author Bartosz Wojciechowski
 * @author David Deutsch
 * @license The MIT License (MIT)
 * @todo Lazy Load Icon
 * @todo prevent animationend bubling
 * @todo itemsScaleUp
 * @todo Test Zepto
 * @todo stagePadding calculate wrong active classes
 */
;(function($, window, document, undefined) {

    /**
     * Creates a carousel.
     * @class The Owl Carousel.
     * @public
     * @param {HTMLElement|jQuery} element - The element to create the carousel for.
     * @param {Object} [options] - The options
     */
    function Owl(element, options) {

        /**
         * Current settings for the carousel.
         * @public
         */
        this.settings = null;

        /**
         * Current options set by the caller including defaults.
         * @public
         */
        this.options = $.extend({}, Owl.Defaults, options);

        /**
         * Plugin element.
         * @public
         */
        this.$element = $(element);

        /**
         * Proxied event handlers.
         * @protected
         */
        this._handlers = {};

        /**
         * References to the running plugins of this carousel.
         * @protected
         */
        this._plugins = {};

        /**
         * Currently suppressed events to prevent them from beeing retriggered.
         * @protected
         */
        this._supress = {};

        /**
         * Absolute current position.
         * @protected
         */
        this._current = null;

        /**
         * Animation speed in milliseconds.
         * @protected
         */
        this._speed = null;

        /**
         * Coordinates of all items in pixel.
         * @todo The name of this member is missleading.
         * @protected
         */
        this._coordinates = [];

        /**
         * Current breakpoint.
         * @todo Real media queries would be nice.
         * @protected
         */
        this._breakpoint = null;

        /**
         * Current width of the plugin element.
         */
        this._width = null;

        /**
         * All real items.
         * @protected
         */
        this._items = [];

        /**
         * All cloned items.
         * @protected
         */
        this._clones = [];

        /**
         * Merge values of all items.
         * @todo Maybe this could be part of a plugin.
         * @protected
         */
        this._mergers = [];

        /**
         * Widths of all items.
         */
        this._widths = [];

        /**
         * Invalidated parts within the update process.
         * @protected
         */
        this._invalidated = {};

        /**
         * Ordered list of workers for the update process.
         * @protected
         */
        this._pipe = [];

        /**
         * Current state information for the drag operation.
         * @todo #261
         * @protected
         */
        this._drag = {
            time: null,
            target: null,
            pointer: null,
            stage: {
                start: null,
                current: null
            },
            direction: null
        };

        /**
         * Current state information and their tags.
         * @type {Object}
         * @protected
         */
        this._states = {
            current: {},
            tags: {
                'initializing': [ 'busy' ],
                'animating': [ 'busy' ],
                'dragging': [ 'interacting' ]
            }
        };

        $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
            this._handlers[handler] = $.proxy(this[handler], this);
        }, this));

        $.each(Owl.Plugins, $.proxy(function(key, plugin) {
            this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
                = new plugin(this);
        }, this));

        $.each(Owl.Workers, $.proxy(function(priority, worker) {
            this._pipe.push({
                'filter': worker.filter,
                'run': $.proxy(worker.run, this)
            });
        }, this));

        this.setup();
        this.initialize();
    }

    /**
     * Default options for the carousel.
     * @public
     */
    Owl.Defaults = {
        items: 3,
        loop: false,
        center: false,
        rewind: false,

        mouseDrag: true,
        touchDrag: true,
        pullDrag: true,
        freeDrag: false,

        margin: 0,
        stagePadding: 0,

        merge: false,
        mergeFit: true,
        autoWidth: false,

        startPosition: 0,
        rtl: false,

        smartSpeed: 250,
        fluidSpeed: false,
        dragEndSpeed: false,

        responsive: {},
        responsiveRefreshRate: 200,
        responsiveBaseElement: window,

        fallbackEasing: 'swing',

        info: false,

        nestedItemSelector: false,
        itemElement: 'div',
        stageElement: 'div',

        refreshClass: 'owl-refresh',
        loadedClass: 'owl-loaded',
        loadingClass: 'owl-loading',
        rtlClass: 'owl-rtl',
        responsiveClass: 'owl-responsive',
        dragClass: 'owl-drag',
        itemClass: 'owl-item',
        stageClass: 'owl-stage',
        stageOuterClass: 'owl-stage-outer',
        grabClass: 'owl-grab'
    };

    /**
     * Enumeration for width.
     * @public
     * @readonly
     * @enum {String}
     */
    Owl.Width = {
        Default: 'default',
        Inner: 'inner',
        Outer: 'outer'
    };

    /**
     * Enumeration for types.
     * @public
     * @readonly
     * @enum {String}
     */
    Owl.Type = {
        Event: 'event',
        State: 'state'
    };

    /**
     * Contains all registered plugins.
     * @public
     */
    Owl.Plugins = {};

    /**
     * List of workers involved in the update process.
     */
    Owl.Workers = [ {
        filter: [ 'width', 'settings' ],
        run: function() {
            this._width = this.$element.width();
        }
    }, {
        filter: [ 'width', 'items', 'settings' ],
        run: function(cache) {
            cache.current = this._items && this._items[this.relative(this._current)];
        }
    }, {
        filter: [ 'items', 'settings' ],
        run: function() {
            this.$stage.children('.cloned').remove();
        }
    }, {
        filter: [ 'width', 'items', 'settings' ],
        run: function(cache) {
            var margin = this.settings.margin || '',
                grid = !this.settings.autoWidth,
                rtl = this.settings.rtl,
                css = {
                    'width': 'auto',
                    'margin-left': rtl ? margin : '',
                    'margin-right': rtl ? '' : margin
                };

            !grid && this.$stage.children().css(css);

            cache.css = css;
        }
    }, {
        filter: [ 'width', 'items', 'settings' ],
        run: function(cache) {
            var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin,
                merge = null,
                iterator = this._items.length,
                grid = !this.settings.autoWidth,
                widths = [];

            cache.items = {
                merge: false,
                width: width
            };

            while (iterator--) {
                merge = this._mergers[iterator];
                merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;

                cache.items.merge = merge > 1 || cache.items.merge;

                widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
            }

            this._widths = widths;
        }
    }, {
        filter: [ 'items', 'settings' ],
        run: function() {
            var clones = [],
                items = this._items,
                settings = this.settings,
                view = Math.max(settings.items * 2, 4),
                size = Math.ceil(items.length / 2) * 2,
                repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
                append = '',
                prepend = '';

            repeat /= 2;

            while (repeat--) {
                clones.push(this.normalize(clones.length / 2, true));
                append = append + items[clones[clones.length - 1]][0].outerHTML;
                clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
                prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
            }

            this._clones = clones;

            $(append).addClass('cloned').appendTo(this.$stage);
            $(prepend).addClass('cloned').prependTo(this.$stage);
        }
    }, {
        filter: [ 'width', 'items', 'settings' ],
        run: function() {
            var rtl = this.settings.rtl ? 1 : -1,
                size = this._clones.length + this._items.length,
                iterator = -1,
                previous = 0,
                current = 0,
                coordinates = [];

            while (++iterator < size) {
                previous = coordinates[iterator - 1] || 0;
                current = this._widths[this.relative(iterator)] + this.settings.margin;
                coordinates.push(previous + current * rtl);
            }

            this._coordinates = coordinates;
        }
    }, {
        filter: [ 'width', 'items', 'settings' ],
        run: function() {
            var padding = this.settings.stagePadding,
                coordinates = this._coordinates,
                css = {
                    'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
                    'padding-left': padding || '',
                    'padding-right': padding || ''
                };

            this.$stage.css(css);
        }
    }, {
        filter: [ 'width', 'items', 'settings' ],
        run: function(cache) {
            var iterator = this._coordinates.length,
                grid = !this.settings.autoWidth,
                items = this.$stage.children();

            if (grid && cache.items.merge) {
                while (iterator--) {
                    cache.css.width = this._widths[this.relative(iterator)];
                    items.eq(iterator).css(cache.css);
                }
            } else if (grid) {
                cache.css.width = cache.items.width;
                items.css(cache.css);
            }
        }
    }, {
        filter: [ 'items' ],
        run: function() {
            this._coordinates.length < 1 && this.$stage.removeAttr('style');
        }
    }, {
        filter: [ 'width', 'items', 'settings' ],
        run: function(cache) {
            cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
            cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
            this.reset(cache.current);
        }
    }, {
        filter: [ 'position' ],
        run: function() {
            this.animate(this.coordinates(this._current));
        }
    }, {
        filter: [ 'width', 'position', 'items', 'settings' ],
        run: function() {
            var rtl = this.settings.rtl ? 1 : -1,
                padding = this.settings.stagePadding * 2,
                begin = this.coordinates(this.current()) + padding,
                end = begin + this.width() * rtl,
                inner, outer, matches = [], i, n;

            for (i = 0, n = this._coordinates.length; i < n; i++) {
                inner = this._coordinates[i - 1] || 0;
                outer = Math.abs(this._coordinates[i]) + padding * rtl;

                if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
                    || (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
                    matches.push(i);
                }
            }

            this.$stage.children('.active').removeClass('active');
            this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');

            if (this.settings.center) {
                this.$stage.children('.center').removeClass('center');
                this.$stage.children().eq(this.current()).addClass('center');
            }
        }
    } ];

    /**
     * Initializes the carousel.
     * @protected
     */
    Owl.prototype.initialize = function() {
        this.enter('initializing');
        this.trigger('initialize');

        this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);

        if (this.settings.autoWidth && !this.is('pre-loading')) {
            var imgs, nestedSelector, width;
            imgs = this.$element.find('img');
            nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
            width = this.$element.children(nestedSelector).width();

            if (imgs.length && width <= 0) {
                this.preloadAutoWidthImages(imgs);
            }
        }

        this.$element.addClass(this.options.loadingClass);

        // create stage
        this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
            .wrap('<div class="' + this.settings.stageOuterClass + '"/>');

        // append stage
        this.$element.append(this.$stage.parent());

        // append content
        this.replace(this.$element.children().not(this.$stage.parent()));

        // check visibility
        if (this.$element.is(':visible')) {
            // update view
            this.refresh();
        } else {
            // invalidate width
            this.invalidate('width');
        }

        this.$element
            .removeClass(this.options.loadingClass)
            .addClass(this.options.loadedClass);

        // register event handlers
        this.registerEventHandlers();

        this.leave('initializing');
        this.trigger('initialized');
    };

    /**
     * Setups the current settings.
     * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
     * @todo Support for media queries by using `matchMedia` would be nice.
     * @public
     */
    Owl.prototype.setup = function() {
        var viewport = this.viewport(),
            overwrites = this.options.responsive,
            match = -1,
            settings = null;

        if (!overwrites) {
            settings = $.extend({}, this.options);
        } else {
            $.each(overwrites, function(breakpoint) {
                if (breakpoint <= viewport && breakpoint > match) {
                    match = Number(breakpoint);
                }
            });

            settings = $.extend({}, this.options, overwrites[match]);
            delete settings.responsive;

            // responsive class
            if (settings.responsiveClass) {
                this.$element.attr('class',
                    this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
                );
            }
        }

        if (this.settings === null || this._breakpoint !== match) {
            this.trigger('change', { property: { name: 'settings', value: settings } });
            this._breakpoint = match;
            this.settings = settings;
            this.invalidate('settings');
            this.trigger('changed', { property: { name: 'settings', value: this.settings } });
        }
    };

    /**
     * Updates option logic if necessery.
     * @protected
     */
    Owl.prototype.optionsLogic = function() {
        if (this.settings.autoWidth) {
            this.settings.stagePadding = false;
            this.settings.merge = false;
        }
    };

    /**
     * Prepares an item before add.
     * @todo Rename event parameter `content` to `item`.
     * @protected
     * @returns {jQuery|HTMLElement} - The item container.
     */
    Owl.prototype.prepare = function(item) {
        var event = this.trigger('prepare', { content: item });

        if (!event.data) {
            event.data = $('<' + this.settings.itemElement + '/>')
                .addClass(this.options.itemClass).append(item)
        }

        this.trigger('prepared', { content: event.data });

        return event.data;
    };

    /**
     * Updates the view.
     * @public
     */
    Owl.prototype.update = function() {
        var i = 0,
            n = this._pipe.length,
            filter = $.proxy(function(p) { return this[p] }, this._invalidated),
            cache = {};

        while (i < n) {
            if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
                this._pipe[i].run(cache);
            }
            i++;
        }

        this._invalidated = {};

        !this.is('valid') && this.enter('valid');
    };

    /**
     * Gets the width of the view.
     * @public
     * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
     * @returns {Number} - The width of the view in pixel.
     */
    Owl.prototype.width = function(dimension) {
        dimension = dimension || Owl.Width.Default;
        switch (dimension) {
            case Owl.Width.Inner:
            case Owl.Width.Outer:
                return this._width;
            default:
                return this._width - this.settings.stagePadding * 2 + this.settings.margin;
        }
    };

    /**
     * Refreshes the carousel primarily for adaptive purposes.
     * @public
     */
    Owl.prototype.refresh = function() {
        this.enter('refreshing');
        this.trigger('refresh');

        this.setup();

        this.optionsLogic();

        this.$element.addClass(this.options.refreshClass);

        this.update();

        this.$element.removeClass(this.options.refreshClass);

        this.leave('refreshing');
        this.trigger('refreshed');
    };

    /**
     * Checks window `resize` event.
     * @protected
     */
    Owl.prototype.onThrottledResize = function() {
        window.clearTimeout(this.resizeTimer);
        this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
    };

    /**
     * Checks window `resize` event.
     * @protected
     */
    Owl.prototype.onResize = function() {
        if (!this._items.length) {
            return false;
        }

        if (this._width === this.$element.width()) {
            return false;
        }

        if (!this.$element.is(':visible')) {
            return false;
        }

        this.enter('resizing');

        if (this.trigger('resize').isDefaultPrevented()) {
            this.leave('resizing');
            return false;
        }

        this.invalidate('width');

        this.refresh();

        this.leave('resizing');
        this.trigger('resized');
    };

    /**
     * Registers event handlers.
     * @todo Check `msPointerEnabled`
     * @todo #261
     * @protected
     */
    Owl.prototype.registerEventHandlers = function() {
        if ($.support.transition) {
            this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
        }

        if (this.settings.responsive !== false) {
            this.on(window, 'resize', this._handlers.onThrottledResize);
        }

        if (this.settings.mouseDrag) {
            this.$element.addClass(this.options.dragClass);
            this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
            this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
        }

        if (this.settings.touchDrag){
            this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
            this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
        }
    };

    /**
     * Handles `touchstart` and `mousedown` events.
     * @todo Horizontal swipe threshold as option
     * @todo #261
     * @protected
     * @param {Event} event - The event arguments.
     */
    Owl.prototype.onDragStart = function(event) {
        var stage = null;

        if (event.which === 3) {
            return;
        }

        if ($.support.transform) {
            stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
            stage = {
                x: stage[stage.length === 16 ? 12 : 4],
                y: stage[stage.length === 16 ? 13 : 5]
            };
        } else {
            stage = this.$stage.position();
            stage = {
                x: this.settings.rtl ?
                    stage.left + this.$stage.width() - this.width() + this.settings.margin :
                    stage.left,
                y: stage.top
            };
        }

        if (this.is('animating')) {
            $.support.transform ? this.animate(stage.x) : this.$stage.stop()
            this.invalidate('position');
        }

        this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');

        this.speed(0);

        this._drag.time = new Date().getTime();
        this._drag.target = $(event.target);
        this._drag.stage.start = stage;
        this._drag.stage.current = stage;
        this._drag.pointer = this.pointer(event);

        $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));

        $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
            var delta = this.difference(this._drag.pointer, this.pointer(event));

            $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));

            if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
                return;
            }

            event.preventDefault();

            this.enter('dragging');
            this.trigger('drag');
        }, this));
    };

    /**
     * Handles the `touchmove` and `mousemove` events.
     * @todo #261
     * @protected
     * @param {Event} event - The event arguments.
     */
    Owl.prototype.onDragMove = function(event) {
        var minimum = null,
            maximum = null,
            pull = null,
            delta = this.difference(this._drag.pointer, this.pointer(event)),
            stage = this.difference(this._drag.stage.start, delta);

        if (!this.is('dragging')) {
            return;
        }

        event.preventDefault();

        if (this.settings.loop) {
            minimum = this.coordinates(this.minimum());
            maximum = this.coordinates(this.maximum() + 1) - minimum;
            stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
        } else {
            minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
            maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
            pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
            stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
        }

        this._drag.stage.current = stage;

        this.animate(stage.x);
    };

    /**
     * Handles the `touchend` and `mouseup` events.
     * @todo #261
     * @todo Threshold for click event
     * @protected
     * @param {Event} event - The event arguments.
     */
    Owl.prototype.onDragEnd = function(event) {
        var delta = this.difference(this._drag.pointer, this.pointer(event)),
            stage = this._drag.stage.current,
            direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';

        $(document).off('.owl.core');

        this.$element.removeClass(this.options.grabClass);

        if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
            this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
            this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
            this.invalidate('position');
            this.update();

            this._drag.direction = direction;

            if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
                this._drag.target.one('click.owl.core', function() { return false; });
            }
        }

        if (!this.is('dragging')) {
            return;
        }

        this.leave('dragging');
        this.trigger('dragged');
    };

    /**
     * Gets absolute position of the closest item for a coordinate.
     * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
     * @protected
     * @param {Number} coordinate - The coordinate in pixel.
     * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
     * @return {Number} - The absolute position of the closest item.
     */
    Owl.prototype.closest = function(coordinate, direction) {
        var position = -1,
            pull = 30,
            width = this.width(),
            coordinates = this.coordinates();

        if (!this.settings.freeDrag) {
            // check closest item
            $.each(coordinates, $.proxy(function(index, value) {
                // on a left pull, check on current index
                if (direction === 'left' && coordinate > value - pull && coordinate < value + pull) {
                    position = index;
                    // on a right pull, check on previous index
                    // to do so, subtract width from value and set position = index + 1
                } else if (direction === 'right' && coordinate > value - width - pull && coordinate < value - width + pull) {
                    position = index + 1;
                } else if (this.op(coordinate, '<', value)
                    && this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
                    position = direction === 'left' ? index + 1 : index;
                }
                return position === -1;
            }, this));
        }

        if (!this.settings.loop) {
            // non loop boundries
            if (this.op(coordinate, '>', coordinates[this.minimum()])) {
                position = coordinate = this.minimum();
            } else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
                position = coordinate = this.maximum();
            }
        }

        return position;
    };

    /**
     * Animates the stage.
     * @todo #270
     * @public
     * @param {Number} coordinate - The coordinate in pixels.
     */
    Owl.prototype.animate = function(coordinate) {
        var animate = this.speed() > 0;

        this.is('animating') && this.onTransitionEnd();

        if (animate) {
            this.enter('animating');
            this.trigger('translate');
        }

        if ($.support.transform3d && $.support.transition) {
            this.$stage.css({
                transform: 'translate3d(' + coordinate + 'px,0px,0px)',
                transition: (this.speed() / 1000) + 's'
            });
        } else if (animate) {
            this.$stage.animate({
                left: coordinate + 'px'
            }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
        } else {
            this.$stage.css({
                left: coordinate + 'px'
            });
        }
    };

    /**
     * Checks whether the carousel is in a specific state or not.
     * @param {String} state - The state to check.
     * @returns {Boolean} - The flag which indicates if the carousel is busy.
     */
    Owl.prototype.is = function(state) {
        return this._states.current[state] && this._states.current[state] > 0;
    };

    /**
     * Sets the absolute position of the current item.
     * @public
     * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
     * @returns {Number} - The absolute position of the current item.
     */
    Owl.prototype.current = function(position) {
        if (position === undefined) {
            return this._current;
        }

        if (this._items.length === 0) {
            return undefined;
        }

        position = this.normalize(position);

        if (this._current !== position) {
            var event = this.trigger('change', { property: { name: 'position', value: position } });

            if (event.data !== undefined) {
                position = this.normalize(event.data);
            }

            this._current = position;

            this.invalidate('position');

            this.trigger('changed', { property: { name: 'position', value: this._current } });
        }

        return this._current;
    };

    /**
     * Invalidates the given part of the update routine.
     * @param {String} [part] - The part to invalidate.
     * @returns {Array.<String>} - The invalidated parts.
     */
    Owl.prototype.invalidate = function(part) {
        if ($.type(part) === 'string') {
            this._invalidated[part] = true;
            this.is('valid') && this.leave('valid');
        }
        return $.map(this._invalidated, function(v, i) { return i });
    };

    /**
     * Resets the absolute position of the current item.
     * @public
     * @param {Number} position - The absolute position of the new item.
     */
    Owl.prototype.reset = function(position) {
        position = this.normalize(position);

        if (position === undefined) {
            return;
        }

        this._speed = 0;
        this._current = position;

        this.suppress([ 'translate', 'translated' ]);

        this.animate(this.coordinates(position));

        this.release([ 'translate', 'translated' ]);
    };

    /**
     * Normalizes an absolute or a relative position of an item.
     * @public
     * @param {Number} position - The absolute or relative position to normalize.
     * @param {Boolean} [relative=false] - Whether the given position is relative or not.
     * @returns {Number} - The normalized position.
     */
    Owl.prototype.normalize = function(position, relative) {
        var n = this._items.length,
            m = relative ? 0 : this._clones.length;

        if (!this.isNumeric(position) || n < 1) {
            position = undefined;
        } else if (position < 0 || position >= n + m) {
            position = ((position - m / 2) % n + n) % n + m / 2;
        }

        return position;
    };

    /**
     * Converts an absolute position of an item into a relative one.
     * @public
     * @param {Number} position - The absolute position to convert.
     * @returns {Number} - The converted position.
     */
    Owl.prototype.relative = function(position) {
        position -= this._clones.length / 2;
        return this.normalize(position, true);
    };

    /**
     * Gets the maximum position for the current item.
     * @public
     * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
     * @returns {Number}
     */
    Owl.prototype.maximum = function(relative) {
        var settings = this.settings,
            maximum = this._coordinates.length,
            boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
            i = -1, j;

        if (settings.loop) {
            maximum = this._clones.length / 2 + this._items.length - 1;
        } else if (settings.autoWidth || settings.merge) {
            // binary search
            while (maximum - i > 1) {
                Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
                    ? i = j : maximum = j;
            }
        } else if (settings.center) {
            maximum = this._items.length - 1;
        } else {
            maximum = this._items.length - settings.items;
        }

        if (relative) {
            maximum -= this._clones.length / 2;
        }

        return Math.max(maximum, 0);
    };

    /**
     * Gets the minimum position for the current item.
     * @public
     * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
     * @returns {Number}
     */
    Owl.prototype.minimum = function(relative) {
        return relative ? 0 : this._clones.length / 2;
    };

    /**
     * Gets an item at the specified relative position.
     * @public
     * @param {Number} [position] - The relative position of the item.
     * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
     */
    Owl.prototype.items = function(position) {
        if (position === undefined) {
            return this._items.slice();
        }

        position = this.normalize(position, true);
        return this._items[position];
    };

    /**
     * Gets an item at the specified relative position.
     * @public
     * @param {Number} [position] - The relative position of the item.
     * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
     */
    Owl.prototype.mergers = function(position) {
        if (position === undefined) {
            return this._mergers.slice();
        }

        position = this.normalize(position, true);
        return this._mergers[position];
    };

    /**
     * Gets the absolute positions of clones for an item.
     * @public
     * @param {Number} [position] - The relative position of the item.
     * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
     */
    Owl.prototype.clones = function(position) {
        var odd = this._clones.length / 2,
            even = odd + this._items.length,
            map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };

        if (position === undefined) {
            return $.map(this._clones, function(v, i) { return map(i) });
        }

        return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
    };

    /**
     * Sets the current animation speed.
     * @public
     * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
     * @returns {Number} - The current animation speed in milliseconds.
     */
    Owl.prototype.speed = function(speed) {
        if (speed !== undefined) {
            this._speed = speed;
        }

        return this._speed;
    };

    /**
     * Gets the coordinate of an item.
     * @todo The name of this method is missleanding.
     * @public
     * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
     * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
     */
    Owl.prototype.coordinates = function(position) {
        var multiplier = 1,
            newPosition = position - 1,
            coordinate;

        if (position === undefined) {
            return $.map(this._coordinates, $.proxy(function(coordinate, index) {
                return this.coordinates(index);
            }, this));
        }

        if (this.settings.center) {
            if (this.settings.rtl) {
                multiplier = -1;
                newPosition = position + 1;
            }

            coordinate = this._coordinates[position];
            coordinate += (this.width() - coordinate + (this._coordinates[newPosition] || 0)) / 2 * multiplier;
        } else {
            coordinate = this._coordinates[newPosition] || 0;
        }

        coordinate = Math.ceil(coordinate);

        return coordinate;
    };

    /**
     * Calculates the speed for a translation.
     * @protected
     * @param {Number} from - The absolute position of the start item.
     * @param {Number} to - The absolute position of the target item.
     * @param {Number} [factor=undefined] - The time factor in milliseconds.
     * @returns {Number} - The time in milliseconds for the translation.
     */
    Owl.prototype.duration = function(from, to, factor) {
        if (factor === 0) {
            return 0;
        }

        return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
    };

    /**
     * Slides to the specified item.
     * @public
     * @param {Number} position - The position of the item.
     * @param {Number} [speed] - The time in milliseconds for the transition.
     */
    Owl.prototype.to = function(position, speed) {
        var current = this.current(),
            revert = null,
            distance = position - this.relative(current),
            direction = (distance > 0) - (distance < 0),
            items = this._items.length,
            minimum = this.minimum(),
            maximum = this.maximum();

        if (this.settings.loop) {
            if (!this.settings.rewind && Math.abs(distance) > items / 2) {
                distance += direction * -1 * items;
            }

            position = current + distance;
            revert = ((position - minimum) % items + items) % items + minimum;

            if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
                current = revert - distance;
                position = revert;
                this.reset(current);
            }
        } else if (this.settings.rewind) {
            maximum += 1;
            position = (position % maximum + maximum) % maximum;
        } else {
            position = Math.max(minimum, Math.min(maximum, position));
        }

        this.speed(this.duration(current, position, speed));
        this.current(position);

        if (this.$element.is(':visible')) {
            this.update();
        }
    };

    /**
     * Slides to the next item.
     * @public
     * @param {Number} [speed] - The time in milliseconds for the transition.
     */
    Owl.prototype.next = function(speed) {
        speed = speed || false;
        this.to(this.relative(this.current()) + 1, speed);
    };

    /**
     * Slides to the previous item.
     * @public
     * @param {Number} [speed] - The time in milliseconds for the transition.
     */
    Owl.prototype.prev = function(speed) {
        speed = speed || false;
        this.to(this.relative(this.current()) - 1, speed);
    };

    /**
     * Handles the end of an animation.
     * @protected
     * @param {Event} event - The event arguments.
     */
    Owl.prototype.onTransitionEnd = function(event) {

        // if css2 animation then event object is undefined
        if (event !== undefined) {
            event.stopPropagation();

            // Catch only owl-stage transitionEnd event
            if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
                return false;
            }
        }

        this.leave('animating');
        this.trigger('translated');
    };

    /**
     * Gets viewport width.
     * @protected
     * @return {Number} - The width in pixel.
     */
    Owl.prototype.viewport = function() {
        var width;
        if (this.options.responsiveBaseElement !== window) {
            width = $(this.options.responsiveBaseElement).width();
        } else if (window.innerWidth) {
            width = window.innerWidth;
        } else if (document.documentElement && document.documentElement.clientWidth) {
            width = document.documentElement.clientWidth;
        } else {
            throw 'Can not detect viewport width.';
        }
        return width;
    };

    /**
     * Replaces the current content.
     * @public
     * @param {HTMLElement|jQuery|String} content - The new content.
     */
    Owl.prototype.replace = function(content) {
        this.$stage.empty();
        this._items = [];

        if (content) {
            content = (content instanceof jQuery) ? content : $(content);
        }

        if (this.settings.nestedItemSelector) {
            content = content.find('.' + this.settings.nestedItemSelector);
        }

        content.filter(function() {
            return this.nodeType === 1;
        }).each($.proxy(function(index, item) {
                item = this.prepare(item);
                this.$stage.append(item);
                this._items.push(item);
                this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
            }, this));

        this.reset(this.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);

        this.invalidate('items');
    };

    /**
     * Adds an item.
     * @todo Use `item` instead of `content` for the event arguments.
     * @public
     * @param {HTMLElement|jQuery|String} content - The item content to add.
     * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
     */
    Owl.prototype.add = function(content, position) {
        var current = this.relative(this._current);

        position = position === undefined ? this._items.length : this.normalize(position, true);
        content = content instanceof jQuery ? content : $(content);

        this.trigger('add', { content: content, position: position });

        content = this.prepare(content);

        if (this._items.length === 0 || position === this._items.length) {
            this._items.length === 0 && this.$stage.append(content);
            this._items.length !== 0 && this._items[position - 1].after(content);
            this._items.push(content);
            this._mergers.push(content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
        } else {
            this._items[position].before(content);
            this._items.splice(position, 0, content);
            this._mergers.splice(position, 0, content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
        }

        this._items[current] && this.reset(this._items[current].index());

        this.invalidate('items');

        this.trigger('added', { content: content, position: position });
    };

    /**
     * Removes an item by its position.
     * @todo Use `item` instead of `content` for the event arguments.
     * @public
     * @param {Number} position - The relative position of the item to remove.
     */
    Owl.prototype.remove = function(position) {
        position = this.normalize(position, true);

        if (position === undefined) {
            return;
        }

        this.trigger('remove', { content: this._items[position], position: position });

        this._items[position].remove();
        this._items.splice(position, 1);
        this._mergers.splice(position, 1);

        this.invalidate('items');

        this.trigger('removed', { content: null, position: position });
    };

    /**
     * Preloads images with auto width.
     * @todo Replace by a more generic approach
     * @protected
     */
    Owl.prototype.preloadAutoWidthImages = function(images) {
        images.each($.proxy(function(i, element) {
            this.enter('pre-loading');
            element = $(element);
            $(new Image()).one('load', $.proxy(function(e) {
                element.attr('src', e.target.src);
                element.css('opacity', 1);
                this.leave('pre-loading');
                !this.is('pre-loading') && !this.is('initializing') && this.refresh();
            }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
        }, this));
    };

    /**
     * Destroys the carousel.
     * @public
     */
    Owl.prototype.destroy = function() {

        this.$element.off('.owl.core');
        this.$stage.off('.owl.core');
        $(document).off('.owl.core');

        if (this.settings.responsive !== false) {
            window.clearTimeout(this.resizeTimer);
            this.off(window, 'resize', this._handlers.onThrottledResize);
        }

        for (var i in this._plugins) {
            this._plugins[i].destroy();
        }

        this.$stage.children('.cloned').remove();

        this.$stage.unwrap();
        this.$stage.children().contents().unwrap();
        this.$stage.children().unwrap();

        this.$element
            .removeClass(this.options.refreshClass)
            .removeClass(this.options.loadingClass)
            .removeClass(this.options.loadedClass)
            .removeClass(this.options.rtlClass)
            .removeClass(this.options.dragClass)
            .removeClass(this.options.grabClass)
            .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
            .removeData('owl.carousel');
    };

    /**
     * Operators to calculate right-to-left and left-to-right.
     * @protected
     * @param {Number} [a] - The left side operand.
     * @param {String} [o] - The operator.
     * @param {Number} [b] - The right side operand.
     */
    Owl.prototype.op = function(a, o, b) {
        var rtl = this.settings.rtl;
        switch (o) {
            case '<':
                return rtl ? a > b : a < b;
            case '>':
                return rtl ? a < b : a > b;
            case '>=':
                return rtl ? a <= b : a >= b;
            case '<=':
                return rtl ? a >= b : a <= b;
            default:
                break;
        }
    };

    /**
     * Attaches to an internal event.
     * @protected
     * @param {HTMLElement} element - The event source.
     * @param {String} event - The event name.
     * @param {Function} listener - The event handler to attach.
     * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
     */
    Owl.prototype.on = function(element, event, listener, capture) {
        if (element.addEventListener) {
            element.addEventListener(event, listener, capture);
        } else if (element.attachEvent) {
            element.attachEvent('on' + event, listener);
        }
    };

    /**
     * Detaches from an internal event.
     * @protected
     * @param {HTMLElement} element - The event source.
     * @param {String} event - The event name.
     * @param {Function} listener - The attached event handler to detach.
     * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
     */
    Owl.prototype.off = function(element, event, listener, capture) {
        if (element.removeEventListener) {
            element.removeEventListener(event, listener, capture);
        } else if (element.detachEvent) {
            element.detachEvent('on' + event, listener);
        }
    };

    /**
     * Triggers a public event.
     * @todo Remove `status`, `relatedTarget` should be used instead.
     * @protected
     * @param {String} name - The event name.
     * @param {*} [data=null] - The event data.
     * @param {String} [namespace=carousel] - The event namespace.
     * @param {String} [state] - The state which is associated with the event.
     * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
     * @returns {Event} - The event arguments.
     */
    Owl.prototype.trigger = function(name, data, namespace, state, enter) {
        var status = {
            item: { count: this._items.length, index: this.current() }
        }, handler = $.camelCase(
            $.grep([ 'on', name, namespace ], function(v) { return v })
                .join('-').toLowerCase()
        ), event = $.Event(
            [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
            $.extend({ relatedTarget: this }, status, data)
        );

        if (!this._supress[name]) {
            $.each(this._plugins, function(name, plugin) {
                if (plugin.onTrigger) {
                    plugin.onTrigger(event);
                }
            });

            this.register({ type: Owl.Type.Event, name: name });
            this.$element.trigger(event);

            if (this.settings && typeof this.settings[handler] === 'function') {
                this.settings[handler].call(this, event);
            }
        }

        return event;
    };

    /**
     * Enters a state.
     * @param name - The state name.
     */
    Owl.prototype.enter = function(name) {
        $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
            if (this._states.current[name] === undefined) {
                this._states.current[name] = 0;
            }

            this._states.current[name]++;
        }, this));
    };

    /**
     * Leaves a state.
     * @param name - The state name.
     */
    Owl.prototype.leave = function(name) {
        $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
            this._states.current[name]--;
        }, this));
    };

    /**
     * Registers an event or state.
     * @public
     * @param {Object} object - The event or state to register.
     */
    Owl.prototype.register = function(object) {
        if (object.type === Owl.Type.Event) {
            if (!$.event.special[object.name]) {
                $.event.special[object.name] = {};
            }

            if (!$.event.special[object.name].owl) {
                var _default = $.event.special[object.name]._default;
                $.event.special[object.name]._default = function(e) {
                    if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
                        return _default.apply(this, arguments);
                    }
                    return e.namespace && e.namespace.indexOf('owl') > -1;
                };
                $.event.special[object.name].owl = true;
            }
        } else if (object.type === Owl.Type.State) {
            if (!this._states.tags[object.name]) {
                this._states.tags[object.name] = object.tags;
            } else {
                this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
            }

            this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
                return $.inArray(tag, this._states.tags[object.name]) === i;
            }, this));
        }
    };

    /**
     * Suppresses events.
     * @protected
     * @param {Array.<String>} events - The events to suppress.
     */
    Owl.prototype.suppress = function(events) {
        $.each(events, $.proxy(function(index, event) {
            this._supress[event] = true;
        }, this));
    };

    /**
     * Releases suppressed events.
     * @protected
     * @param {Array.<String>} events - The events to release.
     */
    Owl.prototype.release = function(events) {
        $.each(events, $.proxy(function(index, event) {
            delete this._supress[event];
        }, this));
    };

    /**
     * Gets unified pointer coordinates from event.
     * @todo #261
     * @protected
     * @param {Event} - The `mousedown` or `touchstart` event.
     * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
     */
    Owl.prototype.pointer = function(event) {
        var result = { x: null, y: null };

        event = event.originalEvent || event || window.event;

        event = event.touches && event.touches.length ?
            event.touches[0] : event.changedTouches && event.changedTouches.length ?
            event.changedTouches[0] : event;

        if (event.pageX) {
            result.x = event.pageX;
            result.y = event.pageY;
        } else {
            result.x = event.clientX;
            result.y = event.clientY;
        }

        return result;
    };

    /**
     * Determines if the input is a Number or something that can be coerced to a Number
     * @protected
     * @param {Number|String|Object|Array|Boolean|RegExp|Function|Symbol} - The input to be tested
     * @returns {Boolean} - An indication if the input is a Number or can be coerced to a Number
     */
    Owl.prototype.isNumeric = function(number) {
        return !isNaN(parseFloat(number));
    };

    /**
     * Gets the difference of two vectors.
     * @todo #261
     * @protected
     * @param {Object} - The first vector.
     * @param {Object} - The second vector.
     * @returns {Object} - The difference.
     */
    Owl.prototype.difference = function(first, second) {
        return {
            x: first.x - second.x,
            y: first.y - second.y
        };
    };

    /**
     * The jQuery Plugin for the Owl Carousel
     * @todo Navigation plugin `next` and `prev`
     * @public
     */
    $.fn.owlCarousel = function(option) {
        var args = Array.prototype.slice.call(arguments, 1);

        return this.each(function() {
            var $this = $(this),
                data = $this.data('owl.carousel');

            if (!data) {
                data = new Owl(this, typeof option == 'object' && option);
                $this.data('owl.carousel', data);

                $.each([
                    'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
                ], function(i, event) {
                    data.register({ type: Owl.Type.Event, name: event });
                    data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
                        if (e.namespace && e.relatedTarget !== this) {
                            this.suppress([ event ]);
                            data[event].apply(this, [].slice.call(arguments, 1));
                            this.release([ event ]);
                        }
                    }, data));
                });
            }

            if (typeof option == 'string' && option.charAt(0) !== '_') {
                data[option].apply(data, args);
            }
        });
    };

    /**
     * The constructor for the jQuery Plugin
     * @public
     */
    $.fn.owlCarousel.Constructor = Owl;

})(window.Zepto || window.jQuery, window, document);

/**
 * AutoRefresh Plugin
 * @version 2.1.0
 * @author Artus Kolanowski
 * @author David Deutsch
 * @license The MIT License (MIT)
 */
;(function($, window, document, undefined) {

    /**
     * Creates the auto refresh plugin.
     * @class The Auto Refresh Plugin
     * @param {Owl} carousel - The Owl Carousel
     */
    var AutoRefresh = function(carousel) {
        /**
         * Reference to the core.
         * @protected
         * @type {Owl}
         */
        this._core = carousel;

        /**
         * Refresh interval.
         * @protected
         * @type {number}
         */
        this._interval = null;

        /**
         * Whether the element is currently visible or not.
         * @protected
         * @type {Boolean}
         */
        this._visible = null;

        /**
         * All event handlers.
         * @protected
         * @type {Object}
         */
        this._handlers = {
            'initialized.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this._core.settings.autoRefresh) {
                    this.watch();
                }
            }, this)
        };

        // set default options
        this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);

        // register event handlers
        this._core.$element.on(this._handlers);
    };

    /**
     * Default options.
     * @public
     */
    AutoRefresh.Defaults = {
        autoRefresh: true,
        autoRefreshInterval: 500
    };

    /**
     * Watches the element.
     */
    AutoRefresh.prototype.watch = function() {
        if (this._interval) {
            return;
        }

        this._visible = this._core.$element.is(':visible');
        this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
    };

    /**
     * Refreshes the element.
     */
    AutoRefresh.prototype.refresh = function() {
        if (this._core.$element.is(':visible') === this._visible) {
            return;
        }

        this._visible = !this._visible;

        this._core.$element.toggleClass('owl-hidden', !this._visible);

        this._visible && (this._core.invalidate('width') && this._core.refresh());
    };

    /**
     * Destroys the plugin.
     */
    AutoRefresh.prototype.destroy = function() {
        var handler, property;

        window.clearInterval(this._interval);

        for (handler in this._handlers) {
            this._core.$element.off(handler, this._handlers[handler]);
        }
        for (property in Object.getOwnPropertyNames(this)) {
            typeof this[property] != 'function' && (this[property] = null);
        }
    };

    $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;

})(window.Zepto || window.jQuery, window, document);

/**
 * Lazy Plugin
 * @version 2.1.0
 * @author Bartosz Wojciechowski
 * @author David Deutsch
 * @license The MIT License (MIT)
 */
;(function($, window, document, undefined) {

    /**
     * Creates the lazy plugin.
     * @class The Lazy Plugin
     * @param {Owl} carousel - The Owl Carousel
     */
    var Lazy = function(carousel) {

        /**
         * Reference to the core.
         * @protected
         * @type {Owl}
         */
        this._core = carousel;

        /**
         * Already loaded items.
         * @protected
         * @type {Array.<jQuery>}
         */
        this._loaded = [];

        /**
         * Event handlers.
         * @protected
         * @type {Object}
         */
        this._handlers = {
            'initialized.owl.carousel change.owl.carousel resized.owl.carousel': $.proxy(function(e) {
                if (!e.namespace) {
                    return;
                }

                if (!this._core.settings || !this._core.settings.lazyLoad) {
                    return;
                }

                if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
                    var settings = this._core.settings,
                        n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
                        i = ((settings.center && n * -1) || 0),
                        position = (e.property && e.property.value !== undefined ? e.property.value : this._core.current()) + i,
                        clones = this._core.clones().length,
                        load = $.proxy(function(i, v) { this.load(v) }, this);

                    while (i++ < n) {
                        this.load(clones / 2 + this._core.relative(position));
                        clones && $.each(this._core.clones(this._core.relative(position)), load);
                        position++;
                    }
                }
            }, this)
        };

        // set the default options
        this._core.options = $.extend({}, Lazy.Defaults, this._core.options);

        // register event handler
        this._core.$element.on(this._handlers);
    };

    /**
     * Default options.
     * @public
     */
    Lazy.Defaults = {
        lazyLoad: false
    };

    /**
     * Loads all resources of an item at the specified position.
     * @param {Number} position - The absolute position of the item.
     * @protected
     */
    Lazy.prototype.load = function(position) {
        var $item = this._core.$stage.children().eq(position),
            $elements = $item && $item.find('.owl-lazy');

        if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
            return;
        }

        $elements.each($.proxy(function(index, element) {
            var $element = $(element), image,
                url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');

            this._core.trigger('load', { element: $element, url: url }, 'lazy');

            if ($element.is('img')) {
                $element.one('load.owl.lazy', $.proxy(function() {
                    $element.css('opacity', 1);
                    this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
                }, this)).attr('src', url);
            } else {
                image = new Image();
                image.onload = $.proxy(function() {
                    $element.css({
                        'background-image': 'url(' + url + ')',
                        'opacity': '1'
                    });
                    this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
                }, this);
                image.src = url;
            }
        }, this));

        this._loaded.push($item.get(0));
    };

    /**
     * Destroys the plugin.
     * @public
     */
    Lazy.prototype.destroy = function() {
        var handler, property;

        for (handler in this.handlers) {
            this._core.$element.off(handler, this.handlers[handler]);
        }
        for (property in Object.getOwnPropertyNames(this)) {
            typeof this[property] != 'function' && (this[property] = null);
        }
    };

    $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;

})(window.Zepto || window.jQuery, window, document);

/**
 * AutoHeight Plugin
 * @version 2.1.0
 * @author Bartosz Wojciechowski
 * @author David Deutsch
 * @license The MIT License (MIT)
 */
;(function($, window, document, undefined) {

    /**
     * Creates the auto height plugin.
     * @class The Auto Height Plugin
     * @param {Owl} carousel - The Owl Carousel
     */
    var AutoHeight = function(carousel) {
        /**
         * Reference to the core.
         * @protected
         * @type {Owl}
         */
        this._core = carousel;

        /**
         * All event handlers.
         * @protected
         * @type {Object}
         */
        this._handlers = {
            'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this._core.settings.autoHeight) {
                    this.update();
                }
            }, this),
            'changed.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
                    this.update();
                }
            }, this),
            'loaded.owl.lazy': $.proxy(function(e) {
                if (e.namespace && this._core.settings.autoHeight
                    && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
                    this.update();
                }
            }, this)
        };

        // set default options
        this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);

        // register event handlers
        this._core.$element.on(this._handlers);
    };

    /**
     * Default options.
     * @public
     */
    AutoHeight.Defaults = {
        autoHeight: false,
        autoHeightClass: 'owl-height'
    };

    /**
     * Updates the view.
     */
    AutoHeight.prototype.update = function() {
        var start = this._core._current,
            end = start + this._core.settings.items,
            visible = this._core.$stage.children().toArray().slice(start, end),
            heights = [],
            maxheight = 0;

        $.each(visible, function(index, item) {
            heights.push($(item).height());
        });

        maxheight = Math.max.apply(null, heights);

        this._core.$stage.parent()
            .height(maxheight)
            .addClass(this._core.settings.autoHeightClass);
    };

    AutoHeight.prototype.destroy = function() {
        var handler, property;

        for (handler in this._handlers) {
            this._core.$element.off(handler, this._handlers[handler]);
        }
        for (property in Object.getOwnPropertyNames(this)) {
            typeof this[property] != 'function' && (this[property] = null);
        }
    };

    $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;

})(window.Zepto || window.jQuery, window, document);

/**
 * Video Plugin
 * @version 2.1.0
 * @author Bartosz Wojciechowski
 * @author David Deutsch
 * @license The MIT License (MIT)
 */
;(function($, window, document, undefined) {

    /**
     * Creates the video plugin.
     * @class The Video Plugin
     * @param {Owl} carousel - The Owl Carousel
     */
    var Video = function(carousel) {
        /**
         * Reference to the core.
         * @protected
         * @type {Owl}
         */
        this._core = carousel;

        /**
         * Cache all video URLs.
         * @protected
         * @type {Object}
         */
        this._videos = {};

        /**
         * Current playing item.
         * @protected
         * @type {jQuery}
         */
        this._playing = null;

        /**
         * All event handlers.
         * @todo The cloned content removale is too late
         * @protected
         * @type {Object}
         */
        this._handlers = {
            'initialized.owl.carousel': $.proxy(function(e) {
                if (e.namespace) {
                    this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
                }
            }, this),
            'resize.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
                    e.preventDefault();
                }
            }, this),
            'refreshed.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this._core.is('resizing')) {
                    this._core.$stage.find('.cloned .owl-video-frame').remove();
                }
            }, this),
            'changed.owl.carousel': $.proxy(function(e) {
                if (e.namespace && e.property.name === 'position' && this._playing) {
                    this.stop();
                }
            }, this),
            'prepared.owl.carousel': $.proxy(function(e) {
                if (!e.namespace) {
                    return;
                }

                var $element = $(e.content).find('.owl-video');

                if ($element.length) {
                    $element.css('display', 'none');
                    this.fetch($element, $(e.content));
                }
            }, this)
        };

        // set default options
        this._core.options = $.extend({}, Video.Defaults, this._core.options);

        // register event handlers
        this._core.$element.on(this._handlers);

        this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
            this.play(e);
        }, this));
    };

    /**
     * Default options.
     * @public
     */
    Video.Defaults = {
        video: false,
        videoHeight: false,
        videoWidth: false
    };

    /**
     * Gets the video ID and the type (YouTube/Vimeo/vzaar only).
     * @protected
     * @param {jQuery} target - The target containing the video data.
     * @param {jQuery} item - The item containing the video.
     */
    Video.prototype.fetch = function(target, item) {
        var type = (function() {
                if (target.attr('data-vimeo-id')) {
                    return 'vimeo';
                } else if (target.attr('data-vzaar-id')) {
                    return 'vzaar'
                } else {
                    return 'youtube';
                }
            })(),
            id = target.attr('data-vimeo-id') || target.attr('data-youtube-id') || target.attr('data-vzaar-id'),
            width = target.attr('data-width') || this._core.settings.videoWidth,
            height = target.attr('data-height') || this._core.settings.videoHeight,
            url = target.attr('href');

        if (url) {

            /*
             Parses the id's out of the following urls (and probably more):
             https://www.youtube.com/watch?v=:id
             https://youtu.be/:id
             https://vimeo.com/:id
             https://vimeo.com/channels/:channel/:id
             https://vimeo.com/groups/:group/videos/:id
             https://app.vzaar.com/videos/:id

             Visual example: https://regexper.com/#(http%3A%7Chttps%3A%7C)%5C%2F%5C%2F(player.%7Cwww.%7Capp.)%3F(vimeo%5C.com%7Cyoutu(be%5C.com%7C%5C.be%7Cbe%5C.googleapis%5C.com)%7Cvzaar%5C.com)%5C%2F(video%5C%2F%7Cvideos%5C%2F%7Cembed%5C%2F%7Cchannels%5C%2F.%2B%5C%2F%7Cgroups%5C%2F.%2B%5C%2F%7Cwatch%5C%3Fv%3D%7Cv%5C%2F)%3F(%5BA-Za-z0-9._%25-%5D*)(%5C%26%5CS%2B)%3F
             */

            id = url.match(/(http:|https:|)\/\/(player.|www.|app.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com)|vzaar\.com)\/(video\/|videos\/|embed\/|channels\/.+\/|groups\/.+\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/);

            if (id[3].indexOf('youtu') > -1) {
                type = 'youtube';
            } else if (id[3].indexOf('vimeo') > -1) {
                type = 'vimeo';
            } else if (id[3].indexOf('vzaar') > -1) {
                type = 'vzaar';
            } else {
                throw new Error('Video URL not supported.');
            }
            id = id[6];
        } else {
            throw new Error('Missing video URL.');
        }

        this._videos[url] = {
            type: type,
            id: id,
            width: width,
            height: height
        };

        item.attr('data-video', url);

        this.thumbnail(target, this._videos[url]);
    };

    /**
     * Creates video thumbnail.
     * @protected
     * @param {jQuery} target - The target containing the video data.
     * @param {Object} info - The video info object.
     * @see `fetch`
     */
    Video.prototype.thumbnail = function(target, video) {
        var tnLink,
            icon,
            path,
            dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
            customTn = target.find('img'),
            srcType = 'src',
            lazyClass = '',
            settings = this._core.settings,
            create = function(path) {
                icon = '<div class="owl-video-play-icon"></div>';

                if (settings.lazyLoad) {
                    tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
                } else {
                    tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
                }
                target.after(tnLink);
                target.after(icon);
            };

        // wrap video content into owl-video-wrapper div
        target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');

        if (this._core.settings.lazyLoad) {
            srcType = 'data-src';
            lazyClass = 'owl-lazy';
        }

        // custom thumbnail
        if (customTn.length) {
            create(customTn.attr(srcType));
            customTn.remove();
            return false;
        }

        if (video.type === 'youtube') {
            path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
            create(path);
        } else if (video.type === 'vimeo') {
            $.ajax({
                type: 'GET',
                url: '//vimeo.com/api/v2/video/' + video.id + '.json',
                jsonp: 'callback',
                dataType: 'jsonp',
                success: function(data) {
                    path = data[0].thumbnail_large;
                    create(path);
                }
            });
        } else if (video.type === 'vzaar') {
            $.ajax({
                type: 'GET',
                url: '//vzaar.com/api/videos/' + video.id + '.json',
                jsonp: 'callback',
                dataType: 'jsonp',
                success: function(data) {
                    path = data.framegrab_url;
                    create(path);
                }
            });
        }
    };

    /**
     * Stops the current video.
     * @public
     */
    Video.prototype.stop = function() {
        this._core.trigger('stop', null, 'video');
        this._playing.find('.owl-video-frame').remove();
        this._playing.removeClass('owl-video-playing');
        this._playing = null;
        this._core.leave('playing');
        this._core.trigger('stopped', null, 'video');
    };

    /**
     * Starts the current video.
     * @public
     * @param {Event} event - The event arguments.
     */
    Video.prototype.play = function(event) {
        var target = $(event.target),
            item = target.closest('.' + this._core.settings.itemClass),
            video = this._videos[item.attr('data-video')],
            width = video.width || '100%',
            height = video.height || this._core.$stage.height(),
            html;

        if (this._playing) {
            return;
        }

        this._core.enter('playing');
        this._core.trigger('play', null, 'video');

        item = this._core.items(this._core.relative(item.index()));

        this._core.reset(item.index());

        if (video.type === 'youtube') {
            html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' +
                video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
        } else if (video.type === 'vimeo') {
            html = '<iframe src="//player.vimeo.com/video/' + video.id +
                '?autoplay=1" width="' + width + '" height="' + height +
                '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
        } else if (video.type === 'vzaar') {
            html = '<iframe frameborder="0"' + 'height="' + height + '"' + 'width="' + width +
                '" allowfullscreen mozallowfullscreen webkitAllowFullScreen ' +
                'src="//view.vzaar.com/' + video.id + '/player?autoplay=true"></iframe>';
        }

        $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));

        this._playing = item.addClass('owl-video-playing');
    };

    /**
     * Checks whether an video is currently in full screen mode or not.
     * @todo Bad style because looks like a readonly method but changes members.
     * @protected
     * @returns {Boolean}
     */
    Video.prototype.isInFullScreen = function() {
        var element = document.fullscreenElement || document.mozFullScreenElement ||
            document.webkitFullscreenElement;

        return element && $(element).parent().hasClass('owl-video-frame');
    };

    /**
     * Destroys the plugin.
     */
    Video.prototype.destroy = function() {
        var handler, property;

        this._core.$element.off('click.owl.video');

        for (handler in this._handlers) {
            this._core.$element.off(handler, this._handlers[handler]);
        }
        for (property in Object.getOwnPropertyNames(this)) {
            typeof this[property] != 'function' && (this[property] = null);
        }
    };

    $.fn.owlCarousel.Constructor.Plugins.Video = Video;

})(window.Zepto || window.jQuery, window, document);

/**
 * Animate Plugin
 * @version 2.1.0
 * @author Bartosz Wojciechowski
 * @author David Deutsch
 * @license The MIT License (MIT)
 */
;(function($, window, document, undefined) {

    /**
     * Creates the animate plugin.
     * @class The Navigation Plugin
     * @param {Owl} scope - The Owl Carousel
     */
    var Animate = function(scope) {
        this.core = scope;
        this.core.options = $.extend({}, Animate.Defaults, this.core.options);
        this.swapping = true;
        this.previous = undefined;
        this.next = undefined;

        this.handlers = {
            'change.owl.carousel': $.proxy(function(e) {
                if (e.namespace && e.property.name == 'position') {
                    this.previous = this.core.current();
                    this.next = e.property.value;
                }
            }, this),
            'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
                if (e.namespace) {
                    this.swapping = e.type == 'translated';
                }
            }, this),
            'translate.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
                    this.swap();
                }
            }, this)
        };

        this.core.$element.on(this.handlers);
    };

    /**
     * Default options.
     * @public
     */
    Animate.Defaults = {
        animateOut: false,
        animateIn: false
    };

    /**
     * Toggles the animation classes whenever an translations starts.
     * @protected
     * @returns {Boolean|undefined}
     */
    Animate.prototype.swap = function() {

        if (this.core.settings.items !== 1) {
            return;
        }

        if (!$.support.animation || !$.support.transition) {
            return;
        }

        this.core.speed(0);

        var left,
            clear = $.proxy(this.clear, this),
            previous = this.core.$stage.children().eq(this.previous),
            next = this.core.$stage.children().eq(this.next),
            incoming = this.core.settings.animateIn,
            outgoing = this.core.settings.animateOut;

        if (this.core.current() === this.previous) {
            return;
        }

        if (outgoing) {
            left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
            previous.one($.support.animation.end, clear)
                .css( { 'left': left + 'px' } )
                .addClass('animated owl-animated-out')
                .addClass(outgoing);
        }

        if (incoming) {
            next.one($.support.animation.end, clear)
                .addClass('animated owl-animated-in')
                .addClass(incoming);
        }
    };

    Animate.prototype.clear = function(e) {
        $(e.target).css( { 'left': '' } )
            .removeClass('animated owl-animated-out owl-animated-in')
            .removeClass(this.core.settings.animateIn)
            .removeClass(this.core.settings.animateOut);
        this.core.onTransitionEnd();
    };

    /**
     * Destroys the plugin.
     * @public
     */
    Animate.prototype.destroy = function() {
        var handler, property;

        for (handler in this.handlers) {
            this.core.$element.off(handler, this.handlers[handler]);
        }
        for (property in Object.getOwnPropertyNames(this)) {
            typeof this[property] != 'function' && (this[property] = null);
        }
    };

    $.fn.owlCarousel.Constructor.Plugins.Animate = Animate;

})(window.Zepto || window.jQuery, window, document);

/**
 * Autoplay Plugin
 * @version 2.1.0
 * @author Bartosz Wojciechowski
 * @author Artus Kolanowski
 * @author David Deutsch
 * @license The MIT License (MIT)
 */
;(function($, window, document, undefined) {

    /**
     * Creates the autoplay plugin.
     * @class The Autoplay Plugin
     * @param {Owl} scope - The Owl Carousel
     */
    var Autoplay = function(carousel) {
        /**
         * Reference to the core.
         * @protected
         * @type {Owl}
         */
        this._core = carousel;

        /**
         * The autoplay timeout.
         * @type {Timeout}
         */
        this._timeout = null;

        /**
         * Indicates whenever the autoplay is paused.
         * @type {Boolean}
         */
        this._paused = false;

        /**
         * All event handlers.
         * @protected
         * @type {Object}
         */
        this._handlers = {
            'changed.owl.carousel': $.proxy(function(e) {
                if (e.namespace && e.property.name === 'settings') {
                    if (this._core.settings.autoplay) {
                        this.play();
                    } else {
                        this.stop();
                    }
                } else if (e.namespace && e.property.name === 'position') {
                    //console.log('play?', e);
                    if (this._core.settings.autoplay) {
                        this._setAutoPlayInterval();
                    }
                }
            }, this),
            'initialized.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this._core.settings.autoplay) {
                    this.play();
                }
            }, this),
            'play.owl.autoplay': $.proxy(function(e, t, s) {
                if (e.namespace) {
                    this.play(t, s);
                }
            }, this),
            'stop.owl.autoplay': $.proxy(function(e) {
                if (e.namespace) {
                    this.stop();
                }
            }, this),
            'mouseover.owl.autoplay': $.proxy(function() {
                if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
                    this.pause();
                }
            }, this),
            'mouseleave.owl.autoplay': $.proxy(function() {
                if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
                    this.play();
                }
            }, this),
            'touchstart.owl.core': $.proxy(function() {
                if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
                    this.pause();
                }
            }, this),
            'touchend.owl.core': $.proxy(function() {
                if (this._core.settings.autoplayHoverPause) {
                    this.play();
                }
            }, this)
        };

        // register event handlers
        this._core.$element.on(this._handlers);

        // set default options
        this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
    };

    /**
     * Default options.
     * @public
     */
    Autoplay.Defaults = {
        autoplay: false,
        autoplayTimeout: 5000,
        autoplayHoverPause: false,
        autoplaySpeed: false
    };

    /**
     * Starts the autoplay.
     * @public
     * @param {Number} [timeout] - The interval before the next animation starts.
     * @param {Number} [speed] - The animation speed for the animations.
     */
    Autoplay.prototype.play = function(timeout, speed) {
        this._paused = false;

        if (this._core.is('rotating')) {
            return;
        }

        this._core.enter('rotating');

        this._setAutoPlayInterval();
    };

    /**
     * Gets a new timeout
     * @private
     * @param {Number} [timeout] - The interval before the next animation starts.
     * @param {Number} [speed] - The animation speed for the animations.
     * @return {Timeout}
     */
    Autoplay.prototype._getNextTimeout = function(timeout, speed) {
        if ( this._timeout ) {
            window.clearTimeout(this._timeout);
        }
        return window.setTimeout($.proxy(function() {
            if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
                return;
            }
            this._core.next(speed || this._core.settings.autoplaySpeed);
        }, this), timeout || this._core.settings.autoplayTimeout);
    };

    /**
     * Sets autoplay in motion.
     * @private
     */
    Autoplay.prototype._setAutoPlayInterval = function() {
        this._timeout = this._getNextTimeout();
    };

    /**
     * Stops the autoplay.
     * @public
     */
    Autoplay.prototype.stop = function() {
        if (!this._core.is('rotating')) {
            return;
        }

        window.clearTimeout(this._timeout);
        this._core.leave('rotating');
    };

    /**
     * Stops the autoplay.
     * @public
     */
    Autoplay.prototype.pause = function() {
        if (!this._core.is('rotating')) {
            return;
        }

        this._paused = true;
    };

    /**
     * Destroys the plugin.
     */
    Autoplay.prototype.destroy = function() {
        var handler, property;

        this.stop();

        for (handler in this._handlers) {
            this._core.$element.off(handler, this._handlers[handler]);
        }
        for (property in Object.getOwnPropertyNames(this)) {
            typeof this[property] != 'function' && (this[property] = null);
        }
    };

    $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;

})(window.Zepto || window.jQuery, window, document);

/**
 * Navigation Plugin
 * @version 2.1.0
 * @author Artus Kolanowski
 * @author David Deutsch
 * @license The MIT License (MIT)
 */
;(function($, window, document, undefined) {
    'use strict';

    /**
     * Creates the navigation plugin.
     * @class The Navigation Plugin
     * @param {Owl} carousel - The Owl Carousel.
     */
    var Navigation = function(carousel) {
        /**
         * Reference to the core.
         * @protected
         * @type {Owl}
         */
        this._core = carousel;

        /**
         * Indicates whether the plugin is initialized or not.
         * @protected
         * @type {Boolean}
         */
        this._initialized = false;

        /**
         * The current paging indexes.
         * @protected
         * @type {Array}
         */
        this._pages = [];

        /**
         * All DOM elements of the user interface.
         * @protected
         * @type {Object}
         */
        this._controls = {};

        /**
         * Markup for an indicator.
         * @protected
         * @type {Array.<String>}
         */
        this._templates = [];

        /**
         * The carousel element.
         * @type {jQuery}
         */
        this.$element = this._core.$element;

        /**
         * Overridden methods of the carousel.
         * @protected
         * @type {Object}
         */
        this._overrides = {
            next: this._core.next,
            prev: this._core.prev,
            to: this._core.to
        };

        /**
         * All event handlers.
         * @protected
         * @type {Object}
         */
        this._handlers = {
            'prepared.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this._core.settings.dotsData) {
                    this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
                        $(e.content).find('[data-dot]').addBack('[data-dot]').attr('data-dot') + '</div>');
                }
            }, this),
            'added.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this._core.settings.dotsData) {
                    this._templates.splice(e.position, 0, this._templates.pop());
                }
            }, this),
            'remove.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this._core.settings.dotsData) {
                    this._templates.splice(e.position, 1);
                }
            }, this),
            'changed.owl.carousel': $.proxy(function(e) {
                if (e.namespace && e.property.name == 'position') {
                    this.draw();
                }
            }, this),
            'initialized.owl.carousel': $.proxy(function(e) {
                if (e.namespace && !this._initialized) {
                    this._core.trigger('initialize', null, 'navigation');
                    this.initialize();
                    this.update();
                    this.draw();
                    this._initialized = true;
                    this._core.trigger('initialized', null, 'navigation');
                }
            }, this),
            'refreshed.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this._initialized) {
                    this._core.trigger('refresh', null, 'navigation');
                    this.update();
                    this.draw();
                    this._core.trigger('refreshed', null, 'navigation');
                }
            }, this)
        };

        // set default options
        this._core.options = $.extend({}, Navigation.Defaults, this._core.options);

        // register event handlers
        this.$element.on(this._handlers);
    };

    /**
     * Default options.
     * @public
     * @todo Rename `slideBy` to `navBy`
     */
    Navigation.Defaults = {
        nav: false,
        navText: [ 'prev', 'next' ],
        navSpeed: false,
        navElement: 'div',
        navContainer: false,
        navContainerClass: 'owl-nav',
        navClass: [ 'owl-prev', 'owl-next' ],
        slideBy: 1,
        dotClass: 'owl-dot',
        dotsClass: 'owl-dots',
        dots: true,
        dotsEach: false,
        dotsData: false,
        dotsSpeed: false,
        dotsContainer: false
    };

    /**
     * Initializes the layout of the plugin and extends the carousel.
     * @protected
     */
    Navigation.prototype.initialize = function() {
        var override,
            settings = this._core.settings;

        // create DOM structure for relative navigation
        this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
            : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');

        this._controls.$previous = $('<' + settings.navElement + '>')
            .addClass(settings.navClass[0])
            .html(settings.navText[0])
            .prependTo(this._controls.$relative)
            .on('click', $.proxy(function(e) {
                this.prev(settings.navSpeed);
            }, this));
        this._controls.$next = $('<' + settings.navElement + '>')
            .addClass(settings.navClass[1])
            .html(settings.navText[1])
            .appendTo(this._controls.$relative)
            .on('click', $.proxy(function(e) {
                this.next(settings.navSpeed);
            }, this));

        // create DOM structure for absolute navigation
        if (!settings.dotsData) {
            this._templates = [ $('<div>')
                .addClass(settings.dotClass)
                .append($('<span>'))
                .prop('outerHTML') ];
        }

        this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
            : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');

        this._controls.$absolute.on('click', 'div', $.proxy(function(e) {
            var index = $(e.target).parent().is(this._controls.$absolute)
                ? $(e.target).index() : $(e.target).parent().index();

            e.preventDefault();

            this.to(index, settings.dotsSpeed);
        }, this));

        // override public methods of the carousel
        for (override in this._overrides) {
            this._core[override] = $.proxy(this[override], this);
        }
    };

    /**
     * Destroys the plugin.
     * @protected
     */
    Navigation.prototype.destroy = function() {
        var handler, control, property, override;

        for (handler in this._handlers) {
            this.$element.off(handler, this._handlers[handler]);
        }
        for (control in this._controls) {
            this._controls[control].remove();
        }
        for (override in this.overides) {
            this._core[override] = this._overrides[override];
        }
        for (property in Object.getOwnPropertyNames(this)) {
            typeof this[property] != 'function' && (this[property] = null);
        }
    };

    /**
     * Updates the internal state.
     * @protected
     */
    Navigation.prototype.update = function() {
        var i, j, k,
            lower = this._core.clones().length / 2,
            upper = lower + this._core.items().length,
            maximum = this._core.maximum(true),
            settings = this._core.settings,
            size = settings.center || settings.autoWidth || settings.dotsData
                ? 1 : settings.dotsEach || settings.items;

        if (settings.slideBy !== 'page') {
            settings.slideBy = Math.min(settings.slideBy, settings.items);
        }

        if (settings.dots || settings.slideBy == 'page') {
            this._pages = [];

            for (i = lower, j = 0, k = 0; i < upper; i++) {
                if (j >= size || j === 0) {
                    this._pages.push({
                        start: Math.min(maximum, i - lower),
                        end: i - lower + size - 1
                    });
                    if (Math.min(maximum, i - lower) === maximum) {
                        break;
                    }
                    j = 0, ++k;
                }
                j += this._core.mergers(this._core.relative(i));
            }
        }
    };

    /**
     * Draws the user interface.
     * @todo The option `dotsData` wont work.
     * @protected
     */
    Navigation.prototype.draw = function() {
        var difference,
            settings = this._core.settings,
            disabled = this._core.items().length <= settings.items,
            index = this._core.relative(this._core.current()),
            loop = settings.loop || settings.rewind;

        this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);

        if (settings.nav) {
            this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
            this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
        }

        this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);

        if (settings.dots) {
            difference = this._pages.length - this._controls.$absolute.children().length;

            if (settings.dotsData && difference !== 0) {
                this._controls.$absolute.html(this._templates.join(''));
            } else if (difference > 0) {
                this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
            } else if (difference < 0) {
                this._controls.$absolute.children().slice(difference).remove();
            }

            this._controls.$absolute.find('.active').removeClass('active');
            this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
        }
    };

    /**
     * Extends event data.
     * @protected
     * @param {Event} event - The event object which gets thrown.
     */
    Navigation.prototype.onTrigger = function(event) {
        var settings = this._core.settings;

        event.page = {
            index: $.inArray(this.current(), this._pages),
            count: this._pages.length,
            size: settings && (settings.center || settings.autoWidth || settings.dotsData
                ? 1 : settings.dotsEach || settings.items)
        };
    };

    /**
     * Gets the current page position of the carousel.
     * @protected
     * @returns {Number}
     */
    Navigation.prototype.current = function() {
        var current = this._core.relative(this._core.current());
        return $.grep(this._pages, $.proxy(function(page, index) {
            return page.start <= current && page.end >= current;
        }, this)).pop();
    };

    /**
     * Gets the current succesor/predecessor position.
     * @protected
     * @returns {Number}
     */
    Navigation.prototype.getPosition = function(successor) {
        var position, length,
            settings = this._core.settings;

        if (settings.slideBy == 'page') {
            position = $.inArray(this.current(), this._pages);
            length = this._pages.length;
            successor ? ++position : --position;
            position = this._pages[((position % length) + length) % length].start;
        } else {
            position = this._core.relative(this._core.current());
            length = this._core.items().length;
            successor ? position += settings.slideBy : position -= settings.slideBy;
        }

        return position;
    };

    /**
     * Slides to the next item or page.
     * @public
     * @param {Number} [speed=false] - The time in milliseconds for the transition.
     */
    Navigation.prototype.next = function(speed) {
        $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
    };

    /**
     * Slides to the previous item or page.
     * @public
     * @param {Number} [speed=false] - The time in milliseconds for the transition.
     */
    Navigation.prototype.prev = function(speed) {
        $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
    };

    /**
     * Slides to the specified item or page.
     * @public
     * @param {Number} position - The position of the item or page.
     * @param {Number} [speed] - The time in milliseconds for the transition.
     * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
     */
    Navigation.prototype.to = function(position, speed, standard) {
        var length;

        if (!standard && this._pages.length) {
            length = this._pages.length;
            $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
        } else {
            $.proxy(this._overrides.to, this._core)(position, speed);
        }
    };

    $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;

})(window.Zepto || window.jQuery, window, document);

/**
 * Hash Plugin
 * @version 2.1.0
 * @author Artus Kolanowski
 * @author David Deutsch
 * @license The MIT License (MIT)
 */
;(function($, window, document, undefined) {
    'use strict';

    /**
     * Creates the hash plugin.
     * @class The Hash Plugin
     * @param {Owl} carousel - The Owl Carousel
     */
    var Hash = function(carousel) {
        /**
         * Reference to the core.
         * @protected
         * @type {Owl}
         */
        this._core = carousel;

        /**
         * Hash index for the items.
         * @protected
         * @type {Object}
         */
        this._hashes = {};

        /**
         * The carousel element.
         * @type {jQuery}
         */
        this.$element = this._core.$element;

        /**
         * All event handlers.
         * @protected
         * @type {Object}
         */
        this._handlers = {
            'initialized.owl.carousel': $.proxy(function(e) {
                if (e.namespace && this._core.settings.startPosition === 'URLHash') {
                    $(window).trigger('hashchange.owl.navigation');
                }
            }, this),
            'prepared.owl.carousel': $.proxy(function(e) {
                if (e.namespace) {
                    var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');

                    if (!hash) {
                        return;
                    }

                    this._hashes[hash] = e.content;
                }
            }, this),
            'changed.owl.carousel': $.proxy(function(e) {
                if (e.namespace && e.property.name === 'position') {
                    var current = this._core.items(this._core.relative(this._core.current())),
                        hash = $.map(this._hashes, function(item, hash) {
                            return item === current ? hash : null;
                        }).join();

                    if (!hash || window.location.hash.slice(1) === hash) {
                        return;
                    }

                    window.location.hash = hash;
                }
            }, this)
        };

        // set default options
        this._core.options = $.extend({}, Hash.Defaults, this._core.options);

        // register the event handlers
        this.$element.on(this._handlers);

        // register event listener for hash navigation
        $(window).on('hashchange.owl.navigation', $.proxy(function(e) {
            var hash = window.location.hash.substring(1),
                items = this._core.$stage.children(),
                position = this._hashes[hash] && items.index(this._hashes[hash]);

            if (position === undefined || position === this._core.current()) {
                return;
            }

            this._core.to(this._core.relative(position), false, true);
        }, this));
    };

    /**
     * Default options.
     * @public
     */
    Hash.Defaults = {
        URLhashListener: false
    };

    /**
     * Destroys the plugin.
     * @public
     */
    Hash.prototype.destroy = function() {
        var handler, property;

        $(window).off('hashchange.owl.navigation');

        for (handler in this._handlers) {
            this._core.$element.off(handler, this._handlers[handler]);
        }
        for (property in Object.getOwnPropertyNames(this)) {
            typeof this[property] != 'function' && (this[property] = null);
        }
    };

    $.fn.owlCarousel.Constructor.Plugins.Hash = Hash;

})(window.Zepto || window.jQuery, window, document);

/**
 * Support Plugin
 *
 * @version 2.1.0
 * @author Vivid Planet Software GmbH
 * @author Artus Kolanowski
 * @author David Deutsch
 * @license The MIT License (MIT)
 */
;(function($, window, document, undefined) {

    var style = $('<support>').get(0).style,
        prefixes = 'Webkit Moz O ms'.split(' '),
        events = {
            transition: {
                end: {
                    WebkitTransition: 'webkitTransitionEnd',
                    MozTransition: 'transitionend',
                    OTransition: 'oTransitionEnd',
                    transition: 'transitionend'
                }
            },
            animation: {
                end: {
                    WebkitAnimation: 'webkitAnimationEnd',
                    MozAnimation: 'animationend',
                    OAnimation: 'oAnimationEnd',
                    animation: 'animationend'
                }
            }
        },
        tests = {
            csstransforms: function() {
                return !!test('transform');
            },
            csstransforms3d: function() {
                return !!test('perspective');
            },
            csstransitions: function() {
                return !!test('transition');
            },
            cssanimations: function() {
                return !!test('animation');
            }
        };

    function test(property, prefixed) {
        var result = false,
            upper = property.charAt(0).toUpperCase() + property.slice(1);

        $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
            if (style[property] !== undefined) {
                result = prefixed ? property : true;
                return false;
            }
        });

        return result;
    }

    function prefixed(property) {
        return test(property, true);
    }

    if (tests.csstransitions()) {
        /* jshint -W053 */
        $.support.transition = new String(prefixed('transition'))
        $.support.transition.end = events.transition.end[ $.support.transition ];
    }

    if (tests.cssanimations()) {
        /* jshint -W053 */
        $.support.animation = new String(prefixed('animation'))
        $.support.animation.end = events.animation.end[ $.support.animation ];
    }

    if (tests.csstransforms()) {
        /* jshint -W053 */
        $.support.transform = new String(prefixed('transform'));
        $.support.transform3d = tests.csstransforms3d();
    }

})(window.Zepto || window.jQuery, window, document);

// Easy Responsive Tabs Plugin

// Author: Samson.Onna <Email : samson3d@gmail.com>

(function ($) {

    $.fn.extend({

        easyResponsiveTabs: function (options) {

            //Set the default values, use comma to separate the settings, example:

            var defaults = {

                type: 'default', //default, vertical, accordion;

                width: 'auto',

                fit: true,

                closed: false,

                activate: function(){}

            }

            //Variables

            var options = $.extend(defaults, options);

            var opt = options, jtype = opt.type, jfit = opt.fit, jwidth = opt.width, vtabs = 'vertical', accord = 'accordion';

            var hash = window.location.hash;

            var historyApi = !!(window.history && history.replaceState);



            //Events

            $(this).bind('tabactivate', function(e, currentTab) {

                if(typeof options.activate === 'function') {

                    options.activate.call(currentTab, e)

                }

            });



            //Main function

            this.each(function () {

                var $respTabs = $(this);

                var $respTabsList = $respTabs.find('ul.resp-tabs-list');

                var respTabsId = $respTabs.attr('id');

                $respTabs.find('ul.resp-tabs-list li').addClass('resp-tab-item');

                $respTabs.css({

                    'display': 'block',

                    'width': jwidth

                });



                $respTabs.find('.resp-tabs-container > div').addClass('resp-tab-content');

                jtab_options();

                //Properties Function

                function jtab_options() {

                    if (jtype == vtabs) {

                        $respTabs.addClass('resp-vtabs');

                    }

                    if (jfit == true) {

                        $respTabs.css({ width: '100%' });

                    }

                    if (jtype == accord) {

                        $respTabs.addClass('resp-easy-accordion');

                        $respTabs.find('.resp-tabs-list').css('display', 'none');

                    }

                }



                //Assigning the h2 markup to accordion title

                var $tabItemh2;

                $respTabs.find('.resp-tab-content').before("<h2 class='resp-accordion' role='tab'><span class='resp-arrow'></span></h2>");



                var itemCount = 0;

                $respTabs.find('.resp-accordion').each(function () {

                    $tabItemh2 = $(this);

                    var $tabItem = $respTabs.find('.resp-tab-item:eq(' + itemCount + ')');

                    var $accItem = $respTabs.find('.resp-accordion:eq(' + itemCount + ')');

                    $accItem.append($tabItem.html());

                    $accItem.data($tabItem.data());

                    $tabItemh2.attr('aria-controls', 'tab_item-' + (itemCount));

                    itemCount++;

                });



                //Assigning the 'aria-controls' to Tab items

                var count = 0,

                    $tabContent;

                $respTabs.find('.resp-tab-item').each(function () {

                    $tabItem = $(this);

                    $tabItem.attr('aria-controls', 'tab_item-' + (count));

                    $tabItem.attr('role', 'tab');



                    //Assigning the 'aria-labelledby' attr to tab-content

                    var tabcount = 0;

                    $respTabs.find('.resp-tab-content').each(function () {

                        $tabContent = $(this);

                        $tabContent.attr('aria-labelledby', 'tab_item-' + (tabcount));

                        tabcount++;

                    });

                    count++;

                });



                // Show correct content area

                var tabNum = 0;

                if(hash!='') {

                    var matches = hash.match(new RegExp(respTabsId+"([0-9]+)"));

                    if (matches!==null && matches.length===2) {

                        tabNum = parseInt(matches[1],10)-1;

                        if (tabNum > count) {

                            tabNum = 0;

                        }

                    }

                }



                //Active correct tab

                $($respTabs.find('.resp-tab-item')[tabNum]).addClass('resp-tab-active');



                //keep closed if option = 'closed' or option is 'accordion' and the element is in accordion mode

                if(options.closed !== true && !(options.closed === 'accordion' && !$respTabsList.is(':visible')) && !(options.closed === 'tabs' && $respTabsList.is(':visible'))) {

                    $($respTabs.find('.resp-accordion')[tabNum]).addClass('resp-tab-active');

                    $($respTabs.find('.resp-tab-content')[tabNum]).addClass('resp-tab-content-active').attr('style', 'display:block');

                }

                //assign proper classes for when tabs mode is activated before making a selection in accordion mode

                else {

                    $($respTabs.find('.resp-tab-content')[tabNum]).addClass('resp-tab-content-active resp-accordion-closed')

                }



                //Tab Click action function

                $respTabs.find("[role=tab]").each(function () {



                    var $currentTab = $(this);

                    $currentTab.click(function () {



                        var $currentTab = $(this);

                        var $tabAria = $currentTab.attr('aria-controls');



                        if ($currentTab.hasClass('resp-accordion') && $currentTab.hasClass('resp-tab-active')) {

                            $respTabs.find('.resp-tab-content-active').slideUp('', function () { $(this).addClass('resp-accordion-closed'); });

                            $currentTab.removeClass('resp-tab-active');

                            return false;

                        }

                        if (!$currentTab.hasClass('resp-tab-active') && $currentTab.hasClass('resp-accordion')) {

                            $respTabs.find('.resp-tab-active').removeClass('resp-tab-active');

                            $respTabs.find('.resp-tab-content-active').slideUp().removeClass('resp-tab-content-active resp-accordion-closed');

                            $respTabs.find("[aria-controls=" + $tabAria + "]").addClass('resp-tab-active');



                            $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').slideDown().addClass('resp-tab-content-active');

                        } else {

                            $respTabs.find('.resp-tab-active').removeClass('resp-tab-active');

                            $respTabs.find('.resp-tab-content-active').removeAttr('style').removeClass('resp-tab-content-active').removeClass('resp-accordion-closed');

                            $respTabs.find("[aria-controls=" + $tabAria + "]").addClass('resp-tab-active');

                            $respTabs.find('.resp-tab-content[aria-labelledby = ' + $tabAria + ']').addClass('resp-tab-content-active').attr('style', 'display:block');

                        }

                        //Trigger tab activation event

                        $currentTab.trigger('tabactivate', $currentTab);



                        //Update Browser History

                        if(historyApi) {

                            /*var currentHash = window.location.hash;

                            var newHash = respTabsId+(parseInt($tabAria.substring(9),10)+1).toString();

                            if (currentHash!="") {

                                var re = new RegExp(respTabsId+"[0-9]+");

                                if (currentHash.match(re)!=null) {

                                    newHash = currentHash.replace(re,newHash);

                                }

                                else {

                                    newHash = currentHash+"|"+newHash;

                                }

                            }

                            else {

                                newHash = '#'+newHash;

                            }



                            history.replaceState(null,null,newHash);*/

                        }

                    });



                });



                //Window resize function

                $(window).resize(function () {

                    $respTabs.find('.resp-accordion-closed').removeAttr('style');

                });

            });

        }

    });

})(jQuery);





/*!
 * hoverIntent r7 // 2013.03.11 // jQuery 1.9.1+
 * http://cherne.net/brian/resources/jquery.hoverIntent.html
 *
 * You may use hoverIntent under the terms of the MIT license. Basically that
 * means you are free to use hoverIntent as long as this header is left intact.
 * Copyright 2007, 2013 Brian Cherne
 */
 
/* hoverIntent is similar to jQuery's built-in "hover" method except that
 * instead of firing the handlerIn function immediately, hoverIntent checks
 * to see if the user's mouse has slowed down (beneath the sensitivity
 * threshold) before firing the event. The handlerOut function is only
 * called after a matching handlerIn.
 *
 * // basic usage ... just like .hover()
 * .hoverIntent( handlerIn, handlerOut )
 * .hoverIntent( handlerInOut )
 *
 * // basic usage ... with event delegation!
 * .hoverIntent( handlerIn, handlerOut, selector )
 * .hoverIntent( handlerInOut, selector )
 *
 * // using a basic configuration object
 * .hoverIntent( config )
 *
 * @param  handlerIn   function OR configuration object
 * @param  handlerOut  function OR selector for delegation OR undefined
 * @param  selector    selector OR undefined
 * @author Brian Cherne <brian(at)cherne(dot)net>
 */
(function($) {
    $.fn.hoverIntent = function(handlerIn,handlerOut,selector) {

        // default configuration values
        var cfg = {
            interval: 100,
            sensitivity: 7,
            timeout: 0
        };

        if ( typeof handlerIn === "object" ) {
            cfg = $.extend(cfg, handlerIn );
        } else if ($.isFunction(handlerOut)) {
            cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } );
        } else {
            cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } );
        }

        // instantiate variables
        // cX, cY = current X and Y position of mouse, updated by mousemove event
        // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
        var cX, cY, pX, pY;

        // A private function for getting mouse position
        var track = function(ev) {
            cX = ev.pageX;
            cY = ev.pageY;
        };

        // A private function for comparing current and previous mouse position
        var compare = function(ev,ob) {
            ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
            // compare mouse positions to see if they've crossed the threshold
            if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
                $(ob).off("mousemove.hoverIntent",track);
                // set hoverIntent state to true (so mouseOut can be called)
                ob.hoverIntent_s = 1;
                return cfg.over.apply(ob,[ev]);
            } else {
                // set previous coordinates for next time
                pX = cX; pY = cY;
                // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
                ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
            }
        };

        // A private function for delaying the mouseOut function
        var delay = function(ev,ob) {
            ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
            ob.hoverIntent_s = 0;
            return cfg.out.apply(ob,[ev]);
        };

        // A private function for handling mouse 'hovering'
        var handleHover = function(e) {
            // copy objects to be passed into t (required for event object to be passed in IE)
            var ev = jQuery.extend({},e);
            var ob = this;

            // cancel hoverIntent timer if it exists
            if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

            // if e.type == "mouseenter"
            if (e.type == "mouseenter") {
                // set "previous" X and Y position based on initial entry point
                pX = ev.pageX; pY = ev.pageY;
                // update "current" X and Y position based on mousemove
                $(ob).on("mousemove.hoverIntent",track);
                // start polling interval (self-calling timeout) to compare mouse coordinates over time
                if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}

                // else e.type == "mouseleave"
            } else {
                // unbind expensive mousemove event
                $(ob).off("mousemove.hoverIntent",track);
                // if hoverIntent state is true, then call the mouseOut function after the specified delay
                if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
            }
        };

        // listen for mouseenter and mouseleave
        return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector);
    };
})(jQuery);

/**
 * jQuery CSS Customizable Scrollbar
 *
 * Copyright 2014, Yuriy Khabarov
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 * If you found bug, please contact me via email <13real008@gmail.com>
 *
 * @author Yuriy Khabarov aka Gromo
 * @version 0.2.5
 * @url https://github.com/gromo/jquery.scrollbar/
 *
 */
;
(function($, doc, win){
    'use strict';

    // init flags & variables
    var debug = false;
    var lmb = 1, px = "px";
    var rtl = false;

    var browser = {
        data: {
            index: 0,
            name: 'scrollbar'
        },
        macosx: /mac/i.test(navigator.platform),
        mobile: /android|webos|iphone|ipad|ipod|blackberry/i.test(navigator.userAgent),
        overlay: null,
        scroll: null,
        scrolls: [],
        webkit: /webkit/i.test(navigator.userAgent) && !/edge\/\d+/i.test(navigator.userAgent),

        log: debug ? function(data, toString){
            var output = data;
            if(toString && typeof data != "string"){
                output = [];
                $.each(data, function(i, v){
                    output.push('"' + i + '": ' + v);
                });
                output = output.join(", ");
            }
            if(win.console && win.console.log){
                //win.console.log(output);
            } else {
                //alert(output);
            }
        } : function(){

        }
    };

    var defaults = {
        "autoScrollSize": true,     // automatically calculate scrollsize
        "autoUpdate": true,         // update scrollbar if content/container size changed
        "debug": false,             // debug mode
        "disableBodyScroll": false, // disable body scroll if mouse over container
        "duration": 200,            // scroll animate duration in ms
        "ignoreMobile": true,       // ignore mobile devices
        "ignoreOverlay": true,      // ignore browsers with overlay scrollbars (mobile, MacOS)
        "scrollStep": 30,           // scroll step for scrollbar arrows
        "showArrows": false,        // add class to show arrows
        "stepScrolling": true,      // when scrolling to scrollbar mousedown position
        "type":"simple",            // [advanced|simple] scrollbar html type

        "scrollx": null,            // horizontal scroll element
        "scrolly": null,            // vertical scroll element

        "onDestroy": null,          // callback function on destroy,
        "onInit": null,             // callback function on first initialization
        "onScroll": null,           // callback function on content scrolling
        "onUpdate": null            // callback function on init/resize (before scrollbar size calculation)
    };


    var customScrollbar = function(container, options){

        rtl = $('body').hasClass('rtl');

        if(!browser.scroll){
            browser.log("Init jQuery Scrollbar v0.2.5");
            browser.overlay = isScrollOverlaysContent();
            browser.scroll = getBrowserScrollSize();
            updateScrollbars();

            $(win).resize(function(){
                var forceUpdate = false;
                if(browser.scroll && (browser.scroll.height || browser.scroll.width)){
                    var scroll = getBrowserScrollSize();
                    if(scroll.height != browser.scroll.height || scroll.width != browser.scroll.width){
                        browser.scroll = scroll;
                        forceUpdate = true; // handle page zoom
                    }
                }
                updateScrollbars(forceUpdate);
            });
        }

        this.container = container;
        this.options = $.extend({}, defaults, win.jQueryScrollbarOptions || {});
        this.scrollTo = null;
        this.scrollx = {};
        this.scrolly = {};

        this.init(options);
    };

    customScrollbar.prototype = {

        destroy: function(){

            if(!this.wrapper){
                return;
            }

            // init variables
            var scrollLeft = this.container.scrollLeft();
            var scrollTop  = this.container.scrollTop();

            this.container.insertBefore(this.wrapper).css({
                "height":"",
                "margin":""
            })
                .removeClass("scroll-content")
                .removeClass("scroll-scrollx_visible")
                .removeClass("scroll-scrolly_visible")
                .off(".scrollbar")
                .scrollLeft(scrollLeft)
                .scrollTop(scrollTop);

            this.scrollx.scrollbar.removeClass("scroll-scrollx_visible").find("div").andSelf().off(".scrollbar");
            this.scrolly.scrollbar.removeClass("scroll-scrolly_visible").find("div").andSelf().off(".scrollbar");

            this.wrapper.remove();

            $(doc).add("body").off(".scrollbar");

            if($.isFunction(this.options.onDestroy))
                this.options.onDestroy.apply(this, [this.container]);
        },



        getScrollbar: function(d){

            var scrollbar = this.options["scroll" + d];
            var html = {
                "advanced":
                    '<div class="scroll-element_corner"></div>' +
                        '<div class="scroll-arrow scroll-arrow_less"></div>' +
                        '<div class="scroll-arrow scroll-arrow_more"></div>' +
                        '<div class="scroll-element_outer">' +
                        '    <div class="scroll-element_size"></div>' + // required! used for scrollbar size calculation !
                        '    <div class="scroll-element_inner-wrapper">' +
                        '        <div class="scroll-element_inner scroll-element_track">'  + // used for handling scrollbar click
                        '            <div class="scroll-element_inner-bottom"></div>' +
                        '        </div>' +
                        '    </div>' +
                        '    <div class="scroll-bar">' +
                        '        <div class="scroll-bar_body">' +
                        '            <div class="scroll-bar_body-inner"></div>' +
                        '        </div>' +
                        '        <div class="scroll-bar_bottom"></div>' +
                        '        <div class="scroll-bar_center"></div>' +
                        '    </div>' +
                        '</div>',

                "simple":
                    '<div class="scroll-element_outer">' +
                        '    <div class="scroll-element_size"></div>'  + // required! used for scrollbar size calculation !
                        '    <div class="scroll-element_track"></div>' + // used for handling scrollbar click
                        '    <div class="scroll-bar"></div>' +
                        '</div>'
            };
            var type = html[this.options.type] ? this.options.type : "advanced";

            if(scrollbar){
                if(typeof(scrollbar) == "string"){
                    scrollbar = $(scrollbar).appendTo(this.wrapper);
                } else {
                    scrollbar = $(scrollbar);
                }
            } else {
                scrollbar = $("<div>").addClass("scroll-element").html(html[type]).appendTo(this.wrapper);
            }

            if(this.options.showArrows){
                scrollbar.addClass("scroll-element_arrows_visible");
            }

            return scrollbar.addClass("scroll-" + d);
        },



        init: function(options){

            // init variables
            var S = this;

            var c = this.container;
            var cw = this.containerWrapper || c;
            var o = $.extend(this.options, options || {});
            var s = {
                "x": this.scrollx,
                "y": this.scrolly
            };
            var w = this.wrapper;

            var initScroll = {
                "scrollLeft": c.scrollLeft(),
                "scrollTop": c.scrollTop()
            };

            // do not init if in ignorable browser
            if ((browser.mobile && o.ignoreMobile)
                || (browser.overlay && o.ignoreOverlay)
                || (browser.macosx && !browser.webkit) // still required to ignore nonWebKit browsers on Mac
                ) {
                return false;
            }

            // init scroll container
            if(!w){
                this.wrapper = w = $('<div>').addClass('scroll-wrapper').addClass(c.attr('class'))
                    .css('position', c.css('position') == 'absolute' ? 'absolute' : 'relative')
                    .insertBefore(c).append(c);

                if(c.is('textarea')){
                    this.containerWrapper = cw = $('<div>').insertBefore(c).append(c);
                    w.addClass('scroll-textarea');
                }

                if (rtl) {
                    cw.addClass("scroll-content").css({
                        "height":"",
                        "margin-bottom": browser.scroll.height * -1 + px,
                        "margin-left":  browser.scroll.width  * -1 + px
                    });
                } else {
                    cw.addClass("scroll-content").css({
                        "height":"",
                        "margin-bottom": browser.scroll.height * -1 + px,
                        "margin-right":  browser.scroll.width  * -1 + px
                    });
                }

                c.on("scroll.scrollbar", function(event){
                    if($.isFunction(o.onScroll)){
                        o.onScroll.call(S, {
                            "maxScroll": s.y.maxScrollOffset,
                            "scroll": c.scrollTop(),
                            "size": s.y.size,
                            "visible": s.y.visible
                        }, {
                            "maxScroll": s.x.maxScrollOffset,
                            "scroll": c.scrollLeft(),
                            "size": s.x.size,
                            "visible": s.x.visible
                        });
                    }
                    s.x.isVisible && s.x.scroller.css(rtl?"right":"left", c.scrollLeft() * s.x.kx + px);
                    s.y.isVisible && s.y.scroller.css("top",  c.scrollTop()  * s.y.kx + px);
                });

                /* prevent native scrollbars to be visible on #anchor click */
                w.on("scroll", function(){
                    w.scrollTop(0).scrollLeft(0);
                });

                if(o.disableBodyScroll){
                    var handleMouseScroll = function(event){
                        isVerticalScroll(event) ?
                            s.y.isVisible && s.y.mousewheel(event) :
                            s.x.isVisible && s.x.mousewheel(event);
                        event.preventDefault();
                        return false;
                    };
                    w.on({
                        "MozMousePixelScroll.scrollbar": handleMouseScroll,
                        "mousewheel.scrollbar": handleMouseScroll
                    });

                    if(browser.mobile){
                        w.on("touchstart.scrollbar", function(event){
                            var touch = event.originalEvent.touches && event.originalEvent.touches[0] || event;
                            var originalTouch = {
                                "pageX": touch.pageX,
                                "pageY": touch.pageY
                            };
                            if (rtl) {
                                var originalScroll = {
                                    "right": c.scrollLeft(),
                                    "top": c.scrollTop()
                                };
                            } else {
                                var originalScroll = {
                                    "left": c.scrollLeft(),
                                    "top": c.scrollTop()
                                };
                            }
                            $(doc).on({
                                "touchmove.scrollbar": function(event){
                                    var touch = event.originalEvent.targetTouches && event.originalEvent.targetTouches[0] || event;
                                    c.scrollLeft(rtl?originalScroll.right:originalScroll.left + originalTouch.pageX - touch.pageX);
                                    c.scrollTop(originalScroll.top + originalTouch.pageY - touch.pageY);
                                    event.preventDefault();
                                },
                                "touchend.scrollbar": function(){
                                    $(doc).off(".scrollbar");
                                }
                            });
                        });
                    }
                }
                if($.isFunction(o.onInit))
                    o.onInit.apply(this, [c]);
            } else {
                if (rtl) {
                    cw.css({
                        "height":"",
                        "margin-bottom": browser.scroll.height * -1 + px,
                        "margin-left":  browser.scroll.width  * -1 + px
                    });
                } else {
                    cw.css({
                        "height":"",
                        "margin-bottom": browser.scroll.height * -1 + px,
                        "margin-right":  browser.scroll.width  * -1 + px
                    });
                }
            }

            // init scrollbars & recalculate sizes
            $.each(s, function(d, scrollx){

                var scrollCallback = null;
                var scrollForward = 1;
                var scrollOffset = (d == "x") ? "scrollLeft" : "scrollTop";
                var scrollStep = o.scrollStep;
                var scrollTo = function(){
                    var currentOffset = c[scrollOffset]();
                    c[scrollOffset](currentOffset + scrollStep);
                    if(scrollForward == 1 && (currentOffset + scrollStep) >= scrollToValue)
                        currentOffset = c[scrollOffset]();
                    if(scrollForward == -1 && (currentOffset + scrollStep) <= scrollToValue)
                        currentOffset = c[scrollOffset]();
                    if(c[scrollOffset]() == currentOffset && scrollCallback){
                        scrollCallback();
                    }
                }
                var scrollToValue = 0;

                if(!scrollx.scrollbar){

                    scrollx.scrollbar = S.getScrollbar(d);
                    scrollx.scroller = scrollx.scrollbar.find(".scroll-bar");

                    scrollx.mousewheel = function(event){

                        if(!scrollx.isVisible || (d == 'x' && isVerticalScroll(event))){
                            return true;
                        }
                        if(d == 'y' && !isVerticalScroll(event)){
                            s.x.mousewheel(event);
                            return true;
                        }

                        var delta = event.originalEvent.wheelDelta * -1 || event.originalEvent.detail;
                        var maxScrollValue = scrollx.size - scrollx.visible - scrollx.offset;

                        if(!((scrollToValue <= 0 && delta < 0) || (scrollToValue >= maxScrollValue && delta > 0))){
                            scrollToValue = scrollToValue + delta;
                            if(scrollToValue < 0)
                                scrollToValue = 0;
                            if(scrollToValue > maxScrollValue)
                                scrollToValue = maxScrollValue;

                            S.scrollTo = S.scrollTo || {};
                            S.scrollTo[scrollOffset] = scrollToValue;
                            setTimeout(function(){
                                if(S.scrollTo){
                                    c.stop().animate(S.scrollTo, 240, 'linear', function(){
                                        scrollToValue = c[scrollOffset]();
                                    });
                                    S.scrollTo = null;
                                }
                            }, 1);
                        } else {
                            return true;
                        }

                        event.preventDefault();
                        return false;
                    };

                    scrollx.scrollbar.on({
                        "MozMousePixelScroll.scrollbar": scrollx.mousewheel,
                        "mousewheel.scrollbar": scrollx.mousewheel,
                        "mouseenter.scrollbar": function(){
                            scrollToValue = c[scrollOffset]();
                        }
                    });

                    scrollx.triggerEvent = function(event) {
                        var ret = scrollx.mousewheel(event);
                        if (!ret) {
                            event.preventDefault;
                            return false;
                        }
                        return true;
                    }

                    w.on({
                        "MozMousePixelScroll.scrollbar": scrollx.triggerEvent,
                        "mousewheel.scrollbar": scrollx.triggerEvent,
                        "mouseenter.scrollbar": function(){
                            scrollToValue = c[scrollOffset]();
                        }
                    });

                    // handle arrows & scroll inner mousedown event
                    scrollx.scrollbar.find(".scroll-arrow, .scroll-element_track")
                        .on("mousedown.scrollbar", function(event){

                            if(event.which != lmb)
                                return true;

                            scrollForward = 1;

                            var data = {
                                "eventOffset": event[(d == "x") ? "pageX" : "pageY"],
                                "maxScrollValue": scrollx.size - scrollx.visible - scrollx.offset,
                                "scrollbarOffset": scrollx.scroller.offset()[(d == "x") ? rtl?"right":"left" : "top"],
                                "scrollbarSize": scrollx.scroller[(d == "x") ? "outerWidth" : "outerHeight"]()
                            };
                            var timeout = 0, timer = 0;

                            if($(this).hasClass('scroll-arrow')){
                                scrollForward = $(this).hasClass("scroll-arrow_more") ? 1 : -1;
                                scrollStep = o.scrollStep * scrollForward;
                                scrollToValue = scrollForward > 0 ? data.maxScrollValue : 0;
                            } else {
                                scrollForward = (data.eventOffset > (data.scrollbarOffset + data.scrollbarSize) ? 1
                                    : (data.eventOffset < data.scrollbarOffset ? -1 : 0));
                                scrollStep = Math.round(scrollx.visible * 0.75) * scrollForward;
                                scrollToValue = (data.eventOffset - data.scrollbarOffset -
                                    (o.stepScrolling ? (scrollForward == 1 ? data.scrollbarSize : 0)
                                        : Math.round(data.scrollbarSize / 2)));
                                scrollToValue = c[scrollOffset]() + (scrollToValue / scrollx.kx);
                            }

                            S.scrollTo = S.scrollTo || {};
                            S.scrollTo[scrollOffset] = o.stepScrolling ? c[scrollOffset]() + scrollStep : scrollToValue;

                            if(o.stepScrolling){
                                scrollCallback = function(){
                                    scrollToValue = c[scrollOffset]();
                                    clearInterval(timer);
                                    clearTimeout(timeout);
                                    timeout = 0;
                                    timer = 0;
                                };
                                timeout = setTimeout(function(){
                                    timer = setInterval(scrollTo, 40);
                                }, o.duration + 100);
                            }

                            setTimeout(function(){
                                if(S.scrollTo){
                                    c.animate(S.scrollTo, o.duration);
                                    S.scrollTo = null;
                                }
                            }, 1);

                            return handleMouseDown(scrollCallback, event);
                        });

                    // handle scrollbar drag'n'drop
                    scrollx.scroller.on("mousedown.scrollbar", function(event){

                        if(event.which != lmb)
                            return true;

                        var eventPosition = event[(d == "x")? "pageX" : "pageY"];
                        var initOffset = c[scrollOffset]();

                        scrollx.scrollbar.addClass("scroll-draggable");

                        $(doc).on("mousemove.scrollbar", function(event){
                            var diff = parseInt((event[(d == "x")? "pageX" : "pageY"] - eventPosition) / scrollx.kx, 10);
                            c[scrollOffset](initOffset + diff);
                        });

                        return handleMouseDown(function(){
                            scrollx.scrollbar.removeClass("scroll-draggable");
                            scrollToValue = c[scrollOffset]();
                        }, event);
                    });
                }
            });

            // remove classes & reset applied styles
            $.each(s, function(d, scrollx){
                var scrollClass = "scroll-scroll" + d + "_visible";
                var scrolly = (d == "x") ? s.y : s.x;

                scrollx.scrollbar.removeClass(scrollClass);
                scrolly.scrollbar.removeClass(scrollClass);
                cw.removeClass(scrollClass);
            });

            // calculate init sizes
            $.each(s, function(d, scrollx){
                $.extend(scrollx, (d == "x") ? {
                    "offset": parseInt(c.css(rtl?"right":"left"), 10) || 0,
                    "size": c.prop("scrollWidth"),
                    "visible": w.width()
                } : {
                    "offset": parseInt(c.css("top"), 10) || 0,
                    "size": c.prop("scrollHeight"),
                    "visible": w.height()
                });
            });


            var updateScroll = function(d, scrollx){

                var scrollClass = "scroll-scroll" + d + "_visible";
                var scrolly = (d == "x") ? s.y : s.x;
                var offset = parseInt(c.css((d == "x") ? rtl?"right":"left" : "top"), 10) || 0;

                var AreaSize = scrollx.size;
                var AreaVisible = scrollx.visible + offset;

                scrollx.isVisible = (AreaSize - AreaVisible) > 1; // bug in IE9/11 with 1px diff
                if(scrollx.isVisible){
                    scrollx.scrollbar.addClass(scrollClass);
                    scrolly.scrollbar.addClass(scrollClass);
                    cw.addClass(scrollClass);
                } else {
                    scrollx.scrollbar.removeClass(scrollClass);
                    scrolly.scrollbar.removeClass(scrollClass);
                    cw.removeClass(scrollClass);
                }

                if(d == "y" && (scrollx.isVisible || scrollx.size < scrollx.visible)){
                    cw.css("height", (AreaVisible + browser.scroll.height) + px);
                }

                if(s.x.size != c.prop("scrollWidth")
                    || s.y.size != c.prop("scrollHeight")
                    || s.x.visible != w.width()
                    || s.y.visible != w.height()
                    || s.x.offset  != (parseInt(c.css(rtl?"right":"left"), 10) || 0)
                    || s.y.offset  != (parseInt(c.css("top"), 10) || 0)
                    ){
                    $.each(s, function(d, scrollx){
                        $.extend(scrollx, (d == "x") ? {
                            "offset": parseInt(c.css(rtl?"right":"left"), 10) || 0,
                            "size": c.prop("scrollWidth"),
                            "visible": w.width()
                        } : {
                            "offset": parseInt(c.css("top"), 10) || 0,
                            "size": c.prop("scrollHeight"),
                            "visible": w.height()
                        });
                    });
                    updateScroll(d == "x" ? "y" : "x", scrolly);
                }
            };
            $.each(s, updateScroll);

            if($.isFunction(o.onUpdate))
                o.onUpdate.apply(this, [c]);

            // calculate scroll size
            $.each(s, function(d, scrollx){

                var cssOffset = (d == "x") ? rtl?"right":"left" : "top";
                var cssFullSize = (d == "x") ? "outerWidth" : "outerHeight";
                var cssSize = (d == "x") ? "width" : "height";
                var offset = parseInt(c.css(cssOffset), 10) || 0;

                var AreaSize = scrollx.size;
                var AreaVisible = scrollx.visible + offset;

                var scrollSize = scrollx.scrollbar.find(".scroll-element_size");
                scrollSize = scrollSize[cssFullSize]() + (parseInt(scrollSize.css(cssOffset), 10) || 0);

                if(o.autoScrollSize){
                    scrollx.scrollbarSize = parseInt(scrollSize * AreaVisible / AreaSize, 10);
                    scrollx.scroller.css(cssSize, scrollx.scrollbarSize + px);
                }

                scrollx.scrollbarSize = scrollx.scroller[cssFullSize]();
                scrollx.kx = ((scrollSize - scrollx.scrollbarSize) / (AreaSize - AreaVisible)) || 1;
                scrollx.maxScrollOffset = AreaSize - AreaVisible;
            });

            c.scrollLeft(initScroll.scrollLeft).scrollTop(initScroll.scrollTop).trigger("scroll");
        }
    };

    /*
     * Extend jQuery as plugin
     *
     * @param {object|string} options or command to execute
     * @param {object|array} args additional arguments as array []
     */
    $.fn.scrollbar = function(options, args){

        var toReturn = this;

        if(options === "get")
            toReturn = null;

        this.each(function() {

            var container = $(this);

            if(container.hasClass("scroll-wrapper")
                || container.get(0).nodeName == "body"){
                return true;
            }

            var instance = container.data("scrollbar");
            if(instance){
                if(options === "get"){
                    toReturn = instance;
                    return false;
                }

                var func = (typeof options == "string" && instance[options]) ? options : "init";
                instance[func].apply(instance, $.isArray(args) ? args : []);

                if(options === "destroy"){
                    container.removeData("scrollbar");
                    while($.inArray(instance, browser.scrolls) >= 0)
                        browser.scrolls.splice($.inArray(instance, browser.scrolls), 1);
                }
            } else {
                if(typeof options != "string"){
                    instance = new customScrollbar(container, options);
                    container.data("scrollbar", instance);
                    browser.scrolls.push(instance);
                }
            }
            return true;
        });

        return toReturn;
    };

    /**
     * Connect default options to global object
     */
    $.fn.scrollbar.options = defaults;

    /**
     * Extend AngularJS as UI directive
     *
     *
     */
    if(win.angular){
        (function(angular){
            var app = angular.module('jQueryScrollbar', []);
            app.directive('jqueryScrollbar', function(){
                return {
                    "link": function(scope, element){
                        element.scrollbar(scope.options).on('$destroy', function(){
                            element.scrollbar('destroy');
                        });
                    },
                    "restring": "AC",
                    "scope": {
                        "options": "=jqueryScrollbar"
                    }
                };
            });
        })(win.angular);
    }

    /**
     * Check if scroll content/container size is changed
     */
    var timer = 0, timerCounter = 0;
    var updateScrollbars = function(force){
        var i, c, o, s, w, x, y;
        for( i = 0; i < browser.scrolls.length; i++){
            s = browser.scrolls[i];
            c = s.container;
            o = s.options;
            w = s.wrapper;
            x = s.scrollx;
            y = s.scrolly;
            if(force || (o.autoUpdate && w && w.is(":visible") &&
                (c.prop("scrollWidth") != x.size
                    || c.prop("scrollHeight") != y.size
                    || w.width()  != x.visible
                    || w.height() != y.visible
                    ))){
                s.init();

                if(debug){
                    browser.log({
                        "scrollHeight":  c.prop("scrollHeight") + ":" + s.scrolly.size,
                        "scrollWidth":   c.prop("scrollWidth") + ":" + s.scrollx.size,
                        "visibleHeight": w.height() + ":" + s.scrolly.visible,
                        "visibleWidth":  w.width() + ":" + s.scrollx.visible
                    }, true);
                    timerCounter++;
                }
            }
        }
        if(debug && timerCounter > 10){
            browser.log("Scroll updates exceed 10");
            updateScrollbars = function(){};
        } else {
            clearTimeout(timer);
            timer = setTimeout(updateScrollbars, 300);
        }
    };

    /* ADDITIONAL FUNCTIONS */
    /**
     * Get native browser scrollbar size (height/width)
     *
     * @param {Boolean} actual size or CSS size, default - CSS size
     * @returns {Object} with height, width
     */
    function getBrowserScrollSize(actualSize){

        if(browser.webkit && !actualSize){
            return {
                "height": 0,
                "width": 0
            };
        }

        var css = {
            "border":  "none",
            "box-sizing": "content-box",
            "height":  "200px",
            "margin":  "0",
            "padding": "0",
            "width":   "200px"
        };
        browser.data.inner = $("<div>").css($.extend({}, css));
        browser.data.outer = $("<div>").css($.extend({
            "left":       "-1000px",
            "overflow":   "scroll",
            "position":   "absolute",
            "top":        "-1000px",
            "direction":  "ltr"
        }, css)).append(browser.data.inner).appendTo("body");

        browser.data.outer.scrollLeft(1000).scrollTop(1000);

        var ret = {
            "height": Math.ceil((browser.data.outer.offset().top - browser.data.inner.offset().top) || 0),
            "width": Math.ceil((browser.data.outer.offset().left - browser.data.inner.offset().left) || 0)
        };

        browser.data.inner.remove();
        browser.data.outer.remove();

        return ret;
    }

    function handleMouseDown(callback, event){
        $(doc).on({
            "blur.scrollbar": function(){
                $(doc).add('body').off('.scrollbar');
                callback && callback();
            },
            "dragstart.scrollbar": function(event){
                event.preventDefault();
                return false;
            },
            "mouseup.scrollbar": function(){
                $(doc).add('body').off('.scrollbar');
                callback && callback();
            }
        });
        $("body").on({
            "selectstart.scrollbar": function(event){
                event.preventDefault();
                return false;
            }
        });
        event && event.preventDefault();
        return false;
    }

    /**
     * Check if native browser scrollbars overlay content
     *
     * @returns {Boolean}
     */
    function isScrollOverlaysContent(){
        var scrollSize = getBrowserScrollSize(true);
        return !(scrollSize.height || scrollSize.width);
    }

    function isVerticalScroll(event){
        var e = event.originalEvent;
        if (e.axis && e.axis === e.HORIZONTAL_AXIS)
            return false;
        if (e.wheelDeltaX)
            return false;
        return true;
    }

})(jQuery, document, window);

/*global jQuery: true */

/*!
   --------------------------------
   Infinite Scroll
   --------------------------------
   + https://github.com/paulirish/infinite-scroll
   + version 2.1.0
   + Copyright 2011/12 Paul Irish & Luke Shumard
   + Licensed under the MIT license

   + Documentation: http://infinite-scroll.com/
*/

// Uses AMD or browser globals to create a jQuery plugin.
(function (factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function ($, undefined) {
    'use strict';

    $.infinitescroll = function infscr(options, callback, element) {
        this.element = $(element);

        // Flag the object in the event of a failed creation
        if (!this._create(options, callback)) {
            this.failed = true;
        }
    };

    $.infinitescroll.defaults = {
        loading: {
            finished: undefined,
            finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>",
            img: 'data:image/gif;base64,R0lGODlh3AATAPQeAPDy+MnQ6LW/4N3h8MzT6rjC4sTM5r/I5NHX7N7j8c7U6tvg8OLl8uXo9Ojr9b3G5MfP6Ovu9tPZ7PT1+vX2+tbb7vf4+8/W69jd7rC73vn5/O/x+K243ai02////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQECgD/ACwAAAAA3AATAAAF/6AnjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEj0BAScpHLJbDqf0Kh0Sq1ar9isdioItAKGw+MAKYMFhbF63CW438f0mg1R2O8EuXj/aOPtaHx7fn96goR4hmuId4qDdX95c4+RBIGCB4yAjpmQhZN0YGYGXitdZBIVGAsLoq4BBKQDswm1CQRkcG6ytrYKubq8vbfAcMK9v7q7EMO1ycrHvsW6zcTKsczNz8HZw9vG3cjTsMIYqQkCLBwHCgsMDQ4RDAYIqfYSFxDxEfz88/X38Onr16+Bp4ADCco7eC8hQYMAEe57yNCew4IVBU7EGNDiRn8Z831cGLHhSIgdFf9chIeBg7oA7gjaWUWTVQAGE3LqBDCTlc9WOHfm7PkTqNCh54rePDqB6M+lR536hCpUqs2gVZM+xbrTqtGoWqdy1emValeXKzggYBBB5y1acFNZmEvXAoN2cGfJrTv3bl69Ffj2xZt3L1+/fw3XRVw4sGDGcR0fJhxZsF3KtBTThZxZ8mLMgC3fRatCbYMNFCzwLEqLgE4NsDWs/tvqdezZf13Hvk2A9Szdu2X3pg18N+68xXn7rh1c+PLksI/Dhe6cuO3ow3NfV92bdArTqC2Ebd3A8vjf5QWfH6Bg7Nz17c2fj69+fnq+8N2Lty+fuP78/eV2X13neIcCeBRwxorbZrA1ANoCDGrgoG8RTshahQ9iSKEEzUmYIYfNWViUhheCGJyIP5E4oom7WWjgCeBFAJNv1DVV01MAdJhhjdkplWNzO/5oXI846njjVEIqR2OS2B1pE5PVscajkxhMycqLJghQSwT40PgfAl4GqNSXYdZXJn5gSkmmmmJu1aZYb14V51do+pTOCmA40AqVCIhG5IJ9PvYnhIFOxmdqhpaI6GeHCtpooisuutmg+Eg62KOMKuqoTaXgicQWoIYq6qiklmoqFV0UoeqqrLbq6quwxirrrLTWauutJ4QAACH5BAUKABwALAcABADOAAsAAAX/IPd0D2dyRCoUp/k8gpHOKtseR9yiSmGbuBykler9XLAhkbDavXTL5k2oqFqNOxzUZPU5YYZd1XsD72rZpBjbeh52mSNnMSC8lwblKZGwi+0QfIJ8CncnCoCDgoVnBHmKfByGJimPkIwtiAeBkH6ZHJaKmCeVnKKTHIihg5KNq4uoqmEtcRUtEREMBggtEr4QDrjCuRC8h7/BwxENeicSF8DKy82pyNLMOxzWygzFmdvD2L3P0dze4+Xh1Arkyepi7dfFvvTtLQkZBC0T/FX3CRgCMOBHsJ+EHYQY7OinAGECgQsB+Lu3AOK+CewcWjwxQeJBihtNGHSoQOE+iQ3//4XkwBBhRZMcUS6YSXOAwIL8PGqEaSJCiYt9SNoCmnJPAgUVLChdaoFBURN8MAzl2PQphwQLfDFd6lTowglHve6rKpbjhK7/pG5VinZP1qkiz1rl4+tr2LRwWU64cFEihwEtZgbgR1UiHaMVvxpOSwBA37kzGz9e8G+B5MIEKLutOGEsAH2ATQwYfTmuX8aETWdGPZmiZcccNSzeTCA1Sw0bdiitC7LBWgu8jQr8HRzqgpK6gX88QbrB14z/kF+ELpwB8eVQj/JkqdylAudji/+ts3039vEEfK8Vz2dlvxZKG0CmbkKDBvllRd6fCzDvBLKBDSCeffhRJEFebFk1k/Mv9jVIoIJZSeBggwUaNeB+Qk34IE0cXlihcfRxkOAJFFhwGmKlmWDiakZhUJtnLBpnWWcnKaAZcxI0piFGGLBm1mc90kajSCveeBVWKeYEoU2wqeaQi0PetoE+rr14EpVC7oAbAUHqhYExbn2XHHsVqbcVew9tx8+XJKk5AZsqqdlddGpqAKdbAYBn1pcczmSTdWvdmZ17c1b3FZ99vnTdCRFM8OEcAhLwm1NdXnWcBBSMRWmfkWZqVlsmLIiAp/o1gGV2vpS4lalGYsUOqXrddcKCmK61aZ8SjEpUpVFVoCpTj4r661Km7kBHjrDyc1RAIQAAIfkEBQoAGwAsBwAEAM4ACwAABf/gtmUCd4goQQgFKj6PYKi0yrrbc8i4ohQt12EHcal+MNSQiCP8gigdz7iCioaCIvUmZLp8QBzW0EN2vSlCuDtFKaq4RyHzQLEKZNdiQDhRDVooCwkbfm59EAmKi4SGIm+AjIsKjhsqB4mSjT2IOIOUnICeCaB/mZKFNTSRmqVpmJqklSqskq6PfYYCDwYHDC4REQwGCBLGxxIQDsHMwhAIX8bKzcENgSLGF9PU1j3Sy9zX2NrgzQziChLk1BHWxcjf7N046tvN82715czn9Pryz6Ilc4ACj4EBOCZM8KEnAYYADBRKnACAYUMFv1wotIhCEcaJCisqwJFgAUSQGyX/kCSVUUTIdKMwJlyo0oXHlhskwrTJciZHEXsgaqS4s6PJiCAr1uzYU8kBBSgnWFqpoMJMUjGtDmUwkmfVmVypakWhEKvXsS4nhLW5wNjVroJIoc05wSzTr0PtiigpYe4EC2vj4iWrFu5euWIMRBhacaVJhYQBEFjA9jHjyQ0xEABwGceGAZYjY0YBOrRLCxUp29QM+bRkx5s7ZyYgVbTqwwti2ybJ+vLtDYpycyZbYOlptxdx0kV+V7lC5iJAyyRrwYKxAdiz82ng0/jnAdMJFz0cPi104Ec1Vj9/M6F173vKL/feXv156dw11tlqeMMnv4V5Ap53GmjQQH97nFfg+IFiucfgRX5Z8KAgbUlQ4IULIlghhhdOSB6AgX0IVn8eReghen3NRIBsRgnH4l4LuEidZBjwRpt6NM5WGwoW0KSjCwX6yJSMab2GwwAPDXfaBCtWpluRTQqC5JM5oUZAjUNS+VeOLWpJEQ7VYQANW0INJSZVDFSnZphjSikfmzE5N4EEbQI1QJmnWXCmHulRp2edwDXF43txukenJwvI9xyg9Q26Z3MzGUcBYFEChZh6DVTq34AU8Iflh51Sd+CnKFYQ6mmZkhqfBKfSxZWqA9DZanWjxmhrWwi0qtCrt/43K6WqVjjpmhIqgEGvculaGKklKstAACEAACH5BAUKABwALAcABADOAAsAAAX/ICdyQmaMYyAUqPgIBiHPxNpy79kqRXH8wAPsRmDdXpAWgWdEIYm2llCHqjVHU+jjJkwqBTecwItShMXkEfNWSh8e1NGAcLgpDGlRgk7EJ/6Ae3VKfoF/fDuFhohVeDeCfXkcCQqDVQcQhn+VNDOYmpSWaoqBlUSfmowjEA+iEAEGDRGztAwGCDcXEA60tXEiCrq8vREMEBLIyRLCxMWSHMzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/Cpk3ABwSLQkYAQwT/P309vcI7OvXr94jBQMJ/nskkGA/BQBRLNDncAIAiDcG6LsxAWOLiQzmeURBKWSLCQbv/1F0eDGinJUKR47YY1IEgQASKk7Yc7ACRwZm7mHweRJoz59BJUogisKCUaFMR0x4SlJBVBFTk8pZivTR0K73rN5wqlXEAq5Fy3IYgHbEzQ0nLy4QSoCjXLoom96VOJEeCosK5n4kkFfqXjl94wa+l1gvAcGICbewAOAxY8l/Ky/QhAGz4cUkGxu2HNozhwMGBnCUqUdBg9UuW9eUynqSwLHIBujePef1ZGQZXcM+OFuEBeBhi3OYgLyqcuaxbT9vLkf4SeqyWxSQpKGB2gQpm1KdWbu72rPRzR9Ne2Nu9Kzr/1Jqj0yD/fvqP4aXOt5sW/5qsXXVcv1Nsp8IBUAmgswGF3llGgeU1YVXXKTN1FlhWFXW3gIE+DVChApysACHHo7Q4A35lLichh+ROBmLKAzgYmYEYDAhCgxKGOOMn4WR4kkDaoBBOxJtdNKQxFmg5JIWIBnQc07GaORfUY4AEkdV6jHlCEISSZ5yTXpp1pbGZbkWmcuZmQCaE6iJ0FhjMaDjTMsgZaNEHFRAQVp3bqXnZED1qYcECOz5V6BhSWCoVJQIKuKQi2KFKEkEFAqoAo7uYSmO3jk61wUUMKmknJ4SGimBmAa0qVQBhAAAIfkEBQoAGwAsBwAEAM4ACwAABf/gJm5FmRlEqhJC+bywgK5pO4rHI0D3pii22+Mg6/0Ej96weCMAk7cDkXf7lZTTnrMl7eaYoy10JN0ZFdco0XAuvKI6qkgVFJXYNwjkIBcNBgR8TQoGfRsJCRuCYYQQiI+ICosiCoGOkIiKfSl8mJkHZ4U9kZMbKaI3pKGXmJKrngmug4WwkhA0lrCBWgYFCCMQFwoQDRHGxwwGCBLMzRLEx8iGzMMO0cYNeCMKzBDW19lnF9DXDIY/48Xg093f0Q3s1dcR8OLe8+Y91OTv5wrj7o7B+7VNQqABIoRVCMBggsOHE36kSoCBIcSH3EbFangxogJYFi8CkJhqQciLJEf/LDDJEeJIBT0GsOwYUYJGBS0fjpQAMidGmyVP6sx4Y6VQhzs9VUwkwqaCCh0tmKoFtSMDmBOf9phg4SrVrROuasRQAaxXpVUhdsU6IsECZlvX3kwLUWzRt0BHOLTbNlbZG3vZinArge5Dvn7wbqtQkSYAAgtKmnSsYKVKo2AfW048uaPmG386i4Q8EQMBAIAnfB7xBxBqvapJ9zX9WgRS2YMpnvYMGdPK3aMjt/3dUcNI4blpj7iwkMFWDXDvSmgAlijrt9RTR78+PS6z1uAJZIe93Q8g5zcsWCi/4Y+C8bah5zUv3vv89uft30QP23punGCx5954oBBwnwYaNCDY/wYrsYeggnM9B2Fpf8GG2CEUVWhbWAtGouEGDy7Y4IEJVrbSiXghqGKIo7z1IVcXIkKWWR361QOLWWnIhwERpLaaCCee5iMBGJQmJGyPFTnbkfHVZGRtIGrg5HALEJAZbu39BuUEUmq1JJQIPtZilY5hGeSWsSk52G9XqsmgljdIcABytq13HyIM6RcUA+r1qZ4EBF3WHWB29tBgAzRhEGhig8KmqKFv8SeCeo+mgsF7YFXa1qWSbkDpom/mqR1PmHCqJ3fwNRVXjC7S6CZhFVCQ2lWvZiirhQq42SACt25IK2hv8TprriUV1usGgeka7LFcNmCldMLi6qZMgFLgpw16Cipb7bC1knXsBiEAACH5BAUKABsALAcABADOAAsAAAX/4FZsJPkUmUGsLCEUTywXglFuSg7fW1xAvNWLF6sFFcPb42C8EZCj24EJdCp2yoegWsolS0Uu6fmamg8n8YYcLU2bXSiRaXMGvqV6/KAeJAh8VgZqCX+BexCFioWAYgqNi4qAR4ORhRuHY408jAeUhAmYYiuVlpiflqGZa5CWkzc5fKmbbhIpsAoQDRG8vQwQCBLCwxK6vb5qwhfGxxENahvCEA7NzskSy7vNzzzK09W/PNHF1NvX2dXcN8K55cfh69Luveol3vO8zwi4Yhj+AQwmCBw4IYclDAAJDlQggVOChAoLKkgFkSCAHDwWLKhIEOONARsDKryogFPIiAUb/95gJNIiw4wnI778GFPhzBKFOAq8qLJEhQpiNArjMcHCmlTCUDIouTKBhApELSxFWiGiVKY4E2CAekPgUphDu0742nRrVLJZnyrFSqKQ2ohoSYAMW6IoDpNJ4bLdILTnAj8KUF7UeENjAKuDyxIgOuGiOI0EBBMgLNew5AUrDTMGsFixwBIaNCQuAXJB57qNJ2OWm2Aj4skwCQCIyNkhhtMkdsIuodE0AN4LJDRgfLPtn5YDLdBlraAByuUbBgxQwICxMOnYpVOPej074OFdlfc0TqC62OIbcppHjV4o+LrieWhfT8JC/I/T6W8oCl29vQ0XjLdBaA3s1RcPBO7lFvpX8BVoG4O5jTXRQRDuJ6FDTzEWF1/BCZhgbyAKE9qICYLloQYOFtahVRsWYlZ4KQJHlwHS/IYaZ6sZd9tmu5HQm2xi1UaTbzxYwJk/wBF5g5EEYOBZeEfGZmNdFyFZmZIR4jikbLThlh5kUUVJGmRT7sekkziRWUIACABk3T4qCsedgO4xhgGcY7q5pHJ4klBBTQRJ0CeHcoYHHUh6wgfdn9uJdSdMiebGJ0zUPTcoS286FCkrZxnYoYYKWLkBowhQoBeaOlZAgVhLidrXqg2GiqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/oGFw2WZuT5oZROsSQnGaKjRvilI893MItlNOJ5v5gDcFrHhKIWcEYu/xFEqNv6B1N62aclysF7fsZYe5aOx2yL5aAUGSaT1oTYMBwQ5VGCAJgYIJCnx1gIOBhXdwiIl7d0p2iYGQUAQBjoOFSQR/lIQHnZ+Ue6OagqYzSqSJi5eTpTxGcjcSChANEbu8DBAIEsHBChe5vL13G7fFuscRDcnKuM3H0La3EA7Oz8kKEsXazr7Cw9/Gztar5uHHvte47MjktznZ2w0G1+D3BgirAqJmJMAQgMGEgwgn5Ei0gKDBhBMALGRYEOJBb5QcWlQo4cbAihZz3GgIMqFEBSM1/4ZEOWPAgpIIJXYU+PIhRG8ja1qU6VHlzZknJNQ6UanCjQkWCIGSUGEjAwVLjc44+DTqUQtPPS5gejUrTa5TJ3g9sWCr1BNUWZI161StiQUDmLYdGfesibQ3XMq1OPYthrwuA2yU2LBs2cBHIypYQPPlYAKFD5cVvNPtW8eVGbdcQADATsiNO4cFAPkvHpedPzc8kUcPgNGgZ5RNDZG05reoE9s2vSEP79MEGiQGy1qP8LA4ZcdtsJE48ONoLTBtTV0B9LsTnPceoIDBDQvS7W7vfjVY3q3eZ4A339J4eaAmKqU/sV58HvJh2RcnIBsDUw0ABqhBA5aV5V9XUFGiHfVeAiWwoFgJJrIXRH1tEMiDFV4oHoAEGlaWhgIGSGBO2nFomYY3mKjVglidaNYJGJDkWW2xxTfbjCbVaOGNqoX2GloR8ZeTaECS9pthRGJH2g0b3Agbk6hNANtteHD2GJUucfajCQBy5OOTQ25ZgUPvaVVQmbKh9510/qQpwXx3SQdfk8tZJOd5b6JJFplT3ZnmmX3qd5l1eg5q00HrtUkUn0AKaiGjClSAgKLYZcgWXwocGRcCFGCKwSB6ceqphwmYRUFYT/1WKlOdUpipmxW0mlCqHjYkAaeoZlqrqZ4qd+upQKaapn/AmgAegZ8KUtYtFAQQAgAh+QQFCgAbACwHAAQAzgALAAAF/+C2PUcmiCiZGUTrEkKBis8jQEquKwU5HyXIbEPgyX7BYa5wTNmEMwWsSXsqFbEh8DYs9mrgGjdK6GkPY5GOeU6ryz7UFopSQEzygOGhJBjoIgMDBAcBM0V/CYqLCQqFOwobiYyKjn2TlI6GKC2YjJZknouaZAcQlJUHl6eooJwKooobqoewrJSEmyKdt59NhRKFMxLEEA4RyMkMEAjDEhfGycqAG8TQx9IRDRDE3d3R2ctD1RLg0ttKEnbY5wZD3+zJ6M7X2RHi9Oby7u/r9g38UFjTh2xZJBEBMDAboogAgwkQI07IMUORwocSJwCgWDFBAIwZOaJIsOBjRogKJP8wTODw5ESVHVtm3AhzpEeQElOuNDlTZ0ycEUWKWFASqEahGwYUPbnxoAgEdlYSqDBkgoUNClAlIHbSAoOsqCRQnQHxq1axVb06FWFxLIqyaze0Tft1JVqyE+pWXMD1pF6bYl3+HTqAWNW8cRUFzmih0ZAAB2oGKukSAAGGRHWJgLiR6AylBLpuHKKUMlMCngMpDSAa9QIUggZVVvDaJobLeC3XZpvgNgCmtPcuwP3WgmXSq4do0DC6o2/guzcseECtUoO0hmcsGKDgOt7ssBd07wqesAIGZC1YIBa7PQHvb1+SFo+++HrJSQfB33xfav3i5eX3Hnb4CTJgegEq8tH/YQEOcIJzbm2G2EoYRLgBXFpVmFYDcREV4HIcnmUhiGBRouEMJGJGzHIspqgdXxK0yCKHRNXoIX4uorCdTyjkyNtdPWrA4Up82EbAbzMRxxZRR54WXVLDIRmRcag5d2R6ugl3ZXzNhTecchpMhIGVAKAYpgJjjsSklBEd99maZoo535ZvdamjBEpusJyctg3h4X8XqodBMx0tiNeg/oGJaKGABpogS40KSqiaEgBqlQWLUtqoVQnytekEjzo0hHqhRorppOZt2p923M2AAV+oBtpAnnPNoB6HaU6mAAIU+IXmi3j2mtFXuUoHKwXpzVrsjcgGOauKEjQrwq157hitGq2NoWmjh7z6Wmxb0m5w66+2VRAuXN/yFUAIACH5BAUKABsALAcABADOAAsAAAX/4CZuRiaM45MZqBgIRbs9AqTcuFLE7VHLOh7KB5ERdjJaEaU4ClO/lgKWjKKcMiJQ8KgumcieVdQMD8cbBeuAkkC6LYLhOxoQ2PF5Ys9PKPBMen17f0CCg4VSh32JV4t8jSNqEIOEgJKPlkYBlJWRInKdiJdkmQlvKAsLBxdABA4RsbIMBggtEhcQsLKxDBC2TAS6vLENdJLDxMZAubu8vjIbzcQRtMzJz79S08oQEt/guNiyy7fcvMbh4OezdAvGrakLAQwyABsELQkY9BP+//ckyPDD4J9BfAMh1GsBoImMeQUN+lMgUJ9CiRMa5msxoB9Gh/o8GmxYMZXIgxtR/yQ46S/gQAURR0pDwYDfywoyLPip5AdnCwsMFPBU4BPFhKBDi444quCmDKZOfwZ9KEGpCKgcN1jdALSpPqIYsabS+nSqvqplvYqQYAeDPgwKwjaMtiDl0oaqUAyo+3TuWwUAMPpVCfee0cEjVBGQq2ABx7oTWmQk4FglZMGN9fGVDMCuiH2AOVOu/PmyxM630gwM0CCn6q8LjVJ8GXvpa5Uwn95OTC/nNxkda1/dLSK475IjCD6dHbK1ZOa4hXP9DXs5chJ00UpVm5xo2qRpoxptwF2E4/IbJpB/SDz9+q9b1aNfQH08+p4a8uvX8B53fLP+ycAfemjsRUBgp1H20K+BghHgVgt1GXZXZpZ5lt4ECjxYR4ScUWiShEtZqBiIInRGWnERNnjiBglw+JyGnxUmGowsyiiZg189lNtPGACjV2+S9UjbU0JWF6SPvEk3QZEqsZYTk3UAaRSUnznJI5LmESCdBVSyaOWUWLK4I5gDUYVeV1T9l+FZClCAUVA09uSmRHBCKAECFEhW51ht6rnmWBXkaR+NjuHpJ40D3DmnQXt2F+ihZxlqVKOfQRACACH5BAUKABwALAcABADOAAsAAAX/ICdyUCkUo/g8mUG8MCGkKgspeC6j6XEIEBpBUeCNfECaglBcOVfJFK7YQwZHQ6JRZBUqTrSuVEuD3nI45pYjFuWKvjjSkCoRaBUMWxkwBGgJCXspQ36Bh4EEB0oKhoiBgyNLjo8Ki4QElIiWfJqHnISNEI+Ql5J9o6SgkqKkgqYihamPkW6oNBgSfiMMDQkGCBLCwxIQDhHIyQwQCGMKxsnKVyPCF9DREQ3MxMPX0cu4wt7J2uHWx9jlKd3o39MiuefYEcvNkuLt5O8c1ePI2tyELXGQwoGDAQf+iEC2xByDCRAjTlAgIUWCBRgCPJQ4AQBFXAs0coT40WLIjRxL/47AcHLkxIomRXL0CHPERZkpa4q4iVKiyp0tR/7kwHMkTUBBJR5dOCEBAVcKKtCAyOHpowXCpk7goABqBZdcvWploACpBKkpIJI1q5OD2rIWE0R1uTZu1LFwbWL9OlKuWb4c6+o9i3dEgw0RCGDUG9KlRw56gDY2qmCByZBaASi+TACA0TucAaTteCcy0ZuOK3N2vJlx58+LRQyY3Xm0ZsgjZg+oPQLi7dUcNXi0LOJw1pgNtB7XG6CBy+U75SYfPTSQAgZTNUDnQHt67wnbZyvwLgKiMN3oCZB3C76tdewpLFgIP2C88rbi4Y+QT3+8S5USMICZXWj1pkEDeUU3lOYGB3alSoEiMIjgX4WlgNF2EibIwQIXauWXSRg2SAOHIU5IIIMoZkhhWiJaiFVbKo6AQEgQXrTAazO1JhkBrBG3Y2Y6EsUhaGn95hprSN0oWpFE7rhkeaQBchGOEWnwEmc0uKWZj0LeuNV3W4Y2lZHFlQCSRjTIl8uZ+kG5HU/3sRlnTG2ytyadytnD3HrmuRcSn+0h1dycexIK1KCjYaCnjCCVqOFFJTZ5GkUUjESWaUIKU2lgCmAKKQIUjHapXRKE+t2og1VgankNYnohqKJ2CmKplso6GKz7WYCgqxeuyoF8u9IQAgA7',
            msg: null,
            msgText: '<em>Loading the next set of posts...</em>',
            selector: null,
            speed: 'fast',
            start: undefined
        },
        state: {
            isDuringAjax: false,
            isInvalidPage: false,
            isDestroyed: false,
            isDone: false, // For when it goes all the way through the archive.
            isPaused: false,
            isBeyondMaxPage: false,
            currPage: 1
        },
        debug: false,
        behavior: undefined,
        binder: $(window), // used to cache the selector
        nextSelector: 'div.navigation a:first',
        navSelector: 'div.navigation',
        contentSelector: null, // rename to pageFragment
        extraScrollPx: 150,
        itemSelector: 'div.post',
        animate: false,
        pathParse: undefined,
        dataType: 'html',
        appendCallback: true,
        bufferPx: 40,
        errorCallback: function () { },
        infid: 0, //Instance ID
        pixelsFromNavToBottom: undefined,
        path: undefined, // Either parts of a URL as an array (e.g. ["/page/", "/"] or a function that takes in the page number and returns a URL
        prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted
        maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work)
    };

    $.infinitescroll.prototype = {

        /*
            ----------------------------
            Private methods
            ----------------------------
            */

        // Bind or unbind from scroll
        _binding: function infscr_binding(binding) {

            var instance = this,
            opts = instance.options;

            opts.v = '2.0b2.120520';

            // if behavior is defined and this function is extended, call that instead of default
            if (!!opts.behavior && this['_binding_'+opts.behavior] !== undefined) {
                this['_binding_'+opts.behavior].call(this);
                return;
            }

            if (binding !== 'bind' && binding !== 'unbind') {
                this._debug('Binding value  ' + binding + ' not valid');
                return false;
            }

            if (binding === 'unbind') {
                (this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid);
            } else {
                (this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () {
                    instance.scroll();
                });
            }

            this._debug('Binding', binding);
        },

        // Fundamental aspects of the plugin are initialized
        _create: function infscr_create(options, callback) {

            // Add custom options to defaults
            var opts = $.extend(true, {}, $.infinitescroll.defaults, options);
            this.options = opts;
            var $window = $(window);
            var instance = this;

            // Validate selectors
            if (!instance._validate(options)) {
                return false;
            }

            // Validate page fragment path
            var path = $(opts.nextSelector).attr('href');
            if (!path) {
                this._debug('Navigation selector not found');
                return false;
            }

            // Set the path to be a relative URL from root.
            opts.path = opts.path || this._determinepath(path);

            // contentSelector is 'page fragment' option for .load() / .ajax() calls
            opts.contentSelector = opts.contentSelector || this.element;

            // loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector
            opts.loading.selector = opts.loading.selector || opts.contentSelector;

            // Define loading.msg
            opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>');

            // Preload loading.img
            (new Image()).src = opts.loading.img;

            // distance from nav links to bottom
            // computed as: height of the document + top offset of container - top offset of nav link
            if(opts.pixelsFromNavToBottom === undefined) {
                opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top;
                this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom);
            }

            var self = this;

            // determine loading.start actions
            opts.loading.start = opts.loading.start || function() {
                $(opts.navSelector).hide();
                opts.loading.msg
                .appendTo(opts.loading.selector)
                .show(opts.loading.speed, $.proxy(function() {
                    this.beginAjax(opts);
                }, self));
            };

            // determine loading.finished actions
            opts.loading.finished = opts.loading.finished || function() {
                if (!opts.state.isBeyondMaxPage)
                    opts.loading.msg.fadeOut(opts.loading.speed);
            };

            // callback loading
            opts.callback = function(instance, data, url) {
                if (!!opts.behavior && instance['_callback_'+opts.behavior] !== undefined) {
                    instance['_callback_'+opts.behavior].call($(opts.contentSelector)[0], data, url);
                }

                if (callback) {
                    callback.call($(opts.contentSelector)[0], data, opts, url);
                }

                if (opts.prefill) {
                    $window.bind('resize.infinite-scroll', instance._prefill);
                }
            };

            if (options.debug) {
                // Tell IE9 to use its built-in console
                if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') {
                    ['log','info','warn','error','assert','dir','clear','profile','profileEnd']
                        .forEach(function (method) {
                            console[method] = this.call(console[method], console);
                        }, Function.prototype.bind);
                }
            }

            this._setup();

            // Setups the prefill method for use
            if (opts.prefill) {
                this._prefill();
            }

            // Return true to indicate successful creation
            return true;
        },

        _prefill: function infscr_prefill() {
            var instance = this;
            var $window = $(window);

            function needsPrefill() {
                return ( $(instance.options.contentSelector).height() <= $window.height() );
            }

            this._prefill = function() {
                if (needsPrefill()) {
                    instance.scroll();
                }

                $window.bind('resize.infinite-scroll', function() {
                    if (needsPrefill()) {
                        $window.unbind('resize.infinite-scroll');
                        instance.scroll();
                    }
                });
            };

            // Call self after setting up the new function
            this._prefill();
        },

        // Console log wrapper
        _debug: function infscr_debug() {
            if (true !== this.options.debug) {
                return;
            }

            if (typeof console !== 'undefined' && typeof console.log === 'function') {
                // Modern browsers
                // Single argument, which is a string
                if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') {
                    //console.log( (Array.prototype.slice.call(arguments)).toString() );
                } else {
                    //console.log( Array.prototype.slice.call(arguments) );
                }
            } else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') {
                // IE8
                Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
            }
        },

        // find the number to increment in the path.
        _determinepath: function infscr_determinepath(path) {

            var opts = this.options;

            // if behavior is defined and this function is extended, call that instead of default
            if (!!opts.behavior && this['_determinepath_'+opts.behavior] !== undefined) {
                return this['_determinepath_'+opts.behavior].call(this,path);
            }

            if (!!opts.pathParse) {

                this._debug('pathParse manual');
                return opts.pathParse(path, this.options.state.currPage+1);

            } else if (path.match(/^(.*?)\b2\b(.*?$)/)) {
                path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1);

                // if there is any 2 in the url at all.
            } else if (path.match(/^(.*?)2(.*?$)/)) {

                // page= is used in django:
                // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127
                if (path.match(/^(.*?page=)2(\/.*|$)/)) {
                    path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1);
                    return path;
                }

                path = path.match(/^(.*?)2(.*?$)/).slice(1);

            } else {

                // page= is used in drupal too but second page is page=1 not page=2:
                // thx Jerod Fritz, vladikoff
                if (path.match(/^(.*?page=)1(\/.*|$)/)) {
                    path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1);
                    return path;
                } else {
                    this._debug("Sorry, we couldn't parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com.");
                    // Get rid of isInvalidPage to allow permalink to state
                    opts.state.isInvalidPage = true;  //prevent it from running on this page.
                }
            }
            this._debug('determinePath', path);
            return path;

        },

        // Custom error
        _error: function infscr_error(xhr) {

            var opts = this.options;

            // if behavior is defined and this function is extended, call that instead of default
            if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) {
                this['_error_'+opts.behavior].call(this,xhr);
                return;
            }

            if (xhr !== 'destroy' && xhr !== 'end') {
                xhr = 'unknown';
            }

            this._debug('Error', xhr);

            if (xhr === 'end' || opts.state.isBeyondMaxPage) {
                this._showdonemsg();
            }

            opts.state.isDone = true;
            opts.state.currPage = 1; // if you need to go back to this instance
            opts.state.isPaused = false;
            opts.state.isBeyondMaxPage = false;
            this._binding('unbind');

        },

        // Load Callback
        _loadcallback: function infscr_loadcallback(box, data, url) {
            var opts = this.options,
            callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK
            result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append',
            frag;

            // if behavior is defined and this function is extended, call that instead of default
            if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) {
                this['_loadcallback_'+opts.behavior].call(this,box,data);
                return;
            }

            switch (result) {
                case 'done':
                    this._showdonemsg();
                    return false;

                case 'no-append':
                    if (opts.dataType === 'html') {
                        data = '<div>' + data + '</div>';
                        data = $(data).find(opts.itemSelector);
                    }

                    // if it didn't return anything
                    if (data.length === 0) {
                        return this._error('end');
                    }

                    break;

                case 'append':
                    var children = box.children();
                    // if it didn't return anything
                    if (children.length === 0) {
                        return this._error('end');
                    }

                    // use a documentFragment because it works when content is going into a table or UL
                    frag = document.createDocumentFragment();
                    while (box[0].firstChild) {
                        frag.appendChild(box[0].firstChild);
                    }

                    this._debug('contentSelector', $(opts.contentSelector)[0]);
                    $(opts.contentSelector)[0].appendChild(frag);
                    // previously, we would pass in the new DOM element as context for the callback
                    // however we're now using a documentfragment, which doesn't have parents or children,
                    // so the context is the contentContainer guy, and we pass in an array
                    // of the elements collected as the first argument.

                    data = children.get();
                    break;
            }

            // loadingEnd function
            opts.loading.finished.call($(opts.contentSelector)[0],opts);

            // smooth scroll to ease in the new content
            if (opts.animate) {
                var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px';
                $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; });
            }

            if (!opts.animate) {
                // once the call is done, we can allow it again.
                opts.state.isDuringAjax = false;
            }

            callback(this, data, url);

            if (opts.prefill) {
                this._prefill();
            }
        },

        _nearbottom: function infscr_nearbottom() {

            var opts = this.options,
            pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height();

            // if behavior is defined and this function is extended, call that instead of default
            if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) {
                return this['_nearbottom_'+opts.behavior].call(this);
            }

            this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom);

            // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom....
            return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom);

        },

        // Pause / temporarily disable plugin from firing
        _pausing: function infscr_pausing(pause) {

            var opts = this.options;

            // if behavior is defined and this function is extended, call that instead of default
            if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) {
                this['_pausing_'+opts.behavior].call(this,pause);
                return;
            }

            // If pause is not 'pause' or 'resume', toggle it's value
            if (pause !== 'pause' && pause !== 'resume' && pause !== null) {
                this._debug('Invalid argument. Toggling pause value instead');
            }

            pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle';

            switch (pause) {
                case 'pause':
                    opts.state.isPaused = true;
                break;

                case 'resume':
                    opts.state.isPaused = false;
                break;

                case 'toggle':
                    opts.state.isPaused = !opts.state.isPaused;
                break;
            }

            this._debug('Paused', opts.state.isPaused);
            return false;

        },

        // Behavior is determined
        // If the behavior option is undefined, it will set to default and bind to scroll
        _setup: function infscr_setup() {

            var opts = this.options;

            // if behavior is defined and this function is extended, call that instead of default
            if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) {
                this['_setup_'+opts.behavior].call(this);
                return;
            }

            this._binding('bind');

            return false;

        },

        // Show done message
        _showdonemsg: function infscr_showdonemsg() {

            var opts = this.options;

            // if behavior is defined and this function is extended, call that instead of default
            if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) {
                this['_showdonemsg_'+opts.behavior].call(this);
                return;
            }

            opts.loading.msg
            .find('img')
            .hide()
            .parent()
            .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () {
                $(this).parent().fadeOut(opts.loading.speed);
            });

            // user provided callback when done
            opts.errorCallback.call($(opts.contentSelector)[0],'done');
        },

        // grab each selector option and see if any fail
        _validate: function infscr_validate(opts) {
            for (var key in opts) {
                if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) {
                    this._debug('Your ' + key + ' found no elements.');
                    return false;
                }
            }

            return true;
        },

        /*
            ----------------------------
            Public methods
            ----------------------------
            */

        // Bind to scroll
        bind: function infscr_bind() {
            this._binding('bind');
        },

        // Destroy current instance of plugin
        destroy: function infscr_destroy() {
            this.options.state.isDestroyed = true;
            this.options.loading.finished();
            return this._error('destroy');
        },

        // Set pause value to false
        pause: function infscr_pause() {
            this._pausing('pause');
        },

        // Set pause value to false
        resume: function infscr_resume() {
            this._pausing('resume');
        },

        beginAjax: function infscr_ajax(opts) {
            var instance = this,
                path = opts.path,
                box, desturl, method, condition;

            // increment the URL bit. e.g. /page/3/
            opts.state.currPage++;

            // Manually control maximum page
            if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){
                opts.state.isBeyondMaxPage = true;
                this.destroy();
                return;
            }

            // if we're dealing with a table we can't use DIVs
            box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>');

            desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage);
            instance._debug('heading into ajax', desturl);

            method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback';
            if (opts.appendCallback && opts.dataType === 'html') {
                method += '+callback';
            }

            switch (method) {
                case 'html+callback':
                    instance._debug('Using HTML via .load() method');
                    box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) {
                        instance._loadcallback(box, responseText, desturl);
                    });

                    break;

                case 'html':
                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
                    $.ajax({
                        // params
                        url: desturl,
                        dataType: opts.dataType,
                        complete: function infscr_ajax_callback(jqXHR, textStatus) {
                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
                            if (condition) {
                                instance._loadcallback(box, jqXHR.responseText, desturl);
                            } else {
                                instance._error('end');
                            }
                        }
                    });

                    break;
                case 'json':
                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
                    $.ajax({
                        dataType: 'json',
                        type: 'GET',
                        url: desturl,
                        success: function (data, textStatus, jqXHR) {
                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
                            if (opts.appendCallback) {
                                // if appendCallback is true, you must defined template in options.
                                // note that data passed into _loadcallback is already an html (after processed in opts.template(data)).
                                if (opts.template !== undefined) {
                                    var theData = opts.template(data);
                                    box.append(theData);
                                    if (condition) {
                                        instance._loadcallback(box, theData);
                                    } else {
                                        instance._error('end');
                                    }
                                } else {
                                    instance._debug('template must be defined.');
                                    instance._error('end');
                                }
                            } else {
                                // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback.
                                if (condition) {
                                    instance._loadcallback(box, data, desturl);
                                } else {
                                    instance._error('end');
                                }
                            }
                        },
                        error: function() {
                            instance._debug('JSON ajax request failed.');
                            instance._error('end');
                        }
                    });

                    break;
            }
        },

        // Retrieve next set of content items
        retrieve: function infscr_retrieve(pageNum) {
            pageNum = pageNum || null;

            var instance = this,
            opts = instance.options;

            // if behavior is defined and this function is extended, call that instead of default
            if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) {
                this['retrieve_'+opts.behavior].call(this,pageNum);
                return;
            }

            // for manual triggers, if destroyed, get out of here
            if (opts.state.isDestroyed) {
                this._debug('Instance is destroyed');
                return false;
            }

            // we dont want to fire the ajax multiple times
            opts.state.isDuringAjax = true;

            opts.loading.start.call($(opts.contentSelector)[0],opts);
        },

        // Check to see next page is needed
        scroll: function infscr_scroll() {

            var opts = this.options,
            state = opts.state;

            // if behavior is defined and this function is extended, call that instead of default
            if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) {
                this['scroll_'+opts.behavior].call(this);
                return;
            }

            if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) {
                return;
            }

            if (!this._nearbottom()) {
                return;
            }

            this.retrieve();

        },

        // Toggle pause value
        toggle: function infscr_toggle() {
            this._pausing();
        },

        // Unbind from scroll
        unbind: function infscr_unbind() {
            this._binding('unbind');
        },

        // update options
        update: function infscr_options(key) {
            if ($.isPlainObject(key)) {
                this.options = $.extend(true,this.options,key);
            }
        }
    };


    /*
        ----------------------------
        Infinite Scroll function
        ----------------------------

        Borrowed logic from the following...

        jQuery UI
        - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js

        jCarousel
        - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js

        Masonry
        - https://github.com/desandro/masonry/blob/master/jquery.masonry.js

*/

    $.fn.infinitescroll = function infscr_init(options, callback) {


        var thisCall = typeof options;

        switch (thisCall) {

            // method
            case 'string':
                var args = Array.prototype.slice.call(arguments, 1);

                this.each(function () {
                    var instance = $.data(this, 'infinitescroll');

                    if (!instance) {
                        // not setup yet
                        // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup');
                        return false;
                    }

                    if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
                        // return $.error('No such method ' + options + ' for Infinite Scroll');
                        return false;
                    }

                    // no errors!
                    instance[options].apply(instance, args);
                });

            break;

            // creation
            case 'object':

                this.each(function () {

                var instance = $.data(this, 'infinitescroll');

                if (instance) {

                    // update options of current instance
                    instance.update(options);

                } else {

                    // initialize new instance
                    instance = new $.infinitescroll(options, callback, this);

                    // don't attach if instantiation failed
                    if (!instance.failed) {
                        $.data(this, 'infinitescroll', instance);
                    }

                }

            });

            break;

        }

        return this;
    };



    /*
     * smartscroll: debounced scroll event for jQuery *
     * https://github.com/lukeshumard/smartscroll
     * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js *
     * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. *
     */

    var event = $.event,
    scrollTimeout;

    event.special.smartscroll = {
        setup: function () {
            $(this).bind('scroll', event.special.smartscroll.handler);
        },
        teardown: function () {
            $(this).unbind('scroll', event.special.smartscroll.handler);
        },
        handler: function (event, execAsap) {
            // Save the context
            var context = this,
            args = arguments;

            // set correct event type
            event.type = 'smartscroll';

            if (scrollTimeout) { clearTimeout(scrollTimeout); }
            scrollTimeout = setTimeout(function () {
                $(context).trigger('smartscroll', args);
            }, execAsap === 'execAsap' ? 0 : 100);
        }
    };

    $.fn.smartscroll = function (fn) {
        return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']);
    };

}));


/*!

 * Packery PACKAGED v2.1.1

 * Gapless, draggable grid layouts

 *

 * Licensed GPLv3 for open source use

 * or Packery Commercial License for commercial use

 *

 * http://packery.metafizzy.co

 * Copyright 2016 Metafizzy

 */



/**

 * Bridget makes jQuery widgets

 * v2.0.0

 * MIT license

 */



/* jshint browser: true, strict: true, undef: true, unused: true */



( function( window, factory ) {

    'use strict';

    /* globals define: false, module: false, require: false */



    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {

            factory( window, jQuery );

        });

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            window,

            require('jquery')

        );

    } else {

        // browser global

        window.jQueryBridget = factory(

            window,

            window.jQuery

        );

    }



}( window, function factory( window, jQuery ) {

    'use strict';



// ----- utils ----- //



    var arraySlice = Array.prototype.slice;



// helper function for logging errors

// $.error breaks jQuery chaining

    var console = window.console;

    var logError = typeof console == 'undefined' ? function() {} :

        function( message ) {

            console.error( message );

        };



// ----- jQueryBridget ----- //



    function jQueryBridget( namespace, PluginClass, $ ) {

        $ = $ || jQuery || window.jQuery;

        if ( !$ ) {

            return;

        }



        // add option method -> $().plugin('option', {...})

        if ( !PluginClass.prototype.option ) {

            // option setter

            PluginClass.prototype.option = function( opts ) {

                // bail out if not an object

                if ( !$.isPlainObject( opts ) ){

                    return;

                }

                this.options = $.extend( true, this.options, opts );

            };

        }



        // make jQuery plugin

        $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {

            if ( typeof arg0 == 'string' ) {

                // method call $().plugin( 'methodName', { options } )

                // shift arguments by 1

                var args = arraySlice.call( arguments, 1 );

                return methodCall( this, arg0, args );

            }

            // just $().plugin({ options })

            plainCall( this, arg0 );

            return this;

        };



        // $().plugin('methodName')

        function methodCall( $elems, methodName, args ) {

            var returnValue;

            var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';



            $elems.each( function( i, elem ) {

                // get instance

                var instance = $.data( elem, namespace );

                if ( !instance ) {

                    logError( namespace + ' not initialized. Cannot call methods, i.e. ' +

                        pluginMethodStr );

                    return;

                }



                var method = instance[ methodName ];

                if ( !method || methodName.charAt(0) == '_' ) {

                    logError( pluginMethodStr + ' is not a valid method' );

                    return;

                }



                // apply method, get return value

                var value = method.apply( instance, args );

                // set return value if value is returned, use only first value

                returnValue = returnValue === undefined ? value : returnValue;

            });



            return returnValue !== undefined ? returnValue : $elems;

        }



        function plainCall( $elems, options ) {

            $elems.each( function( i, elem ) {

                var instance = $.data( elem, namespace );

                if ( instance ) {

                    // set options & init

                    instance.option( options );

                    instance._init();

                } else {

                    // initialize new instance

                    instance = new PluginClass( elem, options );

                    $.data( elem, namespace, instance );

                }

            });

        }



        updateJQuery( $ );



    }



// ----- updateJQuery ----- //



// set $.bridget for v1 backwards compatibility

    function updateJQuery( $ ) {

        if ( !$ || ( $ && $.bridget ) ) {

            return;

        }

        $.bridget = jQueryBridget;

    }



    updateJQuery( jQuery || window.jQuery );



// -----  ----- //



    return jQueryBridget;



}));



/*!

 * getSize v2.0.2

 * measure size of elements

 * MIT license

 */



/*jshint browser: true, strict: true, undef: true, unused: true */

/*global define: false, module: false, console: false */



( function( window, factory ) {

    'use strict';



    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'get-size/get-size',[],function() {

            return factory();

        });

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory();

    } else {

        // browser global

        window.getSize = factory();

    }



})( window, function factory() {

    'use strict';



// -------------------------- helpers -------------------------- //



// get a number from a string, not a percentage

    function getStyleSize( value ) {

        var num = parseFloat( value );

        // not a percent like '100%', and a number

        var isValid = value.indexOf('%') == -1 && !isNaN( num );

        return isValid && num;

    }



    function noop() {}



    var logError = typeof console == 'undefined' ? noop :

        function( message ) {

            console.error( message );

        };



// -------------------------- measurements -------------------------- //



    var measurements = [

        'paddingLeft',

        'paddingRight',

        'paddingTop',

        'paddingBottom',

        'marginLeft',

        'marginRight',

        'marginTop',

        'marginBottom',

        'borderLeftWidth',

        'borderRightWidth',

        'borderTopWidth',

        'borderBottomWidth'

    ];



    var measurementsLength = measurements.length;



    function getZeroSize() {

        var size = {

            width: 0,

            height: 0,

            innerWidth: 0,

            innerHeight: 0,

            outerWidth: 0,

            outerHeight: 0

        };

        for ( var i=0; i < measurementsLength; i++ ) {

            var measurement = measurements[i];

            size[ measurement ] = 0;

        }

        return size;

    }



// -------------------------- getStyle -------------------------- //



    /**

     * getStyle, get style of element, check for Firefox bug

     * https://bugzilla.mozilla.org/show_bug.cgi?id=548397

     */

    function getStyle( elem ) {

        var style = getComputedStyle( elem );

        if ( !style ) {

            logError( 'Style returned ' + style +

                '. Are you running this code in a hidden iframe on Firefox? ' +

                'See http://bit.ly/getsizebug1' );

        }

        return style;

    }



// -------------------------- setup -------------------------- //



    var isSetup = false;



    var isBoxSizeOuter;



    /**

     * setup

     * check isBoxSizerOuter

     * do on first getSize() rather than on page load for Firefox bug

     */

    function setup() {

        // setup once

        if ( isSetup ) {

            return;

        }

        isSetup = true;



        // -------------------------- box sizing -------------------------- //



        /**

         * WebKit measures the outer-width on style.width on border-box elems

         * IE & Firefox<29 measures the inner-width

         */

        var div = document.createElement('div');

        div.style.width = '200px';

        div.style.padding = '1px 2px 3px 4px';

        div.style.borderStyle = 'solid';

        div.style.borderWidth = '1px 2px 3px 4px';

        div.style.boxSizing = 'border-box';



        var body = document.body || document.documentElement;

        body.appendChild( div );

        var style = getStyle( div );



        getSize.isBoxSizeOuter = isBoxSizeOuter = getStyleSize( style.width ) == 200;

        body.removeChild( div );



    }



// -------------------------- getSize -------------------------- //



    function getSize( elem ) {

        setup();



        // use querySeletor if elem is string

        if ( typeof elem == 'string' ) {

            elem = document.querySelector( elem );

        }



        // do not proceed on non-objects

        if ( !elem || typeof elem != 'object' || !elem.nodeType ) {

            return;

        }



        var style = getStyle( elem );



        // if hidden, everything is 0

        if ( style.display == 'none' ) {

            return getZeroSize();

        }



        var size = {};

        size.width = elem.offsetWidth;

        size.height = elem.offsetHeight;



        var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';



        // get all measurements

        for ( var i=0; i < measurementsLength; i++ ) {

            var measurement = measurements[i];

            var value = style[ measurement ];

            var num = parseFloat( value );

            // any 'auto', 'medium' value will be 0

            size[ measurement ] = !isNaN( num ) ? num : 0;

        }



        var paddingWidth = size.paddingLeft + size.paddingRight;

        var paddingHeight = size.paddingTop + size.paddingBottom;

        var marginWidth = size.marginLeft + size.marginRight;

        var marginHeight = size.marginTop + size.marginBottom;

        var borderWidth = size.borderLeftWidth + size.borderRightWidth;

        var borderHeight = size.borderTopWidth + size.borderBottomWidth;



        var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;



        // overwrite width and height if we can get it from style

        var styleWidth = getStyleSize( style.width );

        if ( styleWidth !== false ) {

            size.width = styleWidth +

                // add padding and border unless it's already including it

                ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );

        }



        var styleHeight = getStyleSize( style.height );

        if ( styleHeight !== false ) {

            size.height = styleHeight +

                // add padding and border unless it's already including it

                ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );

        }



        size.innerWidth = size.width - ( paddingWidth + borderWidth );

        size.innerHeight = size.height - ( paddingHeight + borderHeight );



        size.outerWidth = size.width + marginWidth;

        size.outerHeight = size.height + marginHeight;



        return size;

    }



    return getSize;



});



/**

 * EvEmitter v1.0.2

 * Lil' event emitter

 * MIT License

 */



/* jshint unused: true, undef: true, strict: true */



( function( global, factory ) {

    // universal module definition

    /* jshint strict: false */ /* globals define, module */

    if ( typeof define == 'function' && define.amd ) {

        // AMD - RequireJS

        define( 'ev-emitter/ev-emitter',factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS - Browserify, Webpack

        module.exports = factory();

    } else {

        // Browser globals

        global.EvEmitter = factory();

    }



}( this, function() {







    function EvEmitter() {}



    var proto = EvEmitter.prototype;



    proto.on = function( eventName, listener ) {

        if ( !eventName || !listener ) {

            return;

        }

        // set events hash

        var events = this._events = this._events || {};

        // set listeners array

        var listeners = events[ eventName ] = events[ eventName ] || [];

        // only add once

        if ( listeners.indexOf( listener ) == -1 ) {

            listeners.push( listener );

        }



        return this;

    };



    proto.once = function( eventName, listener ) {

        if ( !eventName || !listener ) {

            return;

        }

        // add event

        this.on( eventName, listener );

        // set once flag

        // set onceEvents hash

        var onceEvents = this._onceEvents = this._onceEvents || {};

        // set onceListeners object

        var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};

        // set flag

        onceListeners[ listener ] = true;



        return this;

    };



    proto.off = function( eventName, listener ) {

        var listeners = this._events && this._events[ eventName ];

        if ( !listeners || !listeners.length ) {

            return;

        }

        var index = listeners.indexOf( listener );

        if ( index != -1 ) {

            listeners.splice( index, 1 );

        }



        return this;

    };



    proto.emitEvent = function( eventName, args ) {

        var listeners = this._events && this._events[ eventName ];

        if ( !listeners || !listeners.length ) {

            return;

        }

        var i = 0;

        var listener = listeners[i];

        args = args || [];

        // once stuff

        var onceListeners = this._onceEvents && this._onceEvents[ eventName ];



        while ( listener ) {

            var isOnce = onceListeners && onceListeners[ listener ];

            if ( isOnce ) {

                // remove listener

                // remove before trigger to prevent recursion

                this.off( eventName, listener );

                // unset once flag

                delete onceListeners[ listener ];

            }

            // trigger listener

            listener.apply( this, args );

            // get next listener

            i += isOnce ? 0 : 1;

            listener = listeners[i];

        }



        return this;

    };



    return EvEmitter;



}));



/**

 * matchesSelector v2.0.1

 * matchesSelector( element, '.selector' )

 * MIT license

 */



/*jshint browser: true, strict: true, undef: true, unused: true */



( function( window, factory ) {

    /*global define: false, module: false */

    'use strict';

    // universal module definition

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'desandro-matches-selector/matches-selector',factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory();

    } else {

        // browser global

        window.matchesSelector = factory();

    }



}( window, function factory() {

    'use strict';



    var matchesMethod = ( function() {

        var ElemProto = Element.prototype;

        // check for the standard method name first

        if ( ElemProto.matches ) {

            return 'matches';

        }

        // check un-prefixed

        if ( ElemProto.matchesSelector ) {

            return 'matchesSelector';

        }

        // check vendor prefixes

        var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];



        for ( var i=0; i < prefixes.length; i++ ) {

            var prefix = prefixes[i];

            var method = prefix + 'MatchesSelector';

            if ( ElemProto[ method ] ) {

                return method;

            }

        }

    })();



    return function matchesSelector( elem, selector ) {

        return elem[ matchesMethod ]( selector );

    };



}));



/**

 * Fizzy UI utils v2.0.1

 * MIT license

 */



/*jshint browser: true, undef: true, unused: true, strict: true */



( function( window, factory ) {

    // universal module definition

    /*jshint strict: false */ /*globals define, module, require */



    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'fizzy-ui-utils/utils',[

            'desandro-matches-selector/matches-selector'

        ], function( matchesSelector ) {

            return factory( window, matchesSelector );

        });

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            window,

            require('desandro-matches-selector')

        );

    } else {

        // browser global

        window.fizzyUIUtils = factory(

            window,

            window.matchesSelector

        );

    }



}( window, function factory( window, matchesSelector ) {







    var utils = {};



// ----- extend ----- //



// extends objects

    utils.extend = function( a, b ) {

        for ( var prop in b ) {

            a[ prop ] = b[ prop ];

        }

        return a;

    };



// ----- modulo ----- //



    utils.modulo = function( num, div ) {

        return ( ( num % div ) + div ) % div;

    };



// ----- makeArray ----- //



// turn element or nodeList into an array

    utils.makeArray = function( obj ) {

        var ary = [];

        if ( Array.isArray( obj ) ) {

            // use object if already an array

            ary = obj;

        } else if ( obj && typeof obj.length == 'number' ) {

            // convert nodeList to array

            for ( var i=0; i < obj.length; i++ ) {

                ary.push( obj[i] );

            }

        } else {

            // array of single index

            ary.push( obj );

        }

        return ary;

    };



// ----- removeFrom ----- //



    utils.removeFrom = function( ary, obj ) {

        var index = ary.indexOf( obj );

        if ( index != -1 ) {

            ary.splice( index, 1 );

        }

    };



// ----- getParent ----- //



    utils.getParent = function( elem, selector ) {

        while ( elem != document.body ) {

            elem = elem.parentNode;

            if ( matchesSelector( elem, selector ) ) {

                return elem;

            }

        }

    };



// ----- getQueryElement ----- //



// use element as selector string

    utils.getQueryElement = function( elem ) {

        if ( typeof elem == 'string' ) {

            return document.querySelector( elem );

        }

        return elem;

    };



// ----- handleEvent ----- //



// enable .ontype to trigger from .addEventListener( elem, 'type' )

    utils.handleEvent = function( event ) {

        var method = 'on' + event.type;

        if ( this[ method ] ) {

            this[ method ]( event );

        }

    };



// ----- filterFindElements ----- //



    utils.filterFindElements = function( elems, selector ) {

        // make array of elems

        elems = utils.makeArray( elems );

        var ffElems = [];



        elems.forEach( function( elem ) {

            // check that elem is an actual element

            if ( !( elem instanceof HTMLElement ) ) {

                return;

            }

            // add elem if no selector

            if ( !selector ) {

                ffElems.push( elem );

                return;

            }

            // filter & find items if we have a selector

            // filter

            if ( matchesSelector( elem, selector ) ) {

                ffElems.push( elem );

            }

            // find children

            var childElems = elem.querySelectorAll( selector );

            // concat childElems to filterFound array

            for ( var i=0; i < childElems.length; i++ ) {

                ffElems.push( childElems[i] );

            }

        });



        return ffElems;

    };



// ----- debounceMethod ----- //



    utils.debounceMethod = function( _class, methodName, threshold ) {

        // original method

        var method = _class.prototype[ methodName ];

        var timeoutName = methodName + 'Timeout';



        _class.prototype[ methodName ] = function() {

            var timeout = this[ timeoutName ];

            if ( timeout ) {

                clearTimeout( timeout );

            }

            var args = arguments;



            var _this = this;

            this[ timeoutName ] = setTimeout( function() {

                method.apply( _this, args );

                delete _this[ timeoutName ];

            }, threshold || 100 );

        };

    };



// ----- docReady ----- //



    utils.docReady = function( callback ) {

        if ( document.readyState == 'complete' ) {

            callback();

        } else {

            document.addEventListener( 'DOMContentLoaded', callback );

        }

    };



// ----- htmlInit ----- //



// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/

    utils.toDashed = function( str ) {

        return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {

            return $1 + '-' + $2;

        }).toLowerCase();

    };



    var console = window.console;

    /**

     * allow user to initialize classes via [data-namespace] or .js-namespace class

     * htmlInit( Widget, 'widgetName' )

     * options are parsed from data-namespace-options

     */

    utils.htmlInit = function( WidgetClass, namespace ) {

        utils.docReady( function() {

            var dashedNamespace = utils.toDashed( namespace );

            var dataAttr = 'data-' + dashedNamespace;

            var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );

            var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );

            var elems = utils.makeArray( dataAttrElems )

                .concat( utils.makeArray( jsDashElems ) );

            var dataOptionsAttr = dataAttr + '-options';

            var jQuery = window.jQuery;



            elems.forEach( function( elem ) {

                var attr = elem.getAttribute( dataAttr ) ||

                    elem.getAttribute( dataOptionsAttr );

                var options;

                try {

                    options = attr && JSON.parse( attr );

                } catch ( error ) {

                    // log error, do not initialize

                    if ( console ) {

                        console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +

                            ': ' + error );

                    }

                    return;

                }

                // initialize

                var instance = new WidgetClass( elem, options );

                // make available via $().data('layoutname')

                if ( jQuery ) {

                    jQuery.data( elem, namespace, instance );

                }

            });



        });

    };



// -----  ----- //



    return utils;



}));



/**

 * Outlayer Item

 */



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /* globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD - RequireJS

        define( 'outlayer/item',[

            'ev-emitter/ev-emitter',

            'get-size/get-size'

        ],

            factory

        );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS - Browserify, Webpack

        module.exports = factory(

            require('ev-emitter'),

            require('get-size')

        );

    } else {

        // browser global

        window.Outlayer = {};

        window.Outlayer.Item = factory(

            window.EvEmitter,

            window.getSize

        );

    }



}( window, function factory( EvEmitter, getSize ) {

    'use strict';



// ----- helpers ----- //



    function isEmptyObj( obj ) {

        for ( var prop in obj ) {

            return false;

        }

        prop = null;

        return true;

    }



// -------------------------- CSS3 support -------------------------- //





    var docElemStyle = document.documentElement.style;



    var transitionProperty = typeof docElemStyle.transition == 'string' ?

        'transition' : 'WebkitTransition';

    var transformProperty = typeof docElemStyle.transform == 'string' ?

        'transform' : 'WebkitTransform';



    var transitionEndEvent = {

        WebkitTransition: 'webkitTransitionEnd',

        transition: 'transitionend'

    }[ transitionProperty ];



// cache all vendor properties that could have vendor prefix

    var vendorProperties = {

        transform: transformProperty,

        transition: transitionProperty,

        transitionDuration: transitionProperty + 'Duration',

        transitionProperty: transitionProperty + 'Property',

        transitionDelay: transitionProperty + 'Delay'

    };



// -------------------------- Item -------------------------- //



    function Item( element, layout ) {

        if ( !element ) {

            return;

        }



        this.element = element;

        // parent layout class, i.e. Masonry, Isotope, or Packery

        this.layout = layout;

        this.position = {

            x: 0,

            y: 0

        };



        this._create();

    }



// inherit EvEmitter

    var proto = Item.prototype = Object.create( EvEmitter.prototype );

    proto.constructor = Item;



    proto._create = function() {

        // transition objects

        this._transn = {

            ingProperties: {},

            clean: {},

            onEnd: {}

        };



        this.css({

            position: 'absolute'

        });

    };



// trigger specified handler for event type

    proto.handleEvent = function( event ) {

        var method = 'on' + event.type;

        if ( this[ method ] ) {

            this[ method ]( event );

        }

    };



    proto.getSize = function() {

        this.size = getSize( this.element );

    };



    /**

     * apply CSS styles to element

     * @param {Object} style

     */

    proto.css = function( style ) {

        var elemStyle = this.element.style;



        for ( var prop in style ) {

            // use vendor property if available

            var supportedProp = vendorProperties[ prop ] || prop;

            elemStyle[ supportedProp ] = style[ prop ];

        }

    };



    // measure position, and sets it

    proto.getPosition = function() {

        var style = getComputedStyle( this.element );

        var isOriginLeft = this.layout._getOption('originLeft');

        var isOriginTop = this.layout._getOption('originTop');

        var xValue = style[ isOriginLeft ? 'left' : 'right' ];

        var yValue = style[ isOriginTop ? 'top' : 'bottom' ];

        // convert percent to pixels

        var layoutSize = this.layout.size;

        var x = xValue.indexOf('%') != -1 ?

            ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 );

        var y = yValue.indexOf('%') != -1 ?

            ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 );



        // clean up 'auto' or other non-integer values

        x = isNaN( x ) ? 0 : x;

        y = isNaN( y ) ? 0 : y;

        // remove padding from measurement

        x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;

        y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;



        this.position.x = x;

        this.position.y = y;

    };



// set settled position, apply padding

    proto.layoutPosition = function() {

        var layoutSize = this.layout.size;

        var style = {};

        var isOriginLeft = this.layout._getOption('originLeft');

        var isOriginTop = this.layout._getOption('originTop');



        // x

        var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';

        var xProperty = isOriginLeft ? 'left' : 'right';

        var xResetProperty = isOriginLeft ? 'right' : 'left';



        var x = this.position.x + layoutSize[ xPadding ];

        // set in percentage or pixels

        style[ xProperty ] = this.getXValue( x );

        // reset other property

        style[ xResetProperty ] = '';



        // y

        var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';

        var yProperty = isOriginTop ? 'top' : 'bottom';

        var yResetProperty = isOriginTop ? 'bottom' : 'top';



        var y = this.position.y + layoutSize[ yPadding ];

        // set in percentage or pixels

        style[ yProperty ] = this.getYValue( y );

        // reset other property

        style[ yResetProperty ] = '';



        this.css( style );

        this.emitEvent( 'layout', [ this ] );

    };



    proto.getXValue = function( x ) {

        var isHorizontal = this.layout._getOption('horizontal');

        return this.layout.options.percentPosition && !isHorizontal ?

            ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';

    };



    proto.getYValue = function( y ) {

        var isHorizontal = this.layout._getOption('horizontal');

        return this.layout.options.percentPosition && isHorizontal ?

            ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';

    };



    proto._transitionTo = function( x, y ) {

        this.getPosition();

        // get current x & y from top/left

        var curX = this.position.x;

        var curY = this.position.y;



        var compareX = parseInt( x, 10 );

        var compareY = parseInt( y, 10 );

        var didNotMove = compareX === this.position.x && compareY === this.position.y;



        // save end position

        this.setPosition( x, y );



        // if did not move and not transitioning, just go to layout

        if ( didNotMove && !this.isTransitioning ) {

            this.layoutPosition();

            return;

        }



        var transX = x - curX;

        var transY = y - curY;

        var transitionStyle = {};

        transitionStyle.transform = this.getTranslate( transX, transY );



        this.transition({

            to: transitionStyle,

            onTransitionEnd: {

                transform: this.layoutPosition

            },

            isCleaning: true

        });

    };



    proto.getTranslate = function( x, y ) {

        // flip cooridinates if origin on right or bottom

        var isOriginLeft = this.layout._getOption('originLeft');

        var isOriginTop = this.layout._getOption('originTop');

        x = isOriginLeft ? x : -x;

        y = isOriginTop ? y : -y;

        return 'translate3d(' + x + 'px, ' + y + 'px, 0)';

    };



// non transition + transform support

    proto.goTo = function( x, y ) {

        this.setPosition( x, y );

        this.layoutPosition();

    };



    proto.moveTo = proto._transitionTo;



    proto.setPosition = function( x, y ) {

        this.position.x = parseInt( x, 10 );

        this.position.y = parseInt( y, 10 );

    };



// ----- transition ----- //



    /**

     * @param {Object} style - CSS

     * @param {Function} onTransitionEnd

     */



// non transition, just trigger callback

    proto._nonTransition = function( args ) {

        this.css( args.to );

        if ( args.isCleaning ) {

            this._removeStyles( args.to );

        }

        for ( var prop in args.onTransitionEnd ) {

            args.onTransitionEnd[ prop ].call( this );

        }

    };



    /**

     * proper transition

     * @param {Object} args - arguments

     *   @param {Object} to - style to transition to

     *   @param {Object} from - style to start transition from

     *   @param {Boolean} isCleaning - removes transition styles after transition

     *   @param {Function} onTransitionEnd - callback

     */

    proto.transition = function( args ) {

        // redirect to nonTransition if no transition duration

        if ( !parseFloat( this.layout.options.transitionDuration ) ) {

            this._nonTransition( args );

            return;

        }



        var _transition = this._transn;

        // keep track of onTransitionEnd callback by css property

        for ( var prop in args.onTransitionEnd ) {

            _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];

        }

        // keep track of properties that are transitioning

        for ( prop in args.to ) {

            _transition.ingProperties[ prop ] = true;

            // keep track of properties to clean up when transition is done

            if ( args.isCleaning ) {

                _transition.clean[ prop ] = true;

            }

        }



        // set from styles

        if ( args.from ) {

            this.css( args.from );

            // force redraw. http://blog.alexmaccaw.com/css-transitions

            var h = this.element.offsetHeight;

            // hack for JSHint to hush about unused var

            h = null;

        }

        // enable transition

        this.enableTransition( args.to );

        // set styles that are transitioning

        this.css( args.to );



        this.isTransitioning = true;



    };



// dash before all cap letters, including first for

// WebkitTransform => -webkit-transform

    function toDashedAll( str ) {

        return str.replace( /([A-Z])/g, function( $1 ) {

            return '-' + $1.toLowerCase();

        });

    }



    var transitionProps = 'opacity,' + toDashedAll( transformProperty );



    proto.enableTransition = function(/* style */) {

        // HACK changing transitionProperty during a transition

        // will cause transition to jump

        if ( this.isTransitioning ) {

            return;

        }



        // make `transition: foo, bar, baz` from style object

        // HACK un-comment this when enableTransition can work

        // while a transition is happening

        // var transitionValues = [];

        // for ( var prop in style ) {

        //   // dash-ify camelCased properties like WebkitTransition

        //   prop = vendorProperties[ prop ] || prop;

        //   transitionValues.push( toDashedAll( prop ) );

        // }

        // munge number to millisecond, to match stagger

        var duration = this.layout.options.transitionDuration;

        duration = typeof duration == 'number' ? duration + 'ms' : duration;

        // enable transition styles

        this.css({

            transitionProperty: transitionProps,

            transitionDuration: duration,

            transitionDelay: this.staggerDelay || 0

        });

        // listen for transition end event

        this.element.addEventListener( transitionEndEvent, this, false );

    };



// ----- events ----- //



    proto.onwebkitTransitionEnd = function( event ) {

        this.ontransitionend( event );

    };



    proto.onotransitionend = function( event ) {

        this.ontransitionend( event );

    };



// properties that I munge to make my life easier

    var dashedVendorProperties = {

        '-webkit-transform': 'transform'

    };



    proto.ontransitionend = function( event ) {

        // disregard bubbled events from children

        if ( event.target !== this.element ) {

            return;

        }

        var _transition = this._transn;

        // get property name of transitioned property, convert to prefix-free

        var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;



        // remove property that has completed transitioning

        delete _transition.ingProperties[ propertyName ];

        // check if any properties are still transitioning

        if ( isEmptyObj( _transition.ingProperties ) ) {

            // all properties have completed transitioning

            this.disableTransition();

        }

        // clean style

        if ( propertyName in _transition.clean ) {

            // clean up style

            this.element.style[ event.propertyName ] = '';

            delete _transition.clean[ propertyName ];

        }

        // trigger onTransitionEnd callback

        if ( propertyName in _transition.onEnd ) {

            var onTransitionEnd = _transition.onEnd[ propertyName ];

            onTransitionEnd.call( this );

            delete _transition.onEnd[ propertyName ];

        }



        this.emitEvent( 'transitionEnd', [ this ] );

    };



    proto.disableTransition = function() {

        this.removeTransitionStyles();

        this.element.removeEventListener( transitionEndEvent, this, false );

        this.isTransitioning = false;

    };



    /**

     * removes style property from element

     * @param {Object} style

     **/

    proto._removeStyles = function( style ) {

        // clean up transition styles

        var cleanStyle = {};

        for ( var prop in style ) {

            cleanStyle[ prop ] = '';

        }

        this.css( cleanStyle );

    };



    var cleanTransitionStyle = {

        transitionProperty: '',

        transitionDuration: '',

        transitionDelay: ''

    };



    proto.removeTransitionStyles = function() {

        // remove transition

        this.css( cleanTransitionStyle );

    };



// ----- stagger ----- //



    proto.stagger = function( delay ) {

        delay = isNaN( delay ) ? 0 : delay;

        this.staggerDelay = delay + 'ms';

    };



// ----- show/hide/remove ----- //



// remove element from DOM

    proto.removeElem = function() {

        this.element.parentNode.removeChild( this.element );

        // remove display: none

        this.css({ display: '' });

        this.emitEvent( 'remove', [ this ] );

    };



    proto.remove = function() {

        // just remove element if no transition support or no transition

        if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {

            this.removeElem();

            return;

        }



        // start transition

        this.once( 'transitionEnd', function() {

            this.removeElem();

        });

        this.hide();

    };



    proto.reveal = function() {

        delete this.isHidden;

        // remove display: none

        this.css({ display: '' });



        var options = this.layout.options;



        var onTransitionEnd = {};

        var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');

        onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;



        this.transition({

            from: options.hiddenStyle,

            to: options.visibleStyle,

            isCleaning: true,

            onTransitionEnd: onTransitionEnd

        });

    };



    proto.onRevealTransitionEnd = function() {

        // check if still visible

        // during transition, item may have been hidden

        if ( !this.isHidden ) {

            this.emitEvent('reveal');

        }

    };



    /**

     * get style property use for hide/reveal transition end

     * @param {String} styleProperty - hiddenStyle/visibleStyle

     * @returns {String}

     */

    proto.getHideRevealTransitionEndProperty = function( styleProperty ) {

        var optionStyle = this.layout.options[ styleProperty ];

        // use opacity

        if ( optionStyle.opacity ) {

            return 'opacity';

        }

        // get first property

        for ( var prop in optionStyle ) {

            return prop;

        }

    };



    proto.hide = function() {

        // set flag

        this.isHidden = true;

        // remove display: none

        this.css({ display: '' });



        var options = this.layout.options;



        var onTransitionEnd = {};

        var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');

        onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;



        this.transition({

            from: options.visibleStyle,

            to: options.hiddenStyle,

            // keep hidden stuff hidden

            isCleaning: true,

            onTransitionEnd: onTransitionEnd

        });

    };



    proto.onHideTransitionEnd = function() {

        // check if still hidden

        // during transition, item may have been un-hidden

        if ( this.isHidden ) {

            this.css({ display: 'none' });

            this.emitEvent('hide');

        }

    };



    proto.destroy = function() {

        this.css({

            position: '',

            left: '',

            right: '',

            top: '',

            bottom: '',

            transition: '',

            transform: ''

        });

    };



    return Item;



}));



/*!

 * Outlayer v2.1.0

 * the brains and guts of a layout library

 * MIT license

 */



( function( window, factory ) {

    'use strict';

    // universal module definition

    /* jshint strict: false */ /* globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD - RequireJS

        define( 'outlayer/outlayer',[

            'ev-emitter/ev-emitter',

            'get-size/get-size',

            'fizzy-ui-utils/utils',

            './item'

        ],

            function( EvEmitter, getSize, utils, Item ) {

                return factory( window, EvEmitter, getSize, utils, Item);

            }

        );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS - Browserify, Webpack

        module.exports = factory(

            window,

            require('ev-emitter'),

            require('get-size'),

            require('fizzy-ui-utils'),

            require('./item')

        );

    } else {

        // browser global

        window.Outlayer = factory(

            window,

            window.EvEmitter,

            window.getSize,

            window.fizzyUIUtils,

            window.Outlayer.Item

        );

    }



}( window, function factory( window, EvEmitter, getSize, utils, Item ) {

    'use strict';



// ----- vars ----- //



    var console = window.console;

    var jQuery = window.jQuery;

    var noop = function() {};



// -------------------------- Outlayer -------------------------- //



// globally unique identifiers

    var GUID = 0;

// internal store of all Outlayer intances

    var instances = {};





    /**

     * @param {Element, String} element

     * @param {Object} options

     * @constructor

     */

    function Outlayer( element, options ) {

        var queryElement = utils.getQueryElement( element );

        if ( !queryElement ) {

            if ( console ) {

                console.error( 'Bad element for ' + this.constructor.namespace +

                    ': ' + ( queryElement || element ) );

            }

            return;

        }

        this.element = queryElement;

        // add jQuery

        if ( jQuery ) {

            this.$element = jQuery( this.element );

        }



        // options

        this.options = utils.extend( {}, this.constructor.defaults );

        this.option( options );



        // add id for Outlayer.getFromElement

        var id = ++GUID;

        this.element.outlayerGUID = id; // expando

        instances[ id ] = this; // associate via id



        // kick it off

        this._create();



        var isInitLayout = this._getOption('initLayout');

        if ( isInitLayout ) {

            this.layout();

        }

    }



// settings are for internal use only

    Outlayer.namespace = 'outlayer';

    Outlayer.Item = Item;



// default options

    Outlayer.defaults = {

        containerStyle: {

            position: 'relative'

        },

        initLayout: true,

        originLeft: true,

        originTop: true,

        resize: true,

        resizeContainer: true,

        // item options

        transitionDuration: '0.4s',

        hiddenStyle: {

            opacity: 0,

            transform: 'scale(0.001)'

        },

        visibleStyle: {

            opacity: 1,

            transform: 'scale(1)'

        }

    };



    var proto = Outlayer.prototype;

// inherit EvEmitter

    utils.extend( proto, EvEmitter.prototype );



    /**

     * set options

     * @param {Object} opts

     */

    proto.option = function( opts ) {

        utils.extend( this.options, opts );

    };



    /**

     * get backwards compatible option value, check old name

     */

    proto._getOption = function( option ) {

        var oldOption = this.constructor.compatOptions[ option ];

        return oldOption && this.options[ oldOption ] !== undefined ?

            this.options[ oldOption ] : this.options[ option ];

    };



    Outlayer.compatOptions = {

        // currentName: oldName

        initLayout: 'isInitLayout',

        horizontal: 'isHorizontal',

        layoutInstant: 'isLayoutInstant',

        originLeft: 'isOriginLeft',

        originTop: 'isOriginTop',

        resize: 'isResizeBound',

        resizeContainer: 'isResizingContainer'

    };



    proto._create = function() {

        // get items from children

        this.reloadItems();

        // elements that affect layout, but are not laid out

        this.stamps = [];

        this.stamp( this.options.stamp );

        // set container style

        utils.extend( this.element.style, this.options.containerStyle );



        // bind resize method

        var canBindResize = this._getOption('resize');

        if ( canBindResize ) {

            this.bindResize();

        }

    };



// goes through all children again and gets bricks in proper order

    proto.reloadItems = function() {

        // collection of item elements

        this.items = this._itemize( this.element.children );

    };





    /**

     * turn elements into Outlayer.Items to be used in layout

     * @param {Array or NodeList or HTMLElement} elems

     * @returns {Array} items - collection of new Outlayer Items

     */

    proto._itemize = function( elems ) {



        var itemElems = this._filterFindItemElements( elems );

        var Item = this.constructor.Item;



        // create new Outlayer Items for collection

        var items = [];

        for ( var i=0; i < itemElems.length; i++ ) {

            var elem = itemElems[i];

            var item = new Item( elem, this );

            items.push( item );

        }



        return items;

    };



    /**

     * get item elements to be used in layout

     * @param {Array or NodeList or HTMLElement} elems

     * @returns {Array} items - item elements

     */

    proto._filterFindItemElements = function( elems ) {

        return utils.filterFindElements( elems, this.options.itemSelector );

    };



    /**

     * getter method for getting item elements

     * @returns {Array} elems - collection of item elements

     */

    proto.getItemElements = function() {

        return this.items.map( function( item ) {

            return item.element;

        });

    };



// ----- init & layout ----- //



    /**

     * lays out all items

     */

    proto.layout = function() {

        this._resetLayout();

        this._manageStamps();



        // don't animate first layout

        var layoutInstant = this._getOption('layoutInstant');

        var isInstant = layoutInstant !== undefined ?

            layoutInstant : !this._isLayoutInited;

        this.layoutItems( this.items, isInstant );



        // flag for initalized

        this._isLayoutInited = true;

    };



// _init is alias for layout

    proto._init = proto.layout;



    /**

     * logic before any new layout

     */

    proto._resetLayout = function() {

        this.getSize();

    };





    proto.getSize = function() {

        this.size = getSize( this.element );

    };



    /**

     * get measurement from option, for columnWidth, rowHeight, gutter

     * if option is String -> get element from selector string, & get size of element

     * if option is Element -> get size of element

     * else use option as a number

     *

     * @param {String} measurement

     * @param {String} size - width or height

     * @private

     */

    proto._getMeasurement = function( measurement, size ) {

        var option = this.options[ measurement ];

        var elem;

        if ( !option ) {

            // default to 0

            this[ measurement ] = 0;

        } else {

            // use option as an element

            if ( typeof option == 'string' ) {

                elem = this.element.querySelector( option );

            } else if ( option instanceof HTMLElement ) {

                elem = option;

            }

            // use size of element, if element

            this[ measurement ] = elem ? getSize( elem )[ size ] : option;

        }

    };



    /**

     * layout a collection of item elements

     * @api public

     */

    proto.layoutItems = function( items, isInstant ) {

        items = this._getItemsForLayout( items );



        this._layoutItems( items, isInstant );



        this._postLayout();

    };



    /**

     * get the items to be laid out

     * you may want to skip over some items

     * @param {Array} items

     * @returns {Array} items

     */

    proto._getItemsForLayout = function( items ) {

        return items.filter( function( item ) {

            return !item.isIgnored;

        });

    };



    /**

     * layout items

     * @param {Array} items

     * @param {Boolean} isInstant

     */

    proto._layoutItems = function( items, isInstant ) {

        this._emitCompleteOnItems( 'layout', items );



        if ( !items || !items.length ) {

            // no items, emit event with empty array

            return;

        }



        var queue = [];



        items.forEach( function( item ) {

            // get x/y object from method

            var position = this._getItemLayoutPosition( item );

            // enqueue

            position.item = item;

            position.isInstant = isInstant || item.isLayoutInstant;

            queue.push( position );

        }, this );



        this._processLayoutQueue( queue );

    };



    /**

     * get item layout position

     * @param {Outlayer.Item} item

     * @returns {Object} x and y position

     */

    proto._getItemLayoutPosition = function( /* item */ ) {

        return {

            x: 0,

            y: 0

        };

    };



    /**

     * iterate over array and position each item

     * Reason being - separating this logic prevents 'layout invalidation'

     * thx @paul_irish

     * @param {Array} queue

     */

    proto._processLayoutQueue = function( queue ) {

        this.updateStagger();

        queue.forEach( function( obj, i ) {

            this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );

        }, this );

    };



// set stagger from option in milliseconds number

    proto.updateStagger = function() {

        var stagger = this.options.stagger;

        if ( stagger === null || stagger === undefined ) {

            this.stagger = 0;

            return;

        }

        this.stagger = getMilliseconds( stagger );

        return this.stagger;

    };



    /**

     * Sets position of item in DOM

     * @param {Outlayer.Item} item

     * @param {Number} x - horizontal position

     * @param {Number} y - vertical position

     * @param {Boolean} isInstant - disables transitions

     */

    proto._positionItem = function( item, x, y, isInstant, i ) {

        if ( isInstant ) {

            // if not transition, just set CSS

            item.goTo( x, y );

        } else {

            item.stagger( i * this.stagger );

            item.moveTo( x, y );

        }

    };



    /**

     * Any logic you want to do after each layout,

     * i.e. size the container

     */

    proto._postLayout = function() {

        this.resizeContainer();

    };



    proto.resizeContainer = function() {

        var isResizingContainer = this._getOption('resizeContainer');

        if ( !isResizingContainer ) {

            return;

        }

        var size = this._getContainerSize();

        if ( size ) {

            this._setContainerMeasure( size.width, true );

            this._setContainerMeasure( size.height, false );

        }

    };



    /**

     * Sets width or height of container if returned

     * @returns {Object} size

     *   @param {Number} width

     *   @param {Number} height

     */

    proto._getContainerSize = noop;



    /**

     * @param {Number} measure - size of width or height

     * @param {Boolean} isWidth

     */

    proto._setContainerMeasure = function( measure, isWidth ) {

        if ( measure === undefined ) {

            return;

        }



        var elemSize = this.size;

        // add padding and border width if border box

        if ( elemSize.isBorderBox ) {

            measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +

                elemSize.borderLeftWidth + elemSize.borderRightWidth :

                elemSize.paddingBottom + elemSize.paddingTop +

                    elemSize.borderTopWidth + elemSize.borderBottomWidth;

        }



        measure = Math.max( measure, 0 );

        this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';

    };



    /**

     * emit eventComplete on a collection of items events

     * @param {String} eventName

     * @param {Array} items - Outlayer.Items

     */

    proto._emitCompleteOnItems = function( eventName, items ) {

        var _this = this;

        function onComplete() {

            _this.dispatchEvent( eventName + 'Complete', null, [ items ] );

        }



        var count = items.length;

        if ( !items || !count ) {

            onComplete();

            return;

        }



        var doneCount = 0;

        function tick() {

            doneCount++;

            if ( doneCount == count ) {

                onComplete();

            }

        }



        // bind callback

        items.forEach( function( item ) {

            item.once( eventName, tick );

        });

    };



    /**

     * emits events via EvEmitter and jQuery events

     * @param {String} type - name of event

     * @param {Event} event - original event

     * @param {Array} args - extra arguments

     */

    proto.dispatchEvent = function( type, event, args ) {

        // add original event to arguments

        var emitArgs = event ? [ event ].concat( args ) : args;

        this.emitEvent( type, emitArgs );



        if ( jQuery ) {

            // set this.$element

            this.$element = this.$element || jQuery( this.element );

            if ( event ) {

                // create jQuery event

                var $event = jQuery.Event( event );

                $event.type = type;

                this.$element.trigger( $event, args );

            } else {

                // just trigger with type if no event available

                this.$element.trigger( type, args );

            }

        }

    };



// -------------------------- ignore & stamps -------------------------- //





    /**

     * keep item in collection, but do not lay it out

     * ignored items do not get skipped in layout

     * @param {Element} elem

     */

    proto.ignore = function( elem ) {

        var item = this.getItem( elem );

        if ( item ) {

            item.isIgnored = true;

        }

    };



    /**

     * return item to layout collection

     * @param {Element} elem

     */

    proto.unignore = function( elem ) {

        var item = this.getItem( elem );

        if ( item ) {

            delete item.isIgnored;

        }

    };



    /**

     * adds elements to stamps

     * @param {NodeList, Array, Element, or String} elems

     */

    proto.stamp = function( elems ) {

        elems = this._find( elems );

        if ( !elems ) {

            return;

        }



        this.stamps = this.stamps.concat( elems );

        // ignore

        elems.forEach( this.ignore, this );

    };



    /**

     * removes elements to stamps

     * @param {NodeList, Array, or Element} elems

     */

    proto.unstamp = function( elems ) {

        elems = this._find( elems );

        if ( !elems ){

            return;

        }



        elems.forEach( function( elem ) {

            // filter out removed stamp elements

            utils.removeFrom( this.stamps, elem );

            this.unignore( elem );

        }, this );

    };



    /**

     * finds child elements

     * @param {NodeList, Array, Element, or String} elems

     * @returns {Array} elems

     */

    proto._find = function( elems ) {

        if ( !elems ) {

            return;

        }

        // if string, use argument as selector string

        if ( typeof elems == 'string' ) {

            elems = this.element.querySelectorAll( elems );

        }

        elems = utils.makeArray( elems );

        return elems;

    };



    proto._manageStamps = function() {

        if ( !this.stamps || !this.stamps.length ) {

            return;

        }



        this._getBoundingRect();



        this.stamps.forEach( this._manageStamp, this );

    };



// update boundingLeft / Top

    proto._getBoundingRect = function() {

        // get bounding rect for container element

        var boundingRect = this.element.getBoundingClientRect();

        var size = this.size;

        this._boundingRect = {

            left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,

            top: boundingRect.top + size.paddingTop + size.borderTopWidth,

            right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),

            bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )

        };

    };



    /**

     * @param {Element} stamp

     **/

    proto._manageStamp = noop;



    /**

     * get x/y position of element relative to container element

     * @param {Element} elem

     * @returns {Object} offset - has left, top, right, bottom

     */

    proto._getElementOffset = function( elem ) {

        var boundingRect = elem.getBoundingClientRect();

        var thisRect = this._boundingRect;

        var size = getSize( elem );

        var offset = {

            left: boundingRect.left - thisRect.left - size.marginLeft,

            top: boundingRect.top - thisRect.top - size.marginTop,

            right: thisRect.right - boundingRect.right - size.marginRight,

            bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom

        };

        return offset;

    };



// -------------------------- resize -------------------------- //



// enable event handlers for listeners

// i.e. resize -> onresize

    proto.handleEvent = utils.handleEvent;



    /**

     * Bind layout to window resizing

     */

    proto.bindResize = function() {

        window.addEventListener( 'resize', this );

        this.isResizeBound = true;

    };



    /**

     * Unbind layout to window resizing

     */

    proto.unbindResize = function() {

        window.removeEventListener( 'resize', this );

        this.isResizeBound = false;

    };



    proto.onresize = function() {

        this.resize();

    };



    utils.debounceMethod( Outlayer, 'onresize', 100 );



    proto.resize = function() {

        // don't trigger if size did not change

        // or if resize was unbound. See #9

        if ( !this.isResizeBound || !this.needsResizeLayout() ) {

            return;

        }



        this.layout();

    };



    /**

     * check if layout is needed post layout

     * @returns Boolean

     */

    proto.needsResizeLayout = function() {

        var size = getSize( this.element );

        // check that this.size and size are there

        // IE8 triggers resize on body size change, so they might not be

        var hasSizes = this.size && size;

        return hasSizes && size.innerWidth !== this.size.innerWidth;

    };



// -------------------------- methods -------------------------- //



    /**

     * add items to Outlayer instance

     * @param {Array or NodeList or Element} elems

     * @returns {Array} items - Outlayer.Items

     **/

    proto.addItems = function( elems ) {

        var items = this._itemize( elems );

        // add items to collection

        if ( items.length ) {

            this.items = this.items.concat( items );

        }

        return items;

    };



    /**

     * Layout newly-appended item elements

     * @param {Array or NodeList or Element} elems

     */

    proto.appended = function( elems ) {

        var items = this.addItems( elems );

        if ( !items.length ) {

            return;

        }

        // layout and reveal just the new items

        this.layoutItems( items, true );

        this.reveal( items );

    };



    /**

     * Layout prepended elements

     * @param {Array or NodeList or Element} elems

     */

    proto.prepended = function( elems ) {

        var items = this._itemize( elems );

        if ( !items.length ) {

            return;

        }

        // add items to beginning of collection

        var previousItems = this.items.slice(0);

        this.items = items.concat( previousItems );

        // start new layout

        this._resetLayout();

        this._manageStamps();

        // layout new stuff without transition

        this.layoutItems( items, true );

        this.reveal( items );

        // layout previous items

        this.layoutItems( previousItems );

    };



    /**

     * reveal a collection of items

     * @param {Array of Outlayer.Items} items

     */

    proto.reveal = function( items ) {

        this._emitCompleteOnItems( 'reveal', items );

        if ( !items || !items.length ) {

            return;

        }

        var stagger = this.updateStagger();

        items.forEach( function( item, i ) {

            item.stagger( i * stagger );

            item.reveal();

        });

    };



    /**

     * hide a collection of items

     * @param {Array of Outlayer.Items} items

     */

    proto.hide = function( items ) {

        this._emitCompleteOnItems( 'hide', items );

        if ( !items || !items.length ) {

            return;

        }

        var stagger = this.updateStagger();

        items.forEach( function( item, i ) {

            item.stagger( i * stagger );

            item.hide();

        });

    };



    /**

     * reveal item elements

     * @param {Array}, {Element}, {NodeList} items

     */

    proto.revealItemElements = function( elems ) {

        var items = this.getItems( elems );

        this.reveal( items );

    };



    /**

     * hide item elements

     * @param {Array}, {Element}, {NodeList} items

     */

    proto.hideItemElements = function( elems ) {

        var items = this.getItems( elems );

        this.hide( items );

    };



    /**

     * get Outlayer.Item, given an Element

     * @param {Element} elem

     * @param {Function} callback

     * @returns {Outlayer.Item} item

     */

    proto.getItem = function( elem ) {

        // loop through items to get the one that matches

        for ( var i=0; i < this.items.length; i++ ) {

            var item = this.items[i];

            if ( item.element == elem ) {

                // return item

                return item;

            }

        }

    };



    /**

     * get collection of Outlayer.Items, given Elements

     * @param {Array} elems

     * @returns {Array} items - Outlayer.Items

     */

    proto.getItems = function( elems ) {

        elems = utils.makeArray( elems );

        var items = [];

        elems.forEach( function( elem ) {

            var item = this.getItem( elem );

            if ( item ) {

                items.push( item );

            }

        }, this );



        return items;

    };



    /**

     * remove element(s) from instance and DOM

     * @param {Array or NodeList or Element} elems

     */

    proto.remove = function( elems ) {

        var removeItems = this.getItems( elems );



        this._emitCompleteOnItems( 'remove', removeItems );



        // bail if no items to remove

        if ( !removeItems || !removeItems.length ) {

            return;

        }



        removeItems.forEach( function( item ) {

            item.remove();

            // remove item from collection

            utils.removeFrom( this.items, item );

        }, this );

    };



// ----- destroy ----- //



// remove and disable Outlayer instance

    proto.destroy = function() {

        // clean up dynamic styles

        var style = this.element.style;

        style.height = '';

        style.position = '';

        style.width = '';

        // destroy items

        this.items.forEach( function( item ) {

            item.destroy();

        });



        this.unbindResize();



        var id = this.element.outlayerGUID;

        delete instances[ id ]; // remove reference to instance by id

        delete this.element.outlayerGUID;

        // remove data for jQuery

        if ( jQuery ) {

            jQuery.removeData( this.element, this.constructor.namespace );

        }



    };



// -------------------------- data -------------------------- //



    /**

     * get Outlayer instance from element

     * @param {Element} elem

     * @returns {Outlayer}

     */

    Outlayer.data = function( elem ) {

        elem = utils.getQueryElement( elem );

        var id = elem && elem.outlayerGUID;

        return id && instances[ id ];

    };





// -------------------------- create Outlayer class -------------------------- //



    /**

     * create a layout class

     * @param {String} namespace

     */

    Outlayer.create = function( namespace, options ) {

        // sub-class Outlayer

        var Layout = subclass( Outlayer );

        // apply new options and compatOptions

        Layout.defaults = utils.extend( {}, Outlayer.defaults );

        utils.extend( Layout.defaults, options );

        Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions  );



        Layout.namespace = namespace;



        Layout.data = Outlayer.data;



        // sub-class Item

        Layout.Item = subclass( Item );



        // -------------------------- declarative -------------------------- //



        utils.htmlInit( Layout, namespace );



        // -------------------------- jQuery bridge -------------------------- //



        // make into jQuery plugin

        if ( jQuery && jQuery.bridget ) {

            jQuery.bridget( namespace, Layout );

        }



        return Layout;

    };



    function subclass( Parent ) {

        function SubClass() {

            Parent.apply( this, arguments );

        }



        SubClass.prototype = Object.create( Parent.prototype );

        SubClass.prototype.constructor = SubClass;



        return SubClass;

    }



// ----- helpers ----- //



// how many milliseconds are in each unit

    var msUnits = {

        ms: 1,

        s: 1000

    };



// munge time-like parameter into millisecond number

// '0.4s' -> 40

    function getMilliseconds( time ) {

        if ( typeof time == 'number' ) {

            return time;

        }

        var matches = time.match( /(^\d*\.?\d*)(\w*)/ );

        var num = matches && matches[1];

        var unit = matches && matches[2];

        if ( !num.length ) {

            return 0;

        }

        num = parseFloat( num );

        var mult = msUnits[ unit ] || 1;

        return num * mult;

    }



// ----- fin ----- //



// back in global

    Outlayer.Item = Item;



    return Outlayer;



}));



/**

 * Rect

 * low-level utility class for basic geometry

 */



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /* globals define, module */

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'packery/js/rect',factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory();

    } else {

        // browser global

        window.Packery = window.Packery || {};

        window.Packery.Rect = factory();

    }



}( window, function factory() {

    'use strict';



// -------------------------- Rect -------------------------- //



    function Rect( props ) {

        // extend properties from defaults

        for ( var prop in Rect.defaults ) {

            this[ prop ] = Rect.defaults[ prop ];

        }



        for ( prop in props ) {

            this[ prop ] = props[ prop ];

        }



    }



    Rect.defaults = {

        x: 0,

        y: 0,

        width: 0,

        height: 0

    };



    var proto = Rect.prototype;



    /**

     * Determines whether or not this rectangle wholly encloses another rectangle or point.

     * @param {Rect} rect

     * @returns {Boolean}

     **/

    proto.contains = function( rect ) {

        // points don't have width or height

        var otherWidth = rect.width || 0;

        var otherHeight = rect.height || 0;

        return this.x <= rect.x &&

            this.y <= rect.y &&

            this.x + this.width >= rect.x + otherWidth &&

            this.y + this.height >= rect.y + otherHeight;

    };



    /**

     * Determines whether or not the rectangle intersects with another.

     * @param {Rect} rect

     * @returns {Boolean}

     **/

    proto.overlaps = function( rect ) {

        var thisRight = this.x + this.width;

        var thisBottom = this.y + this.height;

        var rectRight = rect.x + rect.width;

        var rectBottom = rect.y + rect.height;



        // http://stackoverflow.com/a/306332

        return this.x < rectRight &&

            thisRight > rect.x &&

            this.y < rectBottom &&

            thisBottom > rect.y;

    };



    /**

     * @param {Rect} rect - the overlapping rect

     * @returns {Array} freeRects - rects representing the area around the rect

     **/

    proto.getMaximalFreeRects = function( rect ) {



        // if no intersection, return false

        if ( !this.overlaps( rect ) ) {

            return false;

        }



        var freeRects = [];

        var freeRect;



        var thisRight = this.x + this.width;

        var thisBottom = this.y + this.height;

        var rectRight = rect.x + rect.width;

        var rectBottom = rect.y + rect.height;



        // top

        if ( this.y < rect.y ) {

            freeRect = new Rect({

                x: this.x,

                y: this.y,

                width: this.width,

                height: rect.y - this.y

            });

            freeRects.push( freeRect );

        }



        // right

        if ( thisRight > rectRight ) {

            freeRect = new Rect({

                x: rectRight,

                y: this.y,

                width: thisRight - rectRight,

                height: this.height

            });

            freeRects.push( freeRect );

        }



        // bottom

        if ( thisBottom > rectBottom ) {

            freeRect = new Rect({

                x: this.x,

                y: rectBottom,

                width: this.width,

                height: thisBottom - rectBottom

            });

            freeRects.push( freeRect );

        }



        // left

        if ( this.x < rect.x ) {

            freeRect = new Rect({

                x: this.x,

                y: this.y,

                width: rect.x - this.x,

                height: this.height

            });

            freeRects.push( freeRect );

        }



        return freeRects;

    };



    proto.canFit = function( rect ) {

        return this.width >= rect.width && this.height >= rect.height;

    };



    return Rect;



}));



/**

 * Packer

 * bin-packing algorithm

 */



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /* globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'packery/js/packer',[ './rect' ], factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            require('./rect')

        );

    } else {

        // browser global

        var Packery = window.Packery = window.Packery || {};

        Packery.Packer = factory( Packery.Rect );

    }



}( window, function factory( Rect ) {

    'use strict';



// -------------------------- Packer -------------------------- //



    /**

     * @param {Number} width

     * @param {Number} height

     * @param {String} sortDirection

     *   topLeft for vertical, leftTop for horizontal

     */

    function Packer( width, height, sortDirection ) {

        this.width = width || 0;

        this.height = height || 0;

        this.sortDirection = sortDirection || 'downwardLeftToRight';



        this.reset();

    }



    var proto = Packer.prototype;



    proto.reset = function() {

        this.spaces = [];



        var initialSpace = new Rect({

            x: 0,

            y: 0,

            width: this.width,

            height: this.height

        });



        this.spaces.push( initialSpace );

        // set sorter

        this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight;

    };



// change x and y of rect to fit with in Packer's available spaces

    proto.pack = function( rect ) {

        for ( var i=0; i < this.spaces.length; i++ ) {

            var space = this.spaces[i];

            if ( space.canFit( rect ) ) {

                this.placeInSpace( rect, space );

                break;

            }

        }

    };



    proto.columnPack = function( rect ) {

        for ( var i=0; i < this.spaces.length; i++ ) {

            var space = this.spaces[i];

            var canFitInSpaceColumn = space.x <= rect.x &&

                space.x + space.width >= rect.x + rect.width &&

                space.height >= rect.height - 0.01; // fudge number for rounding error

            if ( canFitInSpaceColumn ) {

                rect.y = space.y;

                this.placed( rect );

                break;

            }

        }

    };



    proto.rowPack = function( rect ) {

        for ( var i=0; i < this.spaces.length; i++ ) {

            var space = this.spaces[i];

            var canFitInSpaceRow = space.y <= rect.y &&

                space.y + space.height >= rect.y + rect.height &&

                space.width >= rect.width - 0.01; // fudge number for rounding error

            if ( canFitInSpaceRow ) {

                rect.x = space.x;

                this.placed( rect );

                break;

            }

        }

    };



    proto.placeInSpace = function( rect, space ) {

        // place rect in space

        rect.x = space.x;

        rect.y = space.y;



        this.placed( rect );

    };



// update spaces with placed rect

    proto.placed = function( rect ) {

        // update spaces

        var revisedSpaces = [];

        for ( var i=0; i < this.spaces.length; i++ ) {

            var space = this.spaces[i];

            var newSpaces = space.getMaximalFreeRects( rect );

            // add either the original space or the new spaces to the revised spaces

            if ( newSpaces ) {

                revisedSpaces.push.apply( revisedSpaces, newSpaces );

            } else {

                revisedSpaces.push( space );

            }

        }



        this.spaces = revisedSpaces;



        this.mergeSortSpaces();

    };



    proto.mergeSortSpaces = function() {

        // remove redundant spaces

        Packer.mergeRects( this.spaces );

        this.spaces.sort( this.sorter );

    };



// add a space back

    proto.addSpace = function( rect ) {

        this.spaces.push( rect );

        this.mergeSortSpaces();

    };



// -------------------------- utility functions -------------------------- //



    /**

     * Remove redundant rectangle from array of rectangles

     * @param {Array} rects: an array of Rects

     * @returns {Array} rects: an array of Rects

     **/

    Packer.mergeRects = function( rects ) {

        var i = 0;

        var rect = rects[i];



        rectLoop:

            while ( rect ) {

                var j = 0;

                var compareRect = rects[ i + j ];



                while ( compareRect ) {

                    if  ( compareRect == rect ) {

                        j++; // next

                    } else if ( compareRect.contains( rect ) ) {

                        // remove rect

                        rects.splice( i, 1 );

                        rect = rects[i]; // set next rect

                        continue rectLoop; // bail on compareLoop

                    } else if ( rect.contains( compareRect ) ) {

                        // remove compareRect

                        rects.splice( i + j, 1 );

                    } else {

                        j++;

                    }

                    compareRect = rects[ i + j ]; // set next compareRect

                }

                i++;

                rect = rects[i];

            }



        return rects;

    };





// -------------------------- sorters -------------------------- //



// functions for sorting rects in order

    var sorters = {

        // top down, then left to right

        downwardLeftToRight: function( a, b ) {

            return a.y - b.y || a.x - b.x;

        },

        // left to right, then top down

        rightwardTopToBottom: function( a, b ) {

            return a.x - b.x || a.y - b.y;

        }

    };





// --------------------------  -------------------------- //



    return Packer;



}));



/**

 * Packery Item Element

 **/



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /* globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'packery/js/item',[

            'outlayer/outlayer',

            './rect'

        ],

            factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            require('outlayer'),

            require('./rect')

        );

    } else {

        // browser global

        window.Packery.Item = factory(

            window.Outlayer,

            window.Packery.Rect

        );

    }



}( window, function factory( Outlayer, Rect ) {

    'use strict';



// -------------------------- Item -------------------------- //



    var docElemStyle = document.documentElement.style;



    var transformProperty = typeof docElemStyle.transform == 'string' ?

        'transform' : 'WebkitTransform';



// sub-class Item

    var Item = function PackeryItem() {

        Outlayer.Item.apply( this, arguments );

    };



    var proto = Item.prototype = Object.create( Outlayer.Item.prototype );



    var __create = proto._create;

    proto._create = function() {

        // call default _create logic

        __create.call( this );

        this.rect = new Rect();

    };



    var _moveTo = proto.moveTo;

    proto.moveTo = function( x, y ) {

        // don't shift 1px while dragging

        var dx = Math.abs( this.position.x - x );

        var dy = Math.abs( this.position.y - y );



        var canHackGoTo = this.layout.dragItemCount && !this.isPlacing &&

            !this.isTransitioning && dx < 1 && dy < 1;

        if ( canHackGoTo ) {

            this.goTo( x, y );

            return;

        }

        _moveTo.apply( this, arguments );

    };



// -------------------------- placing -------------------------- //



    proto.enablePlacing = function() {

        this.removeTransitionStyles();

        // remove transform property from transition

        if ( this.isTransitioning && transformProperty ) {

            this.element.style[ transformProperty ] = 'none';

        }

        this.isTransitioning = false;

        this.getSize();

        this.layout._setRectSize( this.element, this.rect );

        this.isPlacing = true;

    };



    proto.disablePlacing = function() {

        this.isPlacing = false;

    };



// -----  ----- //



// remove element from DOM

    proto.removeElem = function() {

        this.element.parentNode.removeChild( this.element );

        // add space back to packer

        this.layout.packer.addSpace( this.rect );

        this.emitEvent( 'remove', [ this ] );

    };



// ----- dropPlaceholder ----- //



    proto.showDropPlaceholder = function() {

        var dropPlaceholder = this.dropPlaceholder;

        if ( !dropPlaceholder ) {

            // create dropPlaceholder

            dropPlaceholder = this.dropPlaceholder = document.createElement('div');

            dropPlaceholder.className = 'packery-drop-placeholder';

            dropPlaceholder.style.position = 'absolute';

        }



        dropPlaceholder.style.width = this.size.width + 'px';

        dropPlaceholder.style.height = this.size.height + 'px';

        this.positionDropPlaceholder();

        this.layout.element.appendChild( dropPlaceholder );

    };



    proto.positionDropPlaceholder = function() {

        this.dropPlaceholder.style[ transformProperty ] = 'translate(' +

            this.rect.x + 'px, ' + this.rect.y + 'px)';

    };



    proto.hideDropPlaceholder = function() {

        // only remove once, #333

        var parent = this.dropPlaceholder.parentNode;

        if ( parent ) {

            parent.removeChild( this.dropPlaceholder );

        }

    };



// -----  ----- //



    return Item;



}));



/*!

 * Packery v2.1.1

 * Gapless, draggable grid layouts

 *

 * Licensed GPLv3 for open source use

 * or Packery Commercial License for commercial use

 *

 * http://packery.metafizzy.co

 * Copyright 2016 Metafizzy

 */



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /* globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( [

            'get-size/get-size',

            'outlayer/outlayer',

            'packery/js/rect',

            'packery/js/packer',

            'packery/js/item'

        ],

            factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            require('get-size'),

            require('outlayer'),

            require('./rect'),

            require('./packer'),

            require('./item')

        );

    } else {

        // browser global

        window.Packery = factory(

            window.getSize,

            window.Outlayer,

            window.Packery.Rect,

            window.Packery.Packer,

            window.Packery.Item

        );

    }



}( window, function factory( getSize, Outlayer, Rect, Packer, Item ) {

    'use strict';



// ----- Rect ----- //



// allow for pixel rounding errors IE8-IE11 & Firefox; #227

    Rect.prototype.canFit = function( rect ) {

        return this.width >= rect.width - 1 && this.height >= rect.height - 1;

    };



// -------------------------- Packery -------------------------- //



// create an Outlayer layout class

    var Packery = Outlayer.create('packery');

    Packery.Item = Item;



    var proto = Packery.prototype;



    proto._create = function() {

        // call super

        Outlayer.prototype._create.call( this );



        // initial properties

        this.packer = new Packer();

        // packer for drop targets

        this.shiftPacker = new Packer();

        this.isEnabled = true;



        this.dragItemCount = 0;



        // create drag handlers

        var _this = this;

        this.handleDraggabilly = {

            dragStart: function() {

                _this.itemDragStart( this.element );

            },

            dragMove: function() {

                _this.itemDragMove( this.element, this.position.x, this.position.y );

            },

            dragEnd: function() {

                _this.itemDragEnd( this.element );

            }

        };



        this.handleUIDraggable = {

            start: function handleUIDraggableStart( event, ui ) {

                // HTML5 may trigger dragstart, dismiss HTML5 dragging

                if ( !ui ) {

                    return;

                }

                _this.itemDragStart( event.currentTarget );

            },

            drag: function handleUIDraggableDrag( event, ui ) {

                if ( !ui ) {

                    return;

                }

                _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top );

            },

            stop: function handleUIDraggableStop( event, ui ) {

                if ( !ui ) {

                    return;

                }

                _this.itemDragEnd( event.currentTarget );

            }

        };



    };





// ----- init & layout ----- //



    /**

     * logic before any new layout

     */

    proto._resetLayout = function() {

        this.getSize();



        this._getMeasurements();



        // reset packer

        var width, height, sortDirection;

        // packer settings, if horizontal or vertical

        if ( this._getOption('horizontal') ) {

            width = Infinity;

            height = this.size.innerHeight + this.gutter;

            sortDirection = 'rightwardTopToBottom';

        } else {

            width = this.size.innerWidth + this.gutter;

            height = Infinity;

            sortDirection = 'downwardLeftToRight';

        }



        this.packer.width = this.shiftPacker.width = width;

        this.packer.height = this.shiftPacker.height = height;

        this.packer.sortDirection = this.shiftPacker.sortDirection = sortDirection;



        this.packer.reset();



        // layout

        this.maxY = 0;

        this.maxX = 0;

    };



    /**

     * update columnWidth, rowHeight, & gutter

     * @private

     */

    proto._getMeasurements = function() {

        this._getMeasurement( 'columnWidth', 'width' );

        this._getMeasurement( 'rowHeight', 'height' );

        this._getMeasurement( 'gutter', 'width' );

    };



    proto._getItemLayoutPosition = function( item ) {

        this._setRectSize( item.element, item.rect );

        if ( this.isShifting || this.dragItemCount > 0 ) {

            var packMethod = this._getPackMethod();

            this.packer[ packMethod ]( item.rect );

        } else {

            this.packer.pack( item.rect );

        }



        this._setMaxXY( item.rect );

        return item.rect;

    };



    proto.shiftLayout = function() {

        this.isShifting = true;

        this.layout();

        delete this.isShifting;

    };



    proto._getPackMethod = function() {

        return this._getOption('horizontal') ? 'rowPack' : 'columnPack';

    };





    /**

     * set max X and Y value, for size of container

     * @param {Packery.Rect} rect

     * @private

     */

    proto._setMaxXY = function( rect ) {

        this.maxX = Math.max( rect.x + rect.width, this.maxX );

        this.maxY = Math.max( rect.y + rect.height, this.maxY );

    };



    /**

     * set the width and height of a rect, applying columnWidth and rowHeight

     * @param {Element} elem

     * @param {Packery.Rect} rect

     */

    proto._setRectSize = function( elem, rect ) {

        var size = getSize( elem );

        var w = size.outerWidth;

        var h = size.outerHeight;

        // size for columnWidth and rowHeight, if available

        // only check if size is non-zero, #177

        if ( w || h ) {

            w = this._applyGridGutter( w, this.columnWidth );

            h = this._applyGridGutter( h, this.rowHeight );

        }

        // rect must fit in packer

        rect.width = Math.min( w, this.packer.width );

        rect.height = Math.min( h, this.packer.height );

    };



    /**

     * fits item to columnWidth/rowHeight and adds gutter

     * @param {Number} measurement - item width or height

     * @param {Number} gridSize - columnWidth or rowHeight

     * @returns measurement

     */

    proto._applyGridGutter = function( measurement, gridSize ) {

        // just add gutter if no gridSize

        if ( !gridSize ) {

            return measurement + this.gutter;

        }

        gridSize += this.gutter;

        // fit item to columnWidth/rowHeight

        var remainder = measurement % gridSize;

        var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';

        measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize;

        return measurement;

    };



    proto._getContainerSize = function() {

        if ( this._getOption('horizontal') ) {

            return {

                width: this.maxX - this.gutter

            };

        } else {

            return {

                height: this.maxY - this.gutter

            };

        }

    };





// -------------------------- stamp -------------------------- //



    /**

     * makes space for element

     * @param {Element} elem

     */

    proto._manageStamp = function( elem ) {



        var item = this.getItem( elem );

        var rect;

        if ( item && item.isPlacing ) {

            rect = item.rect;

        } else {

            var offset = this._getElementOffset( elem );

            rect = new Rect({

                x: this._getOption('originLeft') ? offset.left : offset.right,

                y: this._getOption('originTop') ? offset.top : offset.bottom

            });

        }



        this._setRectSize( elem, rect );

        // save its space in the packer

        this.packer.placed( rect );

        this._setMaxXY( rect );

    };



// -------------------------- methods -------------------------- //



    function verticalSorter( a, b ) {

        return a.position.y - b.position.y || a.position.x - b.position.x;

    }



    function horizontalSorter( a, b ) {

        return a.position.x - b.position.x || a.position.y - b.position.y;

    }



    proto.sortItemsByPosition = function() {

        var sorter = this._getOption('horizontal') ? horizontalSorter : verticalSorter;

        this.items.sort( sorter );

    };



    /**

     * Fit item element in its current position

     * Packery will position elements around it

     * useful for expanding elements

     *

     * @param {Element} elem

     * @param {Number} x - horizontal destination position, optional

     * @param {Number} y - vertical destination position, optional

     */

    proto.fit = function( elem, x, y ) {

        var item = this.getItem( elem );

        if ( !item ) {

            return;

        }



        // stamp item to get it out of layout

        this.stamp( item.element );

        // set placing flag

        item.enablePlacing();

        this.updateShiftTargets( item );

        // fall back to current position for fitting

        x = x === undefined ? item.rect.x: x;

        y = y === undefined ? item.rect.y: y;

        // position it best at its destination

        this.shift( item, x, y );

        this._bindFitEvents( item );

        item.moveTo( item.rect.x, item.rect.y );

        // layout everything else

        this.shiftLayout();

        // return back to regularly scheduled programming

        this.unstamp( item.element );

        this.sortItemsByPosition();

        item.disablePlacing();

    };



    /**

     * emit event when item is fit and other items are laid out

     * @param {Packery.Item} item

     * @private

     */

    proto._bindFitEvents = function( item ) {

        var _this = this;

        var ticks = 0;

        function onLayout() {

            ticks++;

            if ( ticks != 2 ) {

                return;

            }

            _this.dispatchEvent( 'fitComplete', null, [ item ] );

        }

        // when item is laid out

        item.once( 'layout', onLayout );

        // when all items are laid out

        this.once( 'layoutComplete', onLayout );

    };



// -------------------------- resize -------------------------- //



// debounced, layout on resize

    proto.resize = function() {

        // don't trigger if size did not change

        // or if resize was unbound. See #285, outlayer#9

        if ( !this.isResizeBound || !this.needsResizeLayout() ) {

            return;

        }



        if ( this.options.shiftPercentResize ) {

            this.resizeShiftPercentLayout();

        } else {

            this.layout();

        }

    };



    /**

     * check if layout is needed post layout

     * @returns Boolean

     */

    proto.needsResizeLayout = function() {

        var size = getSize( this.element );

        var innerSize = this._getOption('horizontal') ? 'innerHeight' : 'innerWidth';

        return size[ innerSize ] != this.size[ innerSize ];

    };



    proto.resizeShiftPercentLayout = function() {

        var items = this._getItemsForLayout( this.items );



        var isHorizontal = this._getOption('horizontal');

        var coord = isHorizontal ? 'y' : 'x';

        var measure = isHorizontal ? 'height' : 'width';

        var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';

        var innerSize = isHorizontal ? 'innerHeight' : 'innerWidth';



        // proportional re-align items

        var previousSegment = this[ segmentName ];

        previousSegment = previousSegment && previousSegment + this.gutter;



        if ( previousSegment ) {

            this._getMeasurements();

            var currentSegment = this[ segmentName ] + this.gutter;

            items.forEach( function( item ) {

                var seg = Math.round( item.rect[ coord ] / previousSegment );

                item.rect[ coord ] = seg * currentSegment;

            });

        } else {

            var currentSize = getSize( this.element )[ innerSize ] + this.gutter;

            var previousSize = this.packer[ measure ];

            items.forEach( function( item ) {

                item.rect[ coord ] = ( item.rect[ coord ] / previousSize ) * currentSize;

            });

        }



        this.shiftLayout();

    };



// -------------------------- drag -------------------------- //



    /**

     * handle an item drag start event

     * @param {Element} elem

     */

    proto.itemDragStart = function( elem ) {

        if ( !this.isEnabled ) {

            return;

        }

        this.stamp( elem );

        // this.ignore( elem );

        var item = this.getItem( elem );

        if ( !item ) {

            return;

        }



        item.enablePlacing();

        item.showDropPlaceholder();

        this.dragItemCount++;

        this.updateShiftTargets( item );

    };



    proto.updateShiftTargets = function( dropItem ) {

        this.shiftPacker.reset();



        // pack stamps

        this._getBoundingRect();

        var isOriginLeft = this._getOption('originLeft');

        var isOriginTop = this._getOption('originTop');

        this.stamps.forEach( function( stamp ) {

            // ignore dragged item

            var item = this.getItem( stamp );

            if ( item && item.isPlacing ) {

                return;

            }

            var offset = this._getElementOffset( stamp );

            var rect = new Rect({

                x: isOriginLeft ? offset.left : offset.right,

                y: isOriginTop ? offset.top : offset.bottom

            });

            this._setRectSize( stamp, rect );

            // save its space in the packer

            this.shiftPacker.placed( rect );

        }, this );



        // reset shiftTargets

        var isHorizontal = this._getOption('horizontal');

        var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';

        var measure = isHorizontal ? 'height' : 'width';



        this.shiftTargetKeys = [];

        this.shiftTargets = [];

        var boundsSize;

        var segment = this[ segmentName ];

        segment = segment && segment + this.gutter;



        if ( segment ) {

            var segmentSpan = Math.ceil( dropItem.rect[ measure ] / segment );

            var segs = Math.floor( ( this.shiftPacker[ measure ] + this.gutter ) / segment );

            boundsSize = ( segs - segmentSpan ) * segment;

            // add targets on top

            for ( var i=0; i < segs; i++ ) {

                var initialX = isHorizontal ? 0 : i * segment;

                var initialY = isHorizontal ? i * segment : 0;

                this._addShiftTarget( initialX, initialY, boundsSize );

            }

        } else {

            boundsSize = ( this.shiftPacker[ measure ] + this.gutter ) - dropItem.rect[ measure ];

            this._addShiftTarget( 0, 0, boundsSize );

        }



        // pack each item to measure where shiftTargets are

        var items = this._getItemsForLayout( this.items );

        var packMethod = this._getPackMethod();

        items.forEach( function( item ) {

            var rect = item.rect;

            this._setRectSize( item.element, rect );

            this.shiftPacker[ packMethod ]( rect );



            // add top left corner

            this._addShiftTarget( rect.x, rect.y, boundsSize );

            // add bottom left / top right corner

            var cornerX = isHorizontal ? rect.x + rect.width : rect.x;

            var cornerY = isHorizontal ? rect.y : rect.y + rect.height;

            this._addShiftTarget( cornerX, cornerY, boundsSize );



            if ( segment ) {

                // add targets for each column on bottom / row on right

                var segSpan = Math.round( rect[ measure ] / segment );

                for ( var i=1; i < segSpan; i++ ) {

                    var segX = isHorizontal ? cornerX : rect.x + segment * i;

                    var segY = isHorizontal ? rect.y + segment * i : cornerY;

                    this._addShiftTarget( segX, segY, boundsSize );

                }

            }

        }, this );



    };



    proto._addShiftTarget = function( x, y, boundsSize ) {

        var checkCoord = this._getOption('horizontal') ? y : x;

        if ( checkCoord !== 0 && checkCoord > boundsSize ) {

            return;

        }

        // create string for a key, easier to keep track of what targets

        var key = x + ',' + y;

        var hasKey = this.shiftTargetKeys.indexOf( key ) != -1;

        if ( hasKey ) {

            return;

        }

        this.shiftTargetKeys.push( key );

        this.shiftTargets.push({ x: x, y: y });

    };



// -------------------------- drop -------------------------- //



    proto.shift = function( item, x, y ) {

        var shiftPosition;

        var minDistance = Infinity;

        var position = { x: x, y: y };

        this.shiftTargets.forEach( function( target ) {

            var distance = getDistance( target, position );

            if ( distance < minDistance ) {

                shiftPosition = target;

                minDistance = distance;

            }

        });

        item.rect.x = shiftPosition.x;

        item.rect.y = shiftPosition.y;

    };



    function getDistance( a, b ) {

        var dx = b.x - a.x;

        var dy = b.y - a.y;

        return Math.sqrt( dx * dx + dy * dy );

    }



// -------------------------- drag move -------------------------- //



    var DRAG_THROTTLE_TIME = 120;



    /**

     * handle an item drag move event

     * @param {Element} elem

     * @param {Number} x - horizontal change in position

     * @param {Number} y - vertical change in position

     */

    proto.itemDragMove = function( elem, x, y ) {

        var item = this.isEnabled && this.getItem( elem );

        if ( !item ) {

            return;

        }



        x -= this.size.paddingLeft;

        y -= this.size.paddingTop;



        var _this = this;

        function onDrag() {

            _this.shift( item, x, y );

            item.positionDropPlaceholder();

            _this.layout();

        }



        // throttle

        var now = new Date();

        if ( this._itemDragTime && now - this._itemDragTime < DRAG_THROTTLE_TIME ) {

            clearTimeout( this.dragTimeout );

            this.dragTimeout = setTimeout( onDrag, DRAG_THROTTLE_TIME );

        } else {

            onDrag();

            this._itemDragTime = now;

        }

    };



// -------------------------- drag end -------------------------- //



    /**

     * handle an item drag end event

     * @param {Element} elem

     */

    proto.itemDragEnd = function( elem ) {

        var item = this.isEnabled && this.getItem( elem );

        if ( !item ) {

            return;

        }



        clearTimeout( this.dragTimeout );

        item.element.classList.add('is-positioning-post-drag');



        var completeCount = 0;

        var _this = this;

        function onDragEndLayoutComplete() {

            completeCount++;

            if ( completeCount != 2 ) {

                return;

            }

            // reset drag item

            item.element.classList.remove('is-positioning-post-drag');

            item.hideDropPlaceholder();

            _this.dispatchEvent( 'dragItemPositioned', null, [ item ] );

        }



        item.once( 'layout', onDragEndLayoutComplete );

        this.once( 'layoutComplete', onDragEndLayoutComplete );

        item.moveTo( item.rect.x, item.rect.y );

        this.layout();

        this.dragItemCount = Math.max( 0, this.dragItemCount - 1 );

        this.sortItemsByPosition();

        item.disablePlacing();

        this.unstamp( item.element );

    };



    /**

     * binds Draggabilly events

     * @param {Draggabilly} draggie

     */

    proto.bindDraggabillyEvents = function( draggie ) {

        this._bindDraggabillyEvents( draggie, 'on' );

    };



    proto.unbindDraggabillyEvents = function( draggie ) {

        this._bindDraggabillyEvents( draggie, 'off' );

    };



    proto._bindDraggabillyEvents = function( draggie, method ) {

        var handlers = this.handleDraggabilly;

        draggie[ method ]( 'dragStart', handlers.dragStart );

        draggie[ method ]( 'dragMove', handlers.dragMove );

        draggie[ method ]( 'dragEnd', handlers.dragEnd );

    };



    /**

     * binds jQuery UI Draggable events

     * @param {jQuery} $elems

     */

    proto.bindUIDraggableEvents = function( $elems ) {

        this._bindUIDraggableEvents( $elems, 'on' );

    };



    proto.unbindUIDraggableEvents = function( $elems ) {

        this._bindUIDraggableEvents( $elems, 'off' );

    };



    proto._bindUIDraggableEvents = function( $elems, method ) {

        var handlers = this.handleUIDraggable;

        $elems

            [ method ]( 'dragstart', handlers.start )

            [ method ]( 'drag', handlers.drag )

            [ method ]( 'dragstop', handlers.stop );

    };



// ----- destroy ----- //



    var _destroy = proto.destroy;

    proto.destroy = function() {

        _destroy.apply( this, arguments );

        // disable flag; prevent drag events from triggering. #72

        this.isEnabled = false;

    };



// -----  ----- //



    Packery.Rect = Rect;

    Packery.Packer = Packer;



    return Packery;



}));



/*!

 * Isotope PACKAGED v3.0.1

 *

 * Licensed GPLv3 for open source use

 * or Isotope Commercial License for commercial use

 *

 * http://isotope.metafizzy.co

 * Copyright 2016 Metafizzy

 */



/**

 * Bridget makes jQuery widgets

 * v2.0.0

 * MIT license

 */



/* jshint browser: true, strict: true, undef: true, unused: true */



( function( window, factory ) {

    'use strict';

    /* globals define: false, module: false, require: false */



    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {

            factory( window, jQuery );

        });

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            window,

            require('jquery')

        );

    } else {

        // browser global

        window.jQueryBridget = factory(

            window,

            window.jQuery

        );

    }



}( window, function factory( window, jQuery ) {

    'use strict';



// ----- utils ----- //



    var arraySlice = Array.prototype.slice;



// helper function for logging errors

// $.error breaks jQuery chaining

    var console = window.console;

    var logError = typeof console == 'undefined' ? function() {} :

        function( message ) {

            console.error( message );

        };



// ----- jQueryBridget ----- //



    function jQueryBridget( namespace, PluginClass, $ ) {

        $ = $ || jQuery || window.jQuery;

        if ( !$ ) {

            return;

        }



        // add option method -> $().plugin('option', {...})

        if ( !PluginClass.prototype.option ) {

            // option setter

            PluginClass.prototype.option = function( opts ) {

                // bail out if not an object

                if ( !$.isPlainObject( opts ) ){

                    return;

                }

                this.options = $.extend( true, this.options, opts );

            };

        }



        // make jQuery plugin

        $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {

            if ( typeof arg0 == 'string' ) {

                // method call $().plugin( 'methodName', { options } )

                // shift arguments by 1

                var args = arraySlice.call( arguments, 1 );

                return methodCall( this, arg0, args );

            }

            // just $().plugin({ options })

            plainCall( this, arg0 );

            return this;

        };



        // $().plugin('methodName')

        function methodCall( $elems, methodName, args ) {

            var returnValue;

            var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';



            $elems.each( function( i, elem ) {

                // get instance

                var instance = $.data( elem, namespace );

                if ( !instance ) {

                    logError( namespace + ' not initialized. Cannot call methods, i.e. ' +

                        pluginMethodStr );

                    return;

                }



                var method = instance[ methodName ];

                if ( !method || methodName.charAt(0) == '_' ) {

                    logError( pluginMethodStr + ' is not a valid method' );

                    return;

                }



                // apply method, get return value

                var value = method.apply( instance, args );

                // set return value if value is returned, use only first value

                returnValue = returnValue === undefined ? value : returnValue;

            });



            return returnValue !== undefined ? returnValue : $elems;

        }



        function plainCall( $elems, options ) {

            $elems.each( function( i, elem ) {

                var instance = $.data( elem, namespace );

                if ( instance ) {

                    // set options & init

                    instance.option( options );

                    instance._init();

                } else {

                    // initialize new instance

                    instance = new PluginClass( elem, options );

                    $.data( elem, namespace, instance );

                }

            });

        }



        updateJQuery( $ );



    }



// ----- updateJQuery ----- //



// set $.bridget for v1 backwards compatibility

    function updateJQuery( $ ) {

        if ( !$ || ( $ && $.bridget ) ) {

            return;

        }

        $.bridget = jQueryBridget;

    }



    updateJQuery( jQuery || window.jQuery );



// -----  ----- //



    return jQueryBridget;



}));



/**

 * EvEmitter v1.0.3

 * Lil' event emitter

 * MIT License

 */



/* jshint unused: true, undef: true, strict: true */



( function( global, factory ) {

    // universal module definition

    /* jshint strict: false */ /* globals define, module, window */

    if ( typeof define == 'function' && define.amd ) {

        // AMD - RequireJS

        define( 'ev-emitter/ev-emitter',factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS - Browserify, Webpack

        module.exports = factory();

    } else {

        // Browser globals

        global.EvEmitter = factory();

    }



}( typeof window != 'undefined' ? window : this, function() {







    function EvEmitter() {}



    var proto = EvEmitter.prototype;



    proto.on = function( eventName, listener ) {

        if ( !eventName || !listener ) {

            return;

        }

        // set events hash

        var events = this._events = this._events || {};

        // set listeners array

        var listeners = events[ eventName ] = events[ eventName ] || [];

        // only add once

        if ( listeners.indexOf( listener ) == -1 ) {

            listeners.push( listener );

        }



        return this;

    };



    proto.once = function( eventName, listener ) {

        if ( !eventName || !listener ) {

            return;

        }

        // add event

        this.on( eventName, listener );

        // set once flag

        // set onceEvents hash

        var onceEvents = this._onceEvents = this._onceEvents || {};

        // set onceListeners object

        var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};

        // set flag

        onceListeners[ listener ] = true;



        return this;

    };



    proto.off = function( eventName, listener ) {

        var listeners = this._events && this._events[ eventName ];

        if ( !listeners || !listeners.length ) {

            return;

        }

        var index = listeners.indexOf( listener );

        if ( index != -1 ) {

            listeners.splice( index, 1 );

        }



        return this;

    };



    proto.emitEvent = function( eventName, args ) {

        var listeners = this._events && this._events[ eventName ];

        if ( !listeners || !listeners.length ) {

            return;

        }

        var i = 0;

        var listener = listeners[i];

        args = args || [];

        // once stuff

        var onceListeners = this._onceEvents && this._onceEvents[ eventName ];



        while ( listener ) {

            var isOnce = onceListeners && onceListeners[ listener ];

            if ( isOnce ) {

                // remove listener

                // remove before trigger to prevent recursion

                this.off( eventName, listener );

                // unset once flag

                delete onceListeners[ listener ];

            }

            // trigger listener

            listener.apply( this, args );

            // get next listener

            i += isOnce ? 0 : 1;

            listener = listeners[i];

        }



        return this;

    };



    return EvEmitter;



}));



/*!

 * getSize v2.0.2

 * measure size of elements

 * MIT license

 */



/*jshint browser: true, strict: true, undef: true, unused: true */

/*global define: false, module: false, console: false */



( function( window, factory ) {

    'use strict';



    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'get-size/get-size',[],function() {

            return factory();

        });

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory();

    } else {

        // browser global

        window.getSize = factory();

    }



})( window, function factory() {

    'use strict';



// -------------------------- helpers -------------------------- //



// get a number from a string, not a percentage

    function getStyleSize( value ) {

        var num = parseFloat( value );

        // not a percent like '100%', and a number

        var isValid = value.indexOf('%') == -1 && !isNaN( num );

        return isValid && num;

    }



    function noop() {}



    var logError = typeof console == 'undefined' ? noop :

        function( message ) {

            console.error( message );

        };



// -------------------------- measurements -------------------------- //



    var measurements = [

        'paddingLeft',

        'paddingRight',

        'paddingTop',

        'paddingBottom',

        'marginLeft',

        'marginRight',

        'marginTop',

        'marginBottom',

        'borderLeftWidth',

        'borderRightWidth',

        'borderTopWidth',

        'borderBottomWidth'

    ];



    var measurementsLength = measurements.length;



    function getZeroSize() {

        var size = {

            width: 0,

            height: 0,

            innerWidth: 0,

            innerHeight: 0,

            outerWidth: 0,

            outerHeight: 0

        };

        for ( var i=0; i < measurementsLength; i++ ) {

            var measurement = measurements[i];

            size[ measurement ] = 0;

        }

        return size;

    }



// -------------------------- getStyle -------------------------- //



    /**

     * getStyle, get style of element, check for Firefox bug

     * https://bugzilla.mozilla.org/show_bug.cgi?id=548397

     */

    function getStyle( elem ) {

        var style = getComputedStyle( elem );

        if ( !style ) {

            logError( 'Style returned ' + style +

                '. Are you running this code in a hidden iframe on Firefox? ' +

                'See http://bit.ly/getsizebug1' );

        }

        return style;

    }



// -------------------------- setup -------------------------- //



    var isSetup = false;



    var isBoxSizeOuter;



    /**

     * setup

     * check isBoxSizerOuter

     * do on first getSize() rather than on page load for Firefox bug

     */

    function setup() {

        // setup once

        if ( isSetup ) {

            return;

        }

        isSetup = true;



        // -------------------------- box sizing -------------------------- //



        /**

         * WebKit measures the outer-width on style.width on border-box elems

         * IE & Firefox<29 measures the inner-width

         */

        var div = document.createElement('div');

        div.style.width = '200px';

        div.style.padding = '1px 2px 3px 4px';

        div.style.borderStyle = 'solid';

        div.style.borderWidth = '1px 2px 3px 4px';

        div.style.boxSizing = 'border-box';



        var body = document.body || document.documentElement;

        body.appendChild( div );

        var style = getStyle( div );



        getSize.isBoxSizeOuter = isBoxSizeOuter = getStyleSize( style.width ) == 200;

        body.removeChild( div );



    }



// -------------------------- getSize -------------------------- //



    function getSize( elem ) {

        setup();



        // use querySeletor if elem is string

        if ( typeof elem == 'string' ) {

            elem = document.querySelector( elem );

        }



        // do not proceed on non-objects

        if ( !elem || typeof elem != 'object' || !elem.nodeType ) {

            return;

        }



        var style = getStyle( elem );



        // if hidden, everything is 0

        if ( style.display == 'none' ) {

            return getZeroSize();

        }



        var size = {};

        size.width = elem.offsetWidth;

        size.height = elem.offsetHeight;



        var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';



        // get all measurements

        for ( var i=0; i < measurementsLength; i++ ) {

            var measurement = measurements[i];

            var value = style[ measurement ];

            var num = parseFloat( value );

            // any 'auto', 'medium' value will be 0

            size[ measurement ] = !isNaN( num ) ? num : 0;

        }



        var paddingWidth = size.paddingLeft + size.paddingRight;

        var paddingHeight = size.paddingTop + size.paddingBottom;

        var marginWidth = size.marginLeft + size.marginRight;

        var marginHeight = size.marginTop + size.marginBottom;

        var borderWidth = size.borderLeftWidth + size.borderRightWidth;

        var borderHeight = size.borderTopWidth + size.borderBottomWidth;



        var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;



        // overwrite width and height if we can get it from style

        var styleWidth = getStyleSize( style.width );

        if ( styleWidth !== false ) {

            size.width = styleWidth +

                // add padding and border unless it's already including it

                ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );

        }



        var styleHeight = getStyleSize( style.height );

        if ( styleHeight !== false ) {

            size.height = styleHeight +

                // add padding and border unless it's already including it

                ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );

        }



        size.innerWidth = size.width - ( paddingWidth + borderWidth );

        size.innerHeight = size.height - ( paddingHeight + borderHeight );



        size.outerWidth = size.width + marginWidth;

        size.outerHeight = size.height + marginHeight;



        return size;

    }



    return getSize;



});



/**

 * matchesSelector v2.0.1

 * matchesSelector( element, '.selector' )

 * MIT license

 */



/*jshint browser: true, strict: true, undef: true, unused: true */



( function( window, factory ) {

    /*global define: false, module: false */

    'use strict';

    // universal module definition

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'desandro-matches-selector/matches-selector',factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory();

    } else {

        // browser global

        window.matchesSelector = factory();

    }



}( window, function factory() {

    'use strict';



    var matchesMethod = ( function() {

        var ElemProto = Element.prototype;

        // check for the standard method name first

        if ( ElemProto.matches ) {

            return 'matches';

        }

        // check un-prefixed

        if ( ElemProto.matchesSelector ) {

            return 'matchesSelector';

        }

        // check vendor prefixes

        var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];



        for ( var i=0; i < prefixes.length; i++ ) {

            var prefix = prefixes[i];

            var method = prefix + 'MatchesSelector';

            if ( ElemProto[ method ] ) {

                return method;

            }

        }

    })();



    return function matchesSelector( elem, selector ) {

        return elem[ matchesMethod ]( selector );

    };



}));



/**

 * Fizzy UI utils v2.0.2

 * MIT license

 */



/*jshint browser: true, undef: true, unused: true, strict: true */



( function( window, factory ) {

    // universal module definition

    /*jshint strict: false */ /*globals define, module, require */



    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'fizzy-ui-utils/utils',[

            'desandro-matches-selector/matches-selector'

        ], function( matchesSelector ) {

            return factory( window, matchesSelector );

        });

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            window,

            require('desandro-matches-selector')

        );

    } else {

        // browser global

        window.fizzyUIUtils = factory(

            window,

            window.matchesSelector

        );

    }



}( window, function factory( window, matchesSelector ) {







    var utils = {};



// ----- extend ----- //



// extends objects

    utils.extend = function( a, b ) {

        for ( var prop in b ) {

            a[ prop ] = b[ prop ];

        }

        return a;

    };



// ----- modulo ----- //



    utils.modulo = function( num, div ) {

        return ( ( num % div ) + div ) % div;

    };



// ----- makeArray ----- //



// turn element or nodeList into an array

    utils.makeArray = function( obj ) {

        var ary = [];

        if ( Array.isArray( obj ) ) {

            // use object if already an array

            ary = obj;

        } else if ( obj && typeof obj.length == 'number' ) {

            // convert nodeList to array

            for ( var i=0; i < obj.length; i++ ) {

                ary.push( obj[i] );

            }

        } else {

            // array of single index

            ary.push( obj );

        }

        return ary;

    };



// ----- removeFrom ----- //



    utils.removeFrom = function( ary, obj ) {

        var index = ary.indexOf( obj );

        if ( index != -1 ) {

            ary.splice( index, 1 );

        }

    };



// ----- getParent ----- //



    utils.getParent = function( elem, selector ) {

        while ( elem != document.body ) {

            elem = elem.parentNode;

            if ( matchesSelector( elem, selector ) ) {

                return elem;

            }

        }

    };



// ----- getQueryElement ----- //



// use element as selector string

    utils.getQueryElement = function( elem ) {

        if ( typeof elem == 'string' ) {

            return document.querySelector( elem );

        }

        return elem;

    };



// ----- handleEvent ----- //



// enable .ontype to trigger from .addEventListener( elem, 'type' )

    utils.handleEvent = function( event ) {

        var method = 'on' + event.type;

        if ( this[ method ] ) {

            this[ method ]( event );

        }

    };



// ----- filterFindElements ----- //



    utils.filterFindElements = function( elems, selector ) {

        // make array of elems

        elems = utils.makeArray( elems );

        var ffElems = [];



        elems.forEach( function( elem ) {

            // check that elem is an actual element

            if ( !( elem instanceof HTMLElement ) ) {

                return;

            }

            // add elem if no selector

            if ( !selector ) {

                ffElems.push( elem );

                return;

            }

            // filter & find items if we have a selector

            // filter

            if ( matchesSelector( elem, selector ) ) {

                ffElems.push( elem );

            }

            // find children

            var childElems = elem.querySelectorAll( selector );

            // concat childElems to filterFound array

            for ( var i=0; i < childElems.length; i++ ) {

                ffElems.push( childElems[i] );

            }

        });



        return ffElems;

    };



// ----- debounceMethod ----- //



    utils.debounceMethod = function( _class, methodName, threshold ) {

        // original method

        var method = _class.prototype[ methodName ];

        var timeoutName = methodName + 'Timeout';



        _class.prototype[ methodName ] = function() {

            var timeout = this[ timeoutName ];

            if ( timeout ) {

                clearTimeout( timeout );

            }

            var args = arguments;



            var _this = this;

            this[ timeoutName ] = setTimeout( function() {

                method.apply( _this, args );

                delete _this[ timeoutName ];

            }, threshold || 100 );

        };

    };



// ----- docReady ----- //



    utils.docReady = function( callback ) {

        var readyState = document.readyState;

        if ( readyState == 'complete' || readyState == 'interactive' ) {

            callback();

        } else {

            document.addEventListener( 'DOMContentLoaded', callback );

        }

    };



// ----- htmlInit ----- //



// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/

    utils.toDashed = function( str ) {

        return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {

            return $1 + '-' + $2;

        }).toLowerCase();

    };



    var console = window.console;

    /**

     * allow user to initialize classes via [data-namespace] or .js-namespace class

     * htmlInit( Widget, 'widgetName' )

     * options are parsed from data-namespace-options

     */

    utils.htmlInit = function( WidgetClass, namespace ) {

        utils.docReady( function() {

            var dashedNamespace = utils.toDashed( namespace );

            var dataAttr = 'data-' + dashedNamespace;

            var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );

            var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );

            var elems = utils.makeArray( dataAttrElems )

                .concat( utils.makeArray( jsDashElems ) );

            var dataOptionsAttr = dataAttr + '-options';

            var jQuery = window.jQuery;



            elems.forEach( function( elem ) {

                var attr = elem.getAttribute( dataAttr ) ||

                    elem.getAttribute( dataOptionsAttr );

                var options;

                try {

                    options = attr && JSON.parse( attr );

                } catch ( error ) {

                    // log error, do not initialize

                    if ( console ) {

                        console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +

                            ': ' + error );

                    }

                    return;

                }

                // initialize

                var instance = new WidgetClass( elem, options );

                // make available via $().data('layoutname')

                if ( jQuery ) {

                    jQuery.data( elem, namespace, instance );

                }

            });



        });

    };



// -----  ----- //



    return utils;



}));



/**

 * Outlayer Item

 */



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /* globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD - RequireJS

        define( 'outlayer/item',[

            'ev-emitter/ev-emitter',

            'get-size/get-size'

        ],

            factory

        );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS - Browserify, Webpack

        module.exports = factory(

            require('ev-emitter'),

            require('get-size')

        );

    } else {

        // browser global

        window.Outlayer = {};

        window.Outlayer.Item = factory(

            window.EvEmitter,

            window.getSize

        );

    }



}( window, function factory( EvEmitter, getSize ) {

    'use strict';



// ----- helpers ----- //



    function isEmptyObj( obj ) {

        for ( var prop in obj ) {

            return false;

        }

        prop = null;

        return true;

    }



// -------------------------- CSS3 support -------------------------- //





    var docElemStyle = document.documentElement.style;



    var transitionProperty = typeof docElemStyle.transition == 'string' ?

        'transition' : 'WebkitTransition';

    var transformProperty = typeof docElemStyle.transform == 'string' ?

        'transform' : 'WebkitTransform';



    var transitionEndEvent = {

        WebkitTransition: 'webkitTransitionEnd',

        transition: 'transitionend'

    }[ transitionProperty ];



// cache all vendor properties that could have vendor prefix

    var vendorProperties = {

        transform: transformProperty,

        transition: transitionProperty,

        transitionDuration: transitionProperty + 'Duration',

        transitionProperty: transitionProperty + 'Property',

        transitionDelay: transitionProperty + 'Delay'

    };



// -------------------------- Item -------------------------- //



    function Item( element, layout ) {

        if ( !element ) {

            return;

        }



        this.element = element;

        // parent layout class, i.e. Masonry, Isotope, or Packery

        this.layout = layout;

        this.position = {

            x: 0,

            y: 0

        };



        this._create();

    }



// inherit EvEmitter

    var proto = Item.prototype = Object.create( EvEmitter.prototype );

    proto.constructor = Item;



    proto._create = function() {

        // transition objects

        this._transn = {

            ingProperties: {},

            clean: {},

            onEnd: {}

        };



        this.css({

            position: 'absolute'

        });

    };



// trigger specified handler for event type

    proto.handleEvent = function( event ) {

        var method = 'on' + event.type;

        if ( this[ method ] ) {

            this[ method ]( event );

        }

    };



    proto.getSize = function() {

        this.size = getSize( this.element );

    };



    /**

     * apply CSS styles to element

     * @param {Object} style

     */

    proto.css = function( style ) {

        var elemStyle = this.element.style;



        for ( var prop in style ) {

            // use vendor property if available

            var supportedProp = vendorProperties[ prop ] || prop;

            elemStyle[ supportedProp ] = style[ prop ];

        }

    };



    // measure position, and sets it

    proto.getPosition = function() {

        var style = getComputedStyle( this.element );

        var isOriginLeft = this.layout._getOption('originLeft');

        var isOriginTop = this.layout._getOption('originTop');

        var xValue = style[ isOriginLeft ? 'left' : 'right' ];

        var yValue = style[ isOriginTop ? 'top' : 'bottom' ];

        // convert percent to pixels

        var layoutSize = this.layout.size;

        var x = xValue.indexOf('%') != -1 ?

            ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 );

        var y = yValue.indexOf('%') != -1 ?

            ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 );



        // clean up 'auto' or other non-integer values

        x = isNaN( x ) ? 0 : x;

        y = isNaN( y ) ? 0 : y;

        // remove padding from measurement

        x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;

        y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;



        this.position.x = x;

        this.position.y = y;

    };



// set settled position, apply padding

    proto.layoutPosition = function() {

        var layoutSize = this.layout.size;

        var style = {};

        var isOriginLeft = this.layout._getOption('originLeft');

        var isOriginTop = this.layout._getOption('originTop');



        // x

        var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';

        var xProperty = isOriginLeft ? 'left' : 'right';

        var xResetProperty = isOriginLeft ? 'right' : 'left';



        var x = this.position.x + layoutSize[ xPadding ];

        // set in percentage or pixels

        style[ xProperty ] = this.getXValue( x );

        // reset other property

        style[ xResetProperty ] = '';



        // y

        var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';

        var yProperty = isOriginTop ? 'top' : 'bottom';

        var yResetProperty = isOriginTop ? 'bottom' : 'top';



        var y = this.position.y + layoutSize[ yPadding ];

        // set in percentage or pixels

        style[ yProperty ] = this.getYValue( y );

        // reset other property

        style[ yResetProperty ] = '';



        this.css( style );

        this.emitEvent( 'layout', [ this ] );

    };



    proto.getXValue = function( x ) {

        var isHorizontal = this.layout._getOption('horizontal');

        return this.layout.options.percentPosition && !isHorizontal ?

            ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';

    };



    proto.getYValue = function( y ) {

        var isHorizontal = this.layout._getOption('horizontal');

        return this.layout.options.percentPosition && isHorizontal ?

            ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';

    };



    proto._transitionTo = function( x, y ) {

        this.getPosition();

        // get current x & y from top/left

        var curX = this.position.x;

        var curY = this.position.y;



        var compareX = parseInt( x, 10 );

        var compareY = parseInt( y, 10 );

        var didNotMove = compareX === this.position.x && compareY === this.position.y;



        // save end position

        this.setPosition( x, y );



        // if did not move and not transitioning, just go to layout

        if ( didNotMove && !this.isTransitioning ) {

            this.layoutPosition();

            return;

        }



        var transX = x - curX;

        var transY = y - curY;

        var transitionStyle = {};

        transitionStyle.transform = this.getTranslate( transX, transY );



        this.transition({

            to: transitionStyle,

            onTransitionEnd: {

                transform: this.layoutPosition

            },

            isCleaning: true

        });

    };



    proto.getTranslate = function( x, y ) {

        // flip cooridinates if origin on right or bottom

        var isOriginLeft = this.layout._getOption('originLeft');

        var isOriginTop = this.layout._getOption('originTop');

        x = isOriginLeft ? x : -x;

        y = isOriginTop ? y : -y;

        return 'translate3d(' + x + 'px, ' + y + 'px, 0)';

    };



// non transition + transform support

    proto.goTo = function( x, y ) {

        this.setPosition( x, y );

        this.layoutPosition();

    };



    proto.moveTo = proto._transitionTo;



    proto.setPosition = function( x, y ) {

        this.position.x = parseInt( x, 10 );

        this.position.y = parseInt( y, 10 );

    };



// ----- transition ----- //



    /**

     * @param {Object} style - CSS

     * @param {Function} onTransitionEnd

     */



// non transition, just trigger callback

    proto._nonTransition = function( args ) {

        this.css( args.to );

        if ( args.isCleaning ) {

            this._removeStyles( args.to );

        }

        for ( var prop in args.onTransitionEnd ) {

            args.onTransitionEnd[ prop ].call( this );

        }

    };



    /**

     * proper transition

     * @param {Object} args - arguments

     *   @param {Object} to - style to transition to

     *   @param {Object} from - style to start transition from

     *   @param {Boolean} isCleaning - removes transition styles after transition

     *   @param {Function} onTransitionEnd - callback

     */

    proto.transition = function( args ) {

        // redirect to nonTransition if no transition duration

        if ( !parseFloat( this.layout.options.transitionDuration ) ) {

            this._nonTransition( args );

            return;

        }



        var _transition = this._transn;

        // keep track of onTransitionEnd callback by css property

        for ( var prop in args.onTransitionEnd ) {

            _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];

        }

        // keep track of properties that are transitioning

        for ( prop in args.to ) {

            _transition.ingProperties[ prop ] = true;

            // keep track of properties to clean up when transition is done

            if ( args.isCleaning ) {

                _transition.clean[ prop ] = true;

            }

        }



        // set from styles

        if ( args.from ) {

            this.css( args.from );

            // force redraw. http://blog.alexmaccaw.com/css-transitions

            var h = this.element.offsetHeight;

            // hack for JSHint to hush about unused var

            h = null;

        }

        // enable transition

        this.enableTransition( args.to );

        // set styles that are transitioning

        this.css( args.to );



        this.isTransitioning = true;



    };



// dash before all cap letters, including first for

// WebkitTransform => -webkit-transform

    function toDashedAll( str ) {

        return str.replace( /([A-Z])/g, function( $1 ) {

            return '-' + $1.toLowerCase();

        });

    }



    var transitionProps = 'opacity,' + toDashedAll( transformProperty );



    proto.enableTransition = function(/* style */) {

        // HACK changing transitionProperty during a transition

        // will cause transition to jump

        if ( this.isTransitioning ) {

            return;

        }



        // make `transition: foo, bar, baz` from style object

        // HACK un-comment this when enableTransition can work

        // while a transition is happening

        // var transitionValues = [];

        // for ( var prop in style ) {

        //   // dash-ify camelCased properties like WebkitTransition

        //   prop = vendorProperties[ prop ] || prop;

        //   transitionValues.push( toDashedAll( prop ) );

        // }

        // munge number to millisecond, to match stagger

        var duration = this.layout.options.transitionDuration;

        duration = typeof duration == 'number' ? duration + 'ms' : duration;

        // enable transition styles

        this.css({

            transitionProperty: transitionProps,

            transitionDuration: duration,

            transitionDelay: this.staggerDelay || 0

        });

        // listen for transition end event

        this.element.addEventListener( transitionEndEvent, this, false );

    };



// ----- events ----- //



    proto.onwebkitTransitionEnd = function( event ) {

        this.ontransitionend( event );

    };



    proto.onotransitionend = function( event ) {

        this.ontransitionend( event );

    };



// properties that I munge to make my life easier

    var dashedVendorProperties = {

        '-webkit-transform': 'transform'

    };



    proto.ontransitionend = function( event ) {

        // disregard bubbled events from children

        if ( event.target !== this.element ) {

            return;

        }

        var _transition = this._transn;

        // get property name of transitioned property, convert to prefix-free

        var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;



        // remove property that has completed transitioning

        delete _transition.ingProperties[ propertyName ];

        // check if any properties are still transitioning

        if ( isEmptyObj( _transition.ingProperties ) ) {

            // all properties have completed transitioning

            this.disableTransition();

        }

        // clean style

        if ( propertyName in _transition.clean ) {

            // clean up style

            this.element.style[ event.propertyName ] = '';

            delete _transition.clean[ propertyName ];

        }

        // trigger onTransitionEnd callback

        if ( propertyName in _transition.onEnd ) {

            var onTransitionEnd = _transition.onEnd[ propertyName ];

            onTransitionEnd.call( this );

            delete _transition.onEnd[ propertyName ];

        }



        this.emitEvent( 'transitionEnd', [ this ] );

    };



    proto.disableTransition = function() {

        this.removeTransitionStyles();

        this.element.removeEventListener( transitionEndEvent, this, false );

        this.isTransitioning = false;

    };



    /**

     * removes style property from element

     * @param {Object} style

     **/

    proto._removeStyles = function( style ) {

        // clean up transition styles

        var cleanStyle = {};

        for ( var prop in style ) {

            cleanStyle[ prop ] = '';

        }

        this.css( cleanStyle );

    };



    var cleanTransitionStyle = {

        transitionProperty: '',

        transitionDuration: '',

        transitionDelay: ''

    };



    proto.removeTransitionStyles = function() {

        // remove transition

        this.css( cleanTransitionStyle );

    };



// ----- stagger ----- //



    proto.stagger = function( delay ) {

        delay = isNaN( delay ) ? 0 : delay;

        this.staggerDelay = delay + 'ms';

    };



// ----- show/hide/remove ----- //



// remove element from DOM

    proto.removeElem = function() {

        this.element.parentNode.removeChild( this.element );

        // remove display: none

        this.css({ display: '' });

        this.emitEvent( 'remove', [ this ] );

    };



    proto.remove = function() {

        // just remove element if no transition support or no transition

        if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {

            this.removeElem();

            return;

        }



        // start transition

        this.once( 'transitionEnd', function() {

            this.removeElem();

        });

        this.hide();

    };



    proto.reveal = function() {

        delete this.isHidden;

        // remove display: none

        this.css({ display: '' });



        var options = this.layout.options;



        var onTransitionEnd = {};

        var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');

        onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;



        this.transition({

            from: options.hiddenStyle,

            to: options.visibleStyle,

            isCleaning: true,

            onTransitionEnd: onTransitionEnd

        });

    };



    proto.onRevealTransitionEnd = function() {

        // check if still visible

        // during transition, item may have been hidden

        if ( !this.isHidden ) {

            this.emitEvent('reveal');

        }

    };



    /**

     * get style property use for hide/reveal transition end

     * @param {String} styleProperty - hiddenStyle/visibleStyle

     * @returns {String}

     */

    proto.getHideRevealTransitionEndProperty = function( styleProperty ) {

        var optionStyle = this.layout.options[ styleProperty ];

        // use opacity

        if ( optionStyle.opacity ) {

            return 'opacity';

        }

        // get first property

        for ( var prop in optionStyle ) {

            return prop;

        }

    };



    proto.hide = function() {

        // set flag

        this.isHidden = true;

        // remove display: none

        this.css({ display: '' });



        var options = this.layout.options;



        var onTransitionEnd = {};

        var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');

        onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;



        this.transition({

            from: options.visibleStyle,

            to: options.hiddenStyle,

            // keep hidden stuff hidden

            isCleaning: true,

            onTransitionEnd: onTransitionEnd

        });

    };



    proto.onHideTransitionEnd = function() {

        // check if still hidden

        // during transition, item may have been un-hidden

        if ( this.isHidden ) {

            this.css({ display: 'none' });

            this.emitEvent('hide');

        }

    };



    proto.destroy = function() {

        this.css({

            position: '',

            left: '',

            right: '',

            top: '',

            bottom: '',

            transition: '',

            transform: ''

        });

    };



    return Item;



}));



/*!

 * Outlayer v2.1.0

 * the brains and guts of a layout library

 * MIT license

 */



( function( window, factory ) {

    'use strict';

    // universal module definition

    /* jshint strict: false */ /* globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD - RequireJS

        define( 'outlayer/outlayer',[

            'ev-emitter/ev-emitter',

            'get-size/get-size',

            'fizzy-ui-utils/utils',

            './item'

        ],

            function( EvEmitter, getSize, utils, Item ) {

                return factory( window, EvEmitter, getSize, utils, Item);

            }

        );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS - Browserify, Webpack

        module.exports = factory(

            window,

            require('ev-emitter'),

            require('get-size'),

            require('fizzy-ui-utils'),

            require('./item')

        );

    } else {

        // browser global

        window.Outlayer = factory(

            window,

            window.EvEmitter,

            window.getSize,

            window.fizzyUIUtils,

            window.Outlayer.Item

        );

    }



}( window, function factory( window, EvEmitter, getSize, utils, Item ) {

    'use strict';



// ----- vars ----- //



    var console = window.console;

    var jQuery = window.jQuery;

    var noop = function() {};



// -------------------------- Outlayer -------------------------- //



// globally unique identifiers

    var GUID = 0;

// internal store of all Outlayer intances

    var instances = {};





    /**

     * @param {Element, String} element

     * @param {Object} options

     * @constructor

     */

    function Outlayer( element, options ) {

        var queryElement = utils.getQueryElement( element );

        if ( !queryElement ) {

            if ( console ) {

                console.error( 'Bad element for ' + this.constructor.namespace +

                    ': ' + ( queryElement || element ) );

            }

            return;

        }

        this.element = queryElement;

        // add jQuery

        if ( jQuery ) {

            this.$element = jQuery( this.element );

        }



        // options

        this.options = utils.extend( {}, this.constructor.defaults );

        this.option( options );



        // add id for Outlayer.getFromElement

        var id = ++GUID;

        this.element.outlayerGUID = id; // expando

        instances[ id ] = this; // associate via id



        // kick it off

        this._create();



        var isInitLayout = this._getOption('initLayout');

        if ( isInitLayout ) {

            this.layout();

        }

    }



// settings are for internal use only

    Outlayer.namespace = 'outlayer';

    Outlayer.Item = Item;



// default options

    Outlayer.defaults = {

        containerStyle: {

            position: 'relative'

        },

        initLayout: true,

        originLeft: true,

        originTop: true,

        resize: true,

        resizeContainer: true,

        // item options

        transitionDuration: '0.4s',

        hiddenStyle: {

            opacity: 0,

            transform: 'scale(0.001)'

        },

        visibleStyle: {

            opacity: 1,

            transform: 'scale(1)'

        }

    };



    var proto = Outlayer.prototype;

// inherit EvEmitter

    utils.extend( proto, EvEmitter.prototype );



    /**

     * set options

     * @param {Object} opts

     */

    proto.option = function( opts ) {

        utils.extend( this.options, opts );

    };



    /**

     * get backwards compatible option value, check old name

     */

    proto._getOption = function( option ) {

        var oldOption = this.constructor.compatOptions[ option ];

        return oldOption && this.options[ oldOption ] !== undefined ?

            this.options[ oldOption ] : this.options[ option ];

    };



    Outlayer.compatOptions = {

        // currentName: oldName

        initLayout: 'isInitLayout',

        horizontal: 'isHorizontal',

        layoutInstant: 'isLayoutInstant',

        originLeft: 'isOriginLeft',

        originTop: 'isOriginTop',

        resize: 'isResizeBound',

        resizeContainer: 'isResizingContainer'

    };



    proto._create = function() {

        // get items from children

        this.reloadItems();

        // elements that affect layout, but are not laid out

        this.stamps = [];

        this.stamp( this.options.stamp );

        // set container style

        utils.extend( this.element.style, this.options.containerStyle );



        // bind resize method

        var canBindResize = this._getOption('resize');

        if ( canBindResize ) {

            this.bindResize();

        }

    };



// goes through all children again and gets bricks in proper order

    proto.reloadItems = function() {

        // collection of item elements

        this.items = this._itemize( this.element.children );

    };





    /**

     * turn elements into Outlayer.Items to be used in layout

     * @param {Array or NodeList or HTMLElement} elems

     * @returns {Array} items - collection of new Outlayer Items

     */

    proto._itemize = function( elems ) {



        var itemElems = this._filterFindItemElements( elems );

        var Item = this.constructor.Item;



        // create new Outlayer Items for collection

        var items = [];

        for ( var i=0; i < itemElems.length; i++ ) {

            var elem = itemElems[i];

            var item = new Item( elem, this );

            items.push( item );

        }



        return items;

    };



    /**

     * get item elements to be used in layout

     * @param {Array or NodeList or HTMLElement} elems

     * @returns {Array} items - item elements

     */

    proto._filterFindItemElements = function( elems ) {

        return utils.filterFindElements( elems, this.options.itemSelector );

    };



    /**

     * getter method for getting item elements

     * @returns {Array} elems - collection of item elements

     */

    proto.getItemElements = function() {

        return this.items.map( function( item ) {

            return item.element;

        });

    };



// ----- init & layout ----- //



    /**

     * lays out all items

     */

    proto.layout = function() {

        this._resetLayout();

        this._manageStamps();



        // don't animate first layout

        var layoutInstant = this._getOption('layoutInstant');

        var isInstant = layoutInstant !== undefined ?

            layoutInstant : !this._isLayoutInited;

        this.layoutItems( this.items, isInstant );



        // flag for initalized

        this._isLayoutInited = true;

    };



// _init is alias for layout

    proto._init = proto.layout;



    /**

     * logic before any new layout

     */

    proto._resetLayout = function() {

        this.getSize();

    };





    proto.getSize = function() {

        this.size = getSize( this.element );

    };



    /**

     * get measurement from option, for columnWidth, rowHeight, gutter

     * if option is String -> get element from selector string, & get size of element

     * if option is Element -> get size of element

     * else use option as a number

     *

     * @param {String} measurement

     * @param {String} size - width or height

     * @private

     */

    proto._getMeasurement = function( measurement, size ) {

        var option = this.options[ measurement ];

        var elem;

        if ( !option ) {

            // default to 0

            this[ measurement ] = 0;

        } else {

            // use option as an element

            if ( typeof option == 'string' ) {

                elem = this.element.querySelector( option );

            } else if ( option instanceof HTMLElement ) {

                elem = option;

            }

            // use size of element, if element

            this[ measurement ] = elem ? getSize( elem )[ size ] : option;

        }

    };



    /**

     * layout a collection of item elements

     * @api public

     */

    proto.layoutItems = function( items, isInstant ) {

        items = this._getItemsForLayout( items );



        this._layoutItems( items, isInstant );



        this._postLayout();

    };



    /**

     * get the items to be laid out

     * you may want to skip over some items

     * @param {Array} items

     * @returns {Array} items

     */

    proto._getItemsForLayout = function( items ) {

        return items.filter( function( item ) {

            return !item.isIgnored;

        });

    };



    /**

     * layout items

     * @param {Array} items

     * @param {Boolean} isInstant

     */

    proto._layoutItems = function( items, isInstant ) {

        this._emitCompleteOnItems( 'layout', items );



        if ( !items || !items.length ) {

            // no items, emit event with empty array

            return;

        }



        var queue = [];



        items.forEach( function( item ) {

            // get x/y object from method

            var position = this._getItemLayoutPosition( item );

            // enqueue

            position.item = item;

            position.isInstant = isInstant || item.isLayoutInstant;

            queue.push( position );

        }, this );



        this._processLayoutQueue( queue );

    };



    /**

     * get item layout position

     * @param {Outlayer.Item} item

     * @returns {Object} x and y position

     */

    proto._getItemLayoutPosition = function( /* item */ ) {

        return {

            x: 0,

            y: 0

        };

    };



    /**

     * iterate over array and position each item

     * Reason being - separating this logic prevents 'layout invalidation'

     * thx @paul_irish

     * @param {Array} queue

     */

    proto._processLayoutQueue = function( queue ) {

        this.updateStagger();

        queue.forEach( function( obj, i ) {

            this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );

        }, this );

    };



// set stagger from option in milliseconds number

    proto.updateStagger = function() {

        var stagger = this.options.stagger;

        if ( stagger === null || stagger === undefined ) {

            this.stagger = 0;

            return;

        }

        this.stagger = getMilliseconds( stagger );

        return this.stagger;

    };



    /**

     * Sets position of item in DOM

     * @param {Outlayer.Item} item

     * @param {Number} x - horizontal position

     * @param {Number} y - vertical position

     * @param {Boolean} isInstant - disables transitions

     */

    proto._positionItem = function( item, x, y, isInstant, i ) {

        if ( isInstant ) {

            // if not transition, just set CSS

            item.goTo( x, y );

        } else {

            item.stagger( i * this.stagger );

            item.moveTo( x, y );

        }

    };



    /**

     * Any logic you want to do after each layout,

     * i.e. size the container

     */

    proto._postLayout = function() {

        this.resizeContainer();

    };



    proto.resizeContainer = function() {

        var isResizingContainer = this._getOption('resizeContainer');

        if ( !isResizingContainer ) {

            return;

        }

        var size = this._getContainerSize();

        if ( size ) {

            this._setContainerMeasure( size.width, true );

            this._setContainerMeasure( size.height, false );

        }

    };



    /**

     * Sets width or height of container if returned

     * @returns {Object} size

     *   @param {Number} width

     *   @param {Number} height

     */

    proto._getContainerSize = noop;



    /**

     * @param {Number} measure - size of width or height

     * @param {Boolean} isWidth

     */

    proto._setContainerMeasure = function( measure, isWidth ) {

        if ( measure === undefined ) {

            return;

        }



        var elemSize = this.size;

        // add padding and border width if border box

        if ( elemSize.isBorderBox ) {

            measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +

                elemSize.borderLeftWidth + elemSize.borderRightWidth :

                elemSize.paddingBottom + elemSize.paddingTop +

                    elemSize.borderTopWidth + elemSize.borderBottomWidth;

        }



        measure = Math.max( measure, 0 );

        this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';

    };



    /**

     * emit eventComplete on a collection of items events

     * @param {String} eventName

     * @param {Array} items - Outlayer.Items

     */

    proto._emitCompleteOnItems = function( eventName, items ) {

        var _this = this;

        function onComplete() {

            _this.dispatchEvent( eventName + 'Complete', null, [ items ] );

        }



        var count = items.length;

        if ( !items || !count ) {

            onComplete();

            return;

        }



        var doneCount = 0;

        function tick() {

            doneCount++;

            if ( doneCount == count ) {

                onComplete();

            }

        }



        // bind callback

        items.forEach( function( item ) {

            item.once( eventName, tick );

        });

    };



    /**

     * emits events via EvEmitter and jQuery events

     * @param {String} type - name of event

     * @param {Event} event - original event

     * @param {Array} args - extra arguments

     */

    proto.dispatchEvent = function( type, event, args ) {

        // add original event to arguments

        var emitArgs = event ? [ event ].concat( args ) : args;

        this.emitEvent( type, emitArgs );



        if ( jQuery ) {

            // set this.$element

            this.$element = this.$element || jQuery( this.element );

            if ( event ) {

                // create jQuery event

                var $event = jQuery.Event( event );

                $event.type = type;

                this.$element.trigger( $event, args );

            } else {

                // just trigger with type if no event available

                this.$element.trigger( type, args );

            }

        }

    };



// -------------------------- ignore & stamps -------------------------- //





    /**

     * keep item in collection, but do not lay it out

     * ignored items do not get skipped in layout

     * @param {Element} elem

     */

    proto.ignore = function( elem ) {

        var item = this.getItem( elem );

        if ( item ) {

            item.isIgnored = true;

        }

    };



    /**

     * return item to layout collection

     * @param {Element} elem

     */

    proto.unignore = function( elem ) {

        var item = this.getItem( elem );

        if ( item ) {

            delete item.isIgnored;

        }

    };



    /**

     * adds elements to stamps

     * @param {NodeList, Array, Element, or String} elems

     */

    proto.stamp = function( elems ) {

        elems = this._find( elems );

        if ( !elems ) {

            return;

        }



        this.stamps = this.stamps.concat( elems );

        // ignore

        elems.forEach( this.ignore, this );

    };



    /**

     * removes elements to stamps

     * @param {NodeList, Array, or Element} elems

     */

    proto.unstamp = function( elems ) {

        elems = this._find( elems );

        if ( !elems ){

            return;

        }



        elems.forEach( function( elem ) {

            // filter out removed stamp elements

            utils.removeFrom( this.stamps, elem );

            this.unignore( elem );

        }, this );

    };



    /**

     * finds child elements

     * @param {NodeList, Array, Element, or String} elems

     * @returns {Array} elems

     */

    proto._find = function( elems ) {

        if ( !elems ) {

            return;

        }

        // if string, use argument as selector string

        if ( typeof elems == 'string' ) {

            elems = this.element.querySelectorAll( elems );

        }

        elems = utils.makeArray( elems );

        return elems;

    };



    proto._manageStamps = function() {

        if ( !this.stamps || !this.stamps.length ) {

            return;

        }



        this._getBoundingRect();



        this.stamps.forEach( this._manageStamp, this );

    };



// update boundingLeft / Top

    proto._getBoundingRect = function() {

        // get bounding rect for container element

        var boundingRect = this.element.getBoundingClientRect();

        var size = this.size;

        this._boundingRect = {

            left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,

            top: boundingRect.top + size.paddingTop + size.borderTopWidth,

            right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),

            bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )

        };

    };



    /**

     * @param {Element} stamp

     **/

    proto._manageStamp = noop;



    /**

     * get x/y position of element relative to container element

     * @param {Element} elem

     * @returns {Object} offset - has left, top, right, bottom

     */

    proto._getElementOffset = function( elem ) {

        var boundingRect = elem.getBoundingClientRect();

        var thisRect = this._boundingRect;

        var size = getSize( elem );

        var offset = {

            left: boundingRect.left - thisRect.left - size.marginLeft,

            top: boundingRect.top - thisRect.top - size.marginTop,

            right: thisRect.right - boundingRect.right - size.marginRight,

            bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom

        };

        return offset;

    };



// -------------------------- resize -------------------------- //



// enable event handlers for listeners

// i.e. resize -> onresize

    proto.handleEvent = utils.handleEvent;



    /**

     * Bind layout to window resizing

     */

    proto.bindResize = function() {

        window.addEventListener( 'resize', this );

        this.isResizeBound = true;

    };



    /**

     * Unbind layout to window resizing

     */

    proto.unbindResize = function() {

        window.removeEventListener( 'resize', this );

        this.isResizeBound = false;

    };



    proto.onresize = function() {

        this.resize();

    };



    utils.debounceMethod( Outlayer, 'onresize', 100 );



    proto.resize = function() {

        // don't trigger if size did not change

        // or if resize was unbound. See #9

        if ( !this.isResizeBound || !this.needsResizeLayout() ) {

            return;

        }



        this.layout();

    };



    /**

     * check if layout is needed post layout

     * @returns Boolean

     */

    proto.needsResizeLayout = function() {

        var size = getSize( this.element );

        // check that this.size and size are there

        // IE8 triggers resize on body size change, so they might not be

        var hasSizes = this.size && size;

        return hasSizes && size.innerWidth !== this.size.innerWidth;

    };



// -------------------------- methods -------------------------- //



    /**

     * add items to Outlayer instance

     * @param {Array or NodeList or Element} elems

     * @returns {Array} items - Outlayer.Items

     **/

    proto.addItems = function( elems ) {

        var items = this._itemize( elems );

        // add items to collection

        if ( items.length ) {

            this.items = this.items.concat( items );

        }

        return items;

    };



    /**

     * Layout newly-appended item elements

     * @param {Array or NodeList or Element} elems

     */

    proto.appended = function( elems ) {

        var items = this.addItems( elems );

        if ( !items.length ) {

            return;

        }

        // layout and reveal just the new items

        this.layoutItems( items, true );

        this.reveal( items );

    };



    /**

     * Layout prepended elements

     * @param {Array or NodeList or Element} elems

     */

    proto.prepended = function( elems ) {

        var items = this._itemize( elems );

        if ( !items.length ) {

            return;

        }

        // add items to beginning of collection

        var previousItems = this.items.slice(0);

        this.items = items.concat( previousItems );

        // start new layout

        this._resetLayout();

        this._manageStamps();

        // layout new stuff without transition

        this.layoutItems( items, true );

        this.reveal( items );

        // layout previous items

        this.layoutItems( previousItems );

    };



    /**

     * reveal a collection of items

     * @param {Array of Outlayer.Items} items

     */

    proto.reveal = function( items ) {

        this._emitCompleteOnItems( 'reveal', items );

        if ( !items || !items.length ) {

            return;

        }

        var stagger = this.updateStagger();

        items.forEach( function( item, i ) {

            item.stagger( i * stagger );

            item.reveal();

        });

    };



    /**

     * hide a collection of items

     * @param {Array of Outlayer.Items} items

     */

    proto.hide = function( items ) {

        this._emitCompleteOnItems( 'hide', items );

        if ( !items || !items.length ) {

            return;

        }

        var stagger = this.updateStagger();

        items.forEach( function( item, i ) {

            item.stagger( i * stagger );

            item.hide();

        });

    };



    /**

     * reveal item elements

     * @param {Array}, {Element}, {NodeList} items

     */

    proto.revealItemElements = function( elems ) {

        var items = this.getItems( elems );

        this.reveal( items );

    };



    /**

     * hide item elements

     * @param {Array}, {Element}, {NodeList} items

     */

    proto.hideItemElements = function( elems ) {

        var items = this.getItems( elems );

        this.hide( items );

    };



    /**

     * get Outlayer.Item, given an Element

     * @param {Element} elem

     * @param {Function} callback

     * @returns {Outlayer.Item} item

     */

    proto.getItem = function( elem ) {

        // loop through items to get the one that matches

        for ( var i=0; i < this.items.length; i++ ) {

            var item = this.items[i];

            if ( item.element == elem ) {

                // return item

                return item;

            }

        }

    };



    /**

     * get collection of Outlayer.Items, given Elements

     * @param {Array} elems

     * @returns {Array} items - Outlayer.Items

     */

    proto.getItems = function( elems ) {

        elems = utils.makeArray( elems );

        var items = [];

        elems.forEach( function( elem ) {

            var item = this.getItem( elem );

            if ( item ) {

                items.push( item );

            }

        }, this );



        return items;

    };



    /**

     * remove element(s) from instance and DOM

     * @param {Array or NodeList or Element} elems

     */

    proto.remove = function( elems ) {

        var removeItems = this.getItems( elems );



        this._emitCompleteOnItems( 'remove', removeItems );



        // bail if no items to remove

        if ( !removeItems || !removeItems.length ) {

            return;

        }



        removeItems.forEach( function( item ) {

            item.remove();

            // remove item from collection

            utils.removeFrom( this.items, item );

        }, this );

    };



// ----- destroy ----- //



// remove and disable Outlayer instance

    proto.destroy = function() {

        // clean up dynamic styles

        var style = this.element.style;

        style.height = '';

        style.position = '';

        style.width = '';

        // destroy items

        this.items.forEach( function( item ) {

            item.destroy();

        });



        this.unbindResize();



        var id = this.element.outlayerGUID;

        delete instances[ id ]; // remove reference to instance by id

        delete this.element.outlayerGUID;

        // remove data for jQuery

        if ( jQuery ) {

            jQuery.removeData( this.element, this.constructor.namespace );

        }



    };



// -------------------------- data -------------------------- //



    /**

     * get Outlayer instance from element

     * @param {Element} elem

     * @returns {Outlayer}

     */

    Outlayer.data = function( elem ) {

        elem = utils.getQueryElement( elem );

        var id = elem && elem.outlayerGUID;

        return id && instances[ id ];

    };





// -------------------------- create Outlayer class -------------------------- //



    /**

     * create a layout class

     * @param {String} namespace

     */

    Outlayer.create = function( namespace, options ) {

        // sub-class Outlayer

        var Layout = subclass( Outlayer );

        // apply new options and compatOptions

        Layout.defaults = utils.extend( {}, Outlayer.defaults );

        utils.extend( Layout.defaults, options );

        Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions  );



        Layout.namespace = namespace;



        Layout.data = Outlayer.data;



        // sub-class Item

        Layout.Item = subclass( Item );



        // -------------------------- declarative -------------------------- //



        utils.htmlInit( Layout, namespace );



        // -------------------------- jQuery bridge -------------------------- //



        // make into jQuery plugin

        if ( jQuery && jQuery.bridget ) {

            jQuery.bridget( namespace, Layout );

        }



        return Layout;

    };



    function subclass( Parent ) {

        function SubClass() {

            Parent.apply( this, arguments );

        }



        SubClass.prototype = Object.create( Parent.prototype );

        SubClass.prototype.constructor = SubClass;



        return SubClass;

    }



// ----- helpers ----- //



// how many milliseconds are in each unit

    var msUnits = {

        ms: 1,

        s: 1000

    };



// munge time-like parameter into millisecond number

// '0.4s' -> 40

    function getMilliseconds( time ) {

        if ( typeof time == 'number' ) {

            return time;

        }

        var matches = time.match( /(^\d*\.?\d*)(\w*)/ );

        var num = matches && matches[1];

        var unit = matches && matches[2];

        if ( !num.length ) {

            return 0;

        }

        num = parseFloat( num );

        var mult = msUnits[ unit ] || 1;

        return num * mult;

    }



// ----- fin ----- //



// back in global

    Outlayer.Item = Item;



    return Outlayer;



}));



/**

 * Isotope Item

 **/



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /*globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'isotope/js/item',[

            'outlayer/outlayer'

        ],

            factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            require('outlayer')

        );

    } else {

        // browser global

        window.Isotope = window.Isotope || {};

        window.Isotope.Item = factory(

            window.Outlayer

        );

    }



}( window, function factory( Outlayer ) {

    'use strict';



// -------------------------- Item -------------------------- //



// sub-class Outlayer Item

    function Item() {

        Outlayer.Item.apply( this, arguments );

    }



    var proto = Item.prototype = Object.create( Outlayer.Item.prototype );



    var _create = proto._create;

    proto._create = function() {

        // assign id, used for original-order sorting

        this.id = this.layout.itemGUID++;

        _create.call( this );

        this.sortData = {};

    };



    proto.updateSortData = function() {

        if ( this.isIgnored ) {

            return;

        }

        // default sorters

        this.sortData.id = this.id;

        // for backward compatibility

        this.sortData['original-order'] = this.id;

        this.sortData.random = Math.random();

        // go thru getSortData obj and apply the sorters

        var getSortData = this.layout.options.getSortData;

        var sorters = this.layout._sorters;

        for ( var key in getSortData ) {

            var sorter = sorters[ key ];

            this.sortData[ key ] = sorter( this.element, this );

        }

    };



    var _destroy = proto.destroy;

    proto.destroy = function() {

        // call super

        _destroy.apply( this, arguments );

        // reset display, #741

        this.css({

            display: ''

        });

    };



    return Item;



}));



/**

 * Isotope LayoutMode

 */



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /*globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'isotope/js/layout-mode',[

            'get-size/get-size',

            'outlayer/outlayer'

        ],

            factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            require('get-size'),

            require('outlayer')

        );

    } else {

        // browser global

        window.Isotope = window.Isotope || {};

        window.Isotope.LayoutMode = factory(

            window.getSize,

            window.Outlayer

        );

    }



}( window, function factory( getSize, Outlayer ) {

    'use strict';



    // layout mode class

    function LayoutMode( isotope ) {

        this.isotope = isotope;

        // link properties

        if ( isotope ) {

            this.options = isotope.options[ this.namespace ];

            this.element = isotope.element;

            this.items = isotope.filteredItems;

            this.size = isotope.size;

        }

    }



    var proto = LayoutMode.prototype;



    /**

     * some methods should just defer to default Outlayer method

     * and reference the Isotope instance as `this`

     **/

    var facadeMethods = [

        '_resetLayout',

        '_getItemLayoutPosition',

        '_manageStamp',

        '_getContainerSize',

        '_getElementOffset',

        'needsResizeLayout',

        '_getOption'

    ];



    facadeMethods.forEach( function( methodName ) {

        proto[ methodName ] = function() {

            return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );

        };

    });



    // -----  ----- //



    // for horizontal layout modes, check vertical size

    proto.needsVerticalResizeLayout = function() {

        // don't trigger if size did not change

        var size = getSize( this.isotope.element );

        // check that this.size and size are there

        // IE8 triggers resize on body size change, so they might not be

        var hasSizes = this.isotope.size && size;

        return hasSizes && size.innerHeight != this.isotope.size.innerHeight;

    };



    // ----- measurements ----- //



    proto._getMeasurement = function() {

        this.isotope._getMeasurement.apply( this, arguments );

    };



    proto.getColumnWidth = function() {

        this.getSegmentSize( 'column', 'Width' );

    };



    proto.getRowHeight = function() {

        this.getSegmentSize( 'row', 'Height' );

    };



    /**

     * get columnWidth or rowHeight

     * segment: 'column' or 'row'

     * size 'Width' or 'Height'

     **/

    proto.getSegmentSize = function( segment, size ) {

        var segmentName = segment + size;

        var outerSize = 'outer' + size;

        // columnWidth / outerWidth // rowHeight / outerHeight

        this._getMeasurement( segmentName, outerSize );

        // got rowHeight or columnWidth, we can chill

        if ( this[ segmentName ] ) {

            return;

        }

        // fall back to item of first element

        var firstItemSize = this.getFirstItemSize();

        this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||

            // or size of container

            this.isotope.size[ 'inner' + size ];

    };



    proto.getFirstItemSize = function() {

        var firstItem = this.isotope.filteredItems[0];

        return firstItem && firstItem.element && getSize( firstItem.element );

    };



    // ----- methods that should reference isotope ----- //



    proto.layout = function() {

        this.isotope.layout.apply( this.isotope, arguments );

    };



    proto.getSize = function() {

        this.isotope.getSize();

        this.size = this.isotope.size;

    };



    // -------------------------- create -------------------------- //



    LayoutMode.modes = {};



    LayoutMode.create = function( namespace, options ) {



        function Mode() {

            LayoutMode.apply( this, arguments );

        }



        Mode.prototype = Object.create( proto );

        Mode.prototype.constructor = Mode;



        // default options

        if ( options ) {

            Mode.options = options;

        }



        Mode.prototype.namespace = namespace;

        // register in Isotope

        LayoutMode.modes[ namespace ] = Mode;



        return Mode;

    };



    return LayoutMode;



}));



/*!

 * Masonry v4.1.0

 * Cascading grid layout library

 * http://masonry.desandro.com

 * MIT License

 * by David DeSandro

 */



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /*globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'masonry/masonry',[

            'outlayer/outlayer',

            'get-size/get-size'

        ],

            factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            require('outlayer'),

            require('get-size')

        );

    } else {

        // browser global

        window.Masonry = factory(

            window.Outlayer,

            window.getSize

        );

    }



}( window, function factory( Outlayer, getSize ) {







// -------------------------- masonryDefinition -------------------------- //



    // create an Outlayer layout class

    var Masonry = Outlayer.create('masonry');

    // isFitWidth -> fitWidth

    Masonry.compatOptions.fitWidth = 'isFitWidth';



    Masonry.prototype._resetLayout = function() {

        this.getSize();

        this._getMeasurement( 'columnWidth', 'outerWidth' );

        this._getMeasurement( 'gutter', 'outerWidth' );

        this.measureColumns();



        // reset column Y

        this.colYs = [];

        for ( var i=0; i < this.cols; i++ ) {

            this.colYs.push( 0 );

        }



        this.maxY = 0;

    };



    Masonry.prototype.measureColumns = function() {

        this.getContainerWidth();

        // if columnWidth is 0, default to outerWidth of first item

        if ( !this.columnWidth ) {

            var firstItem = this.items[0];

            var firstItemElem = firstItem && firstItem.element;

            // columnWidth fall back to item of first element

            this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||

                // if first elem has no width, default to size of container

                this.containerWidth;

        }



        var columnWidth = this.columnWidth += this.gutter;



        // calculate columns

        var containerWidth = this.containerWidth + this.gutter;

        var cols = containerWidth / columnWidth;

        // fix rounding errors, typically with gutters

        var excess = columnWidth - containerWidth % columnWidth;

        // if overshoot is less than a pixel, round up, otherwise floor it

        var mathMethod = excess && excess < 1 ? 'round' : 'floor';

        cols = Math[ mathMethod ]( cols );

        this.cols = Math.max( cols, 1 );

    };



    Masonry.prototype.getContainerWidth = function() {

        // container is parent if fit width

        var isFitWidth = this._getOption('fitWidth');

        var container = isFitWidth ? this.element.parentNode : this.element;

        // check that this.size and size are there

        // IE8 triggers resize on body size change, so they might not be

        var size = getSize( container );

        this.containerWidth = size && size.innerWidth;

    };



    Masonry.prototype._getItemLayoutPosition = function( item ) {

        item.getSize();

        // how many columns does this brick span

        var remainder = item.size.outerWidth % this.columnWidth;

        var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';

        // round if off by 1 pixel, otherwise use ceil

        var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );

        colSpan = Math.min( colSpan, this.cols );



        var colGroup = this._getColGroup( colSpan );

        // get the minimum Y value from the columns

        var minimumY = Math.min.apply( Math, colGroup );

        var shortColIndex = colGroup.indexOf( minimumY );



        // position the brick

        var position = {

            x: this.columnWidth * shortColIndex,

            y: minimumY

        };



        // apply setHeight to necessary columns

        var setHeight = minimumY + item.size.outerHeight;

        var setSpan = this.cols + 1 - colGroup.length;

        for ( var i = 0; i < setSpan; i++ ) {

            this.colYs[ shortColIndex + i ] = setHeight;

        }



        return position;

    };



    /**

     * @param {Number} colSpan - number of columns the element spans

     * @returns {Array} colGroup

     */

    Masonry.prototype._getColGroup = function( colSpan ) {

        if ( colSpan < 2 ) {

            // if brick spans only one column, use all the column Ys

            return this.colYs;

        }



        var colGroup = [];

        // how many different places could this brick fit horizontally

        var groupCount = this.cols + 1 - colSpan;

        // for each group potential horizontal position

        for ( var i = 0; i < groupCount; i++ ) {

            // make an array of colY values for that one group

            var groupColYs = this.colYs.slice( i, i + colSpan );

            // and get the max value of the array

            colGroup[i] = Math.max.apply( Math, groupColYs );

        }

        return colGroup;

    };



    Masonry.prototype._manageStamp = function( stamp ) {

        var stampSize = getSize( stamp );

        var offset = this._getElementOffset( stamp );

        // get the columns that this stamp affects

        var isOriginLeft = this._getOption('originLeft');

        var firstX = isOriginLeft ? offset.left : offset.right;

        var lastX = firstX + stampSize.outerWidth;

        var firstCol = Math.floor( firstX / this.columnWidth );

        firstCol = Math.max( 0, firstCol );

        var lastCol = Math.floor( lastX / this.columnWidth );

        // lastCol should not go over if multiple of columnWidth #425

        lastCol -= lastX % this.columnWidth ? 0 : 1;

        lastCol = Math.min( this.cols - 1, lastCol );

        // set colYs to bottom of the stamp



        var isOriginTop = this._getOption('originTop');

        var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +

            stampSize.outerHeight;

        for ( var i = firstCol; i <= lastCol; i++ ) {

            this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );

        }

    };



    Masonry.prototype._getContainerSize = function() {

        this.maxY = Math.max.apply( Math, this.colYs );

        var size = {

            height: this.maxY

        };



        if ( this._getOption('fitWidth') ) {

            size.width = this._getContainerFitWidth();

        }



        return size;

    };



    Masonry.prototype._getContainerFitWidth = function() {

        var unusedCols = 0;

        // count unused columns

        var i = this.cols;

        while ( --i ) {

            if ( this.colYs[i] !== 0 ) {

                break;

            }

            unusedCols++;

        }

        // fit container to columns that have been used

        return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;

    };



    Masonry.prototype.needsResizeLayout = function() {

        var previousWidth = this.containerWidth;

        this.getContainerWidth();

        return previousWidth != this.containerWidth;

    };



    return Masonry;



}));



/*!

 * Masonry layout mode

 * sub-classes Masonry

 * http://masonry.desandro.com

 */



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /*globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'isotope/js/layout-modes/masonry',[

            '../layout-mode',

            'masonry/masonry'

        ],

            factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            require('../layout-mode'),

            require('masonry-layout')

        );

    } else {

        // browser global

        factory(

            window.Isotope.LayoutMode,

            window.Masonry

        );

    }



}( window, function factory( LayoutMode, Masonry ) {

    'use strict';



// -------------------------- masonryDefinition -------------------------- //



    // create an Outlayer layout class

    var MasonryMode = LayoutMode.create('masonry');



    var proto = MasonryMode.prototype;



    var keepModeMethods = {

        _getElementOffset: true,

        layout: true,

        _getMeasurement: true

    };



    // inherit Masonry prototype

    for ( var method in Masonry.prototype ) {

        // do not inherit mode methods

        if ( !keepModeMethods[ method ] ) {

            proto[ method ] = Masonry.prototype[ method ];

        }

    }



    var measureColumns = proto.measureColumns;

    proto.measureColumns = function() {

        // set items, used if measuring first item

        this.items = this.isotope.filteredItems;

        measureColumns.call( this );

    };



    // point to mode options for fitWidth

    var _getOption = proto._getOption;

    proto._getOption = function( option ) {

        if ( option == 'fitWidth' ) {

            return this.options.isFitWidth !== undefined ?

                this.options.isFitWidth : this.options.fitWidth;

        }

        return _getOption.apply( this.isotope, arguments );

    };



    return MasonryMode;



}));



/**

 * fitRows layout mode

 */



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /*globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'isotope/js/layout-modes/fit-rows',[

            '../layout-mode'

        ],

            factory );

    } else if ( typeof exports == 'object' ) {

        // CommonJS

        module.exports = factory(

            require('../layout-mode')

        );

    } else {

        // browser global

        factory(

            window.Isotope.LayoutMode

        );

    }



}( window, function factory( LayoutMode ) {

    'use strict';



    var FitRows = LayoutMode.create('fitRows');



    var proto = FitRows.prototype;



    proto._resetLayout = function() {

        this.x = 0;

        this.y = 0;

        this.maxY = 0;

        this._getMeasurement( 'gutter', 'outerWidth' );

    };



    proto._getItemLayoutPosition = function( item ) {

        item.getSize();



        var itemWidth = item.size.outerWidth + this.gutter;

        // if this element cannot fit in the current row

        var containerWidth = this.isotope.size.innerWidth + this.gutter;

        if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {

            this.x = 0;

            this.y = this.maxY;

        }



        var position = {

            x: this.x,

            y: this.y

        };



        this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );

        this.x += itemWidth;



        return position;

    };



    proto._getContainerSize = function() {

        return { height: this.maxY };

    };



    return FitRows;



}));



/**

 * vertical layout mode

 */



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /*globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( 'isotope/js/layout-modes/vertical',[

            '../layout-mode'

        ],

            factory );

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            require('../layout-mode')

        );

    } else {

        // browser global

        factory(

            window.Isotope.LayoutMode

        );

    }



}( window, function factory( LayoutMode ) {

    'use strict';



    var Vertical = LayoutMode.create( 'vertical', {

        horizontalAlignment: 0

    });



    var proto = Vertical.prototype;



    proto._resetLayout = function() {

        this.y = 0;

    };



    proto._getItemLayoutPosition = function( item ) {

        item.getSize();

        var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *

            this.options.horizontalAlignment;

        var y = this.y;

        this.y += item.size.outerHeight;

        return { x: x, y: y };

    };



    proto._getContainerSize = function() {

        return { height: this.y };

    };



    return Vertical;



}));



/*!

 * Isotope v3.0.1

 *

 * Licensed GPLv3 for open source use

 * or Isotope Commercial License for commercial use

 *

 * http://isotope.metafizzy.co

 * Copyright 2016 Metafizzy

 */



( function( window, factory ) {

    // universal module definition

    /* jshint strict: false */ /*globals define, module, require */

    if ( typeof define == 'function' && define.amd ) {

        // AMD

        define( [

            'outlayer/outlayer',

            'get-size/get-size',

            'desandro-matches-selector/matches-selector',

            'fizzy-ui-utils/utils',

            'isotope/js/item',

            'isotope/js/layout-mode',

            // include default layout modes

            'isotope/js/layout-modes/masonry',

            'isotope/js/layout-modes/fit-rows',

            'isotope/js/layout-modes/vertical'

        ],

            function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {

                return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );

            });

    } else if ( typeof module == 'object' && module.exports ) {

        // CommonJS

        module.exports = factory(

            window,

            require('outlayer'),

            require('get-size'),

            require('desandro-matches-selector'),

            require('fizzy-ui-utils'),

            require('isotope/js/item'),

            require('isotope/js/layout-mode'),

            // include default layout modes

            require('isotope/js/layout-modes/masonry'),

            require('isotope/js/layout-modes/fit-rows'),

            require('isotope/js/layout-modes/vertical')

        );

    } else {

        // browser global

        window.Isotope = factory(

            window,

            window.Outlayer,

            window.getSize,

            window.matchesSelector,

            window.fizzyUIUtils,

            window.Isotope.Item,

            window.Isotope.LayoutMode

        );

    }



}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,

                             Item, LayoutMode ) {







// -------------------------- vars -------------------------- //



    var jQuery = window.jQuery;



// -------------------------- helpers -------------------------- //



    var trim = String.prototype.trim ?

        function( str ) {

            return str.trim();

        } :

        function( str ) {

            return str.replace( /^\s+|\s+$/g, '' );

        };



// -------------------------- isotopeDefinition -------------------------- //



    // create an Outlayer layout class

    var Isotope = Outlayer.create( 'isotope', {

        layoutMode: 'masonry',

        isJQueryFiltering: true,

        sortAscending: true

    });



    Isotope.Item = Item;

    Isotope.LayoutMode = LayoutMode;



    var proto = Isotope.prototype;



    proto._create = function() {

        this.itemGUID = 0;

        // functions that sort items

        this._sorters = {};

        this._getSorters();

        // call super

        Outlayer.prototype._create.call( this );



        // create layout modes

        this.modes = {};

        // start filteredItems with all items

        this.filteredItems = this.items;

        // keep of track of sortBys

        this.sortHistory = [ 'original-order' ];

        // create from registered layout modes

        for ( var name in LayoutMode.modes ) {

            this._initLayoutMode( name );

        }

    };



    proto.reloadItems = function() {

        // reset item ID counter

        this.itemGUID = 0;

        // call super

        Outlayer.prototype.reloadItems.call( this );

    };



    proto._itemize = function() {

        var items = Outlayer.prototype._itemize.apply( this, arguments );

        // assign ID for original-order

        for ( var i=0; i < items.length; i++ ) {

            var item = items[i];

            item.id = this.itemGUID++;

        }

        this._updateItemsSortData( items );

        return items;

    };





    // -------------------------- layout -------------------------- //



    proto._initLayoutMode = function( name ) {

        var Mode = LayoutMode.modes[ name ];

        // set mode options

        // HACK extend initial options, back-fill in default options

        var initialOpts = this.options[ name ] || {};

        this.options[ name ] = Mode.options ?

            utils.extend( Mode.options, initialOpts ) : initialOpts;

        // init layout mode instance

        this.modes[ name ] = new Mode( this );

    };





    proto.layout = function() {

        // if first time doing layout, do all magic

        if ( !this._isLayoutInited && this._getOption('initLayout') ) {

            this.arrange();

            return;

        }

        this._layout();

    };



    // private method to be used in layout() & magic()

    proto._layout = function() {

        // don't animate first layout

        var isInstant = this._getIsInstant();

        // layout flow

        this._resetLayout();

        this._manageStamps();

        this.layoutItems( this.filteredItems, isInstant );



        // flag for initalized

        this._isLayoutInited = true;

    };



    // filter + sort + layout

    proto.arrange = function( opts ) {

        // set any options pass

        this.option( opts );

        this._getIsInstant();

        // filter, sort, and layout



        // filter

        var filtered = this._filter( this.items );

        this.filteredItems = filtered.matches;



        this._bindArrangeComplete();



        if ( this._isInstant ) {

            this._noTransition( this._hideReveal, [ filtered ] );

        } else {

            this._hideReveal( filtered );

        }



        this._sort();

        this._layout();

    };

    // alias to _init for main plugin method

    proto._init = proto.arrange;



    proto._hideReveal = function( filtered ) {

        this.reveal( filtered.needReveal );

        this.hide( filtered.needHide );

    };



    // HACK

    // Don't animate/transition first layout

    // Or don't animate/transition other layouts

    proto._getIsInstant = function() {

        var isLayoutInstant = this._getOption('layoutInstant');

        var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :

            !this._isLayoutInited;

        this._isInstant = isInstant;

        return isInstant;

    };



    // listen for layoutComplete, hideComplete and revealComplete

    // to trigger arrangeComplete

    proto._bindArrangeComplete = function() {

        // listen for 3 events to trigger arrangeComplete

        var isLayoutComplete, isHideComplete, isRevealComplete;

        var _this = this;

        function arrangeParallelCallback() {

            if ( isLayoutComplete && isHideComplete && isRevealComplete ) {

                _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );

            }

        }

        this.once( 'layoutComplete', function() {

            isLayoutComplete = true;

            arrangeParallelCallback();

        });

        this.once( 'hideComplete', function() {

            isHideComplete = true;

            arrangeParallelCallback();

        });

        this.once( 'revealComplete', function() {

            isRevealComplete = true;

            arrangeParallelCallback();

        });

    };



    // -------------------------- filter -------------------------- //



    proto._filter = function( items ) {

        var filter = this.options.filter;

        filter = filter || '*';

        var matches = [];

        var hiddenMatched = [];

        var visibleUnmatched = [];



        var test = this._getFilterTest( filter );



        // test each item

        for ( var i=0; i < items.length; i++ ) {

            var item = items[i];

            if ( item.isIgnored ) {

                continue;

            }

            // add item to either matched or unmatched group

            var isMatched = test( item );

            // item.isFilterMatched = isMatched;

            // add to matches if its a match

            if ( isMatched ) {

                matches.push( item );

            }

            // add to additional group if item needs to be hidden or revealed

            if ( isMatched && item.isHidden ) {

                hiddenMatched.push( item );

            } else if ( !isMatched && !item.isHidden ) {

                visibleUnmatched.push( item );

            }

        }



        // return collections of items to be manipulated

        return {

            matches: matches,

            needReveal: hiddenMatched,

            needHide: visibleUnmatched

        };

    };



    // get a jQuery, function, or a matchesSelector test given the filter

    proto._getFilterTest = function( filter ) {

        if ( jQuery && this.options.isJQueryFiltering ) {

            // use jQuery

            return function( item ) {

                return jQuery( item.element ).is( filter );

            };

        }

        if ( typeof filter == 'function' ) {

            // use filter as function

            return function( item ) {

                return filter( item.element );

            };

        }

        // default, use filter as selector string

        return function( item ) {

            return matchesSelector( item.element, filter );

        };

    };



    // -------------------------- sorting -------------------------- //



    /**

     * @params {Array} elems

     * @public

     */

    proto.updateSortData = function( elems ) {

        // get items

        var items;

        if ( elems ) {

            elems = utils.makeArray( elems );

            items = this.getItems( elems );

        } else {

            // update all items if no elems provided

            items = this.items;

        }



        this._getSorters();

        this._updateItemsSortData( items );

    };



    proto._getSorters = function() {

        var getSortData = this.options.getSortData;

        for ( var key in getSortData ) {

            var sorter = getSortData[ key ];

            this._sorters[ key ] = mungeSorter( sorter );

        }

    };



    /**

     * @params {Array} items - of Isotope.Items

     * @private

     */

    proto._updateItemsSortData = function( items ) {

        // do not update if no items

        var len = items && items.length;



        for ( var i=0; len && i < len; i++ ) {

            var item = items[i];

            item.updateSortData();

        }

    };



    // ----- munge sorter ----- //



    // encapsulate this, as we just need mungeSorter

    // other functions in here are just for munging

    var mungeSorter = ( function() {

        // add a magic layer to sorters for convienent shorthands

        // `.foo-bar` will use the text of .foo-bar querySelector

        // `[foo-bar]` will use attribute

        // you can also add parser

        // `.foo-bar parseInt` will parse that as a number

        function mungeSorter( sorter ) {

            // if not a string, return function or whatever it is

            if ( typeof sorter != 'string' ) {

                return sorter;

            }

            // parse the sorter string

            var args = trim( sorter ).split(' ');

            var query = args[0];

            // check if query looks like [an-attribute]

            var attrMatch = query.match( /^\[(.+)\]$/ );

            var attr = attrMatch && attrMatch[1];

            var getValue = getValueGetter( attr, query );

            // use second argument as a parser

            var parser = Isotope.sortDataParsers[ args[1] ];

            // parse the value, if there was a parser

            sorter = parser ? function( elem ) {

                return elem && parser( getValue( elem ) );

            } :

                // otherwise just return value

                function( elem ) {

                    return elem && getValue( elem );

                };



            return sorter;

        }



        // get an attribute getter, or get text of the querySelector

        function getValueGetter( attr, query ) {

            // if query looks like [foo-bar], get attribute

            if ( attr ) {

                return function getAttribute( elem ) {

                    return elem.getAttribute( attr );

                };

            }



            // otherwise, assume its a querySelector, and get its text

            return function getChildText( elem ) {

                var child = elem.querySelector( query );

                return child && child.textContent;

            };

        }



        return mungeSorter;

    })();



    // parsers used in getSortData shortcut strings

    Isotope.sortDataParsers = {

        'parseInt': function( val ) {

            return parseInt( val, 10 );

        },

        'parseFloat': function( val ) {

            return parseFloat( val );

        }

    };



    // ----- sort method ----- //



    // sort filteredItem order

    proto._sort = function() {

        var sortByOpt = this.options.sortBy;

        if ( !sortByOpt ) {

            return;

        }

        // concat all sortBy and sortHistory

        var sortBys = [].concat.apply( sortByOpt, this.sortHistory );

        // sort magic

        var itemSorter = getItemSorter( sortBys, this.options.sortAscending );

        this.filteredItems.sort( itemSorter );

        // keep track of sortBy History

        if ( sortByOpt != this.sortHistory[0] ) {

            // add to front, oldest goes in last

            this.sortHistory.unshift( sortByOpt );

        }

    };



    // returns a function used for sorting

    function getItemSorter( sortBys, sortAsc ) {

        return function sorter( itemA, itemB ) {

            // cycle through all sortKeys

            for ( var i = 0; i < sortBys.length; i++ ) {

                var sortBy = sortBys[i];

                var a = itemA.sortData[ sortBy ];

                var b = itemB.sortData[ sortBy ];

                if ( a > b || a < b ) {

                    // if sortAsc is an object, use the value given the sortBy key

                    var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;

                    var direction = isAscending ? 1 : -1;

                    return ( a > b ? 1 : -1 ) * direction;

                }

            }

            return 0;

        };

    }



    // -------------------------- methods -------------------------- //



    // get layout mode

    proto._mode = function() {

        var layoutMode = this.options.layoutMode;

        var mode = this.modes[ layoutMode ];

        if ( !mode ) {

            // TODO console.error

            throw new Error( 'No layout mode: ' + layoutMode );

        }

        // HACK sync mode's options

        // any options set after init for layout mode need to be synced

        mode.options = this.options[ layoutMode ];

        return mode;

    };



    proto._resetLayout = function() {

        // trigger original reset layout

        Outlayer.prototype._resetLayout.call( this );

        this._mode()._resetLayout();

    };



    proto._getItemLayoutPosition = function( item  ) {

        return this._mode()._getItemLayoutPosition( item );

    };



    proto._manageStamp = function( stamp ) {

        this._mode()._manageStamp( stamp );

    };



    proto._getContainerSize = function() {

        return this._mode()._getContainerSize();

    };



    proto.needsResizeLayout = function() {

        return this._mode().needsResizeLayout();

    };



    // -------------------------- adding & removing -------------------------- //



    // HEADS UP overwrites default Outlayer appended

    proto.appended = function( elems ) {

        var items = this.addItems( elems );

        if ( !items.length ) {

            return;

        }

        // filter, layout, reveal new items

        var filteredItems = this._filterRevealAdded( items );

        // add to filteredItems

        this.filteredItems = this.filteredItems.concat( filteredItems );

    };



    // HEADS UP overwrites default Outlayer prepended

    proto.prepended = function( elems ) {

        var items = this._itemize( elems );

        if ( !items.length ) {

            return;

        }

        // start new layout

        this._resetLayout();

        this._manageStamps();

        // filter, layout, reveal new items

        var filteredItems = this._filterRevealAdded( items );

        // layout previous items

        this.layoutItems( this.filteredItems );

        // add to items and filteredItems

        this.filteredItems = filteredItems.concat( this.filteredItems );

        this.items = items.concat( this.items );

    };



    proto._filterRevealAdded = function( items ) {

        var filtered = this._filter( items );

        this.hide( filtered.needHide );

        // reveal all new items

        this.reveal( filtered.matches );

        // layout new items, no transition

        this.layoutItems( filtered.matches, true );

        return filtered.matches;

    };



    /**

     * Filter, sort, and layout newly-appended item elements

     * @param {Array or NodeList or Element} elems

     */

    proto.insert = function( elems ) {

        var items = this.addItems( elems );

        if ( !items.length ) {

            return;

        }

        // append item elements

        var i, item;

        var len = items.length;

        for ( i=0; i < len; i++ ) {

            item = items[i];

            this.element.appendChild( item.element );

        }

        // filter new stuff

        var filteredInsertItems = this._filter( items ).matches;

        // set flag

        for ( i=0; i < len; i++ ) {

            items[i].isLayoutInstant = true;

        }

        this.arrange();

        // reset flag

        for ( i=0; i < len; i++ ) {

            delete items[i].isLayoutInstant;

        }

        this.reveal( filteredInsertItems );

    };



    var _remove = proto.remove;

    proto.remove = function( elems ) {

        elems = utils.makeArray( elems );

        var removeItems = this.getItems( elems );

        // do regular thing

        _remove.call( this, elems );

        // bail if no items to remove

        var len = removeItems && removeItems.length;

        // remove elems from filteredItems

        for ( var i=0; len && i < len; i++ ) {

            var item = removeItems[i];

            // remove item from collection

            utils.removeFrom( this.filteredItems, item );

        }

    };



    proto.shuffle = function() {

        // update random sortData

        for ( var i=0; i < this.items.length; i++ ) {

            var item = this.items[i];

            item.sortData.random = Math.random();

        }

        this.options.sortBy = 'random';

        this._sort();

        this._layout();

    };



    /**

     * trigger fn without transition

     * kind of hacky to have this in the first place

     * @param {Function} fn

     * @param {Array} args

     * @returns ret

     * @private

     */

    proto._noTransition = function( fn, args ) {

        // save transitionDuration before disabling

        var transitionDuration = this.options.transitionDuration;

        // disable transition

        this.options.transitionDuration = 0;

        // do it

        var returnValue = fn.apply( this, args );

        // re-enable transition for reveal

        this.options.transitionDuration = transitionDuration;

        return returnValue;

    };



    // ----- helper methods ----- //



    /**

     * getter method for getting filtered item elements

     * @returns {Array} elems - collection of item elements

     */

    proto.getFilteredItemElements = function() {

        return this.filteredItems.map( function( item ) {

            return item.element;

        });

    };



    // -----  ----- //



    return Isotope;



}));

/*
 * jQuery.appear
 * https://github.com/bas2k/jquery.appear/
 * http://code.google.com/p/jquery-appear/
 * http://bas2k.ru/
 *
 * Copyright (c) 2009 Michael Hixson
 * Copyright (c) 2012-2014 Alexander Brovikov
 * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
 */
(function($) {
    $.fn.appear = function(fn, options) {

        var settings = $.extend({

            //arbitrary data to pass to fn
            data: undefined,

            //call fn only on the first appear?
            one: true,

            // X & Y accuracy
            accX: 0,
            accY: 0

        }, options);

        return this.each(function() {

            var t = $(this);

            //whether the element is currently visible
            t.appeared = false;

            if (!fn) {

                //trigger the custom event
                t.trigger('appear', settings.data);
                return;
            }

            var w = $(window);

            //fires the appear event when appropriate
            var check = function() {

                //is the element hidden?
                if (!t.is(':visible')) {

                    //it became hidden
                    t.appeared = false;
                    return;
                }

                //is the element inside the visible window?
                var a = w.scrollLeft();
                var b = w.scrollTop();
                var o = t.offset();
                var x = o.left;
                var y = o.top;

                var ax = settings.accX;
                var ay = settings.accY;
                var th = t.height();
                var wh = w.height();
                var tw = t.width();
                var ww = w.width();

                if (y + th + ay >= b &&
                    y <= b + wh + ay &&
                    x + tw + ax >= a &&
                    x <= a + ww + ax) {

                    //trigger the custom event
                    if (!t.appeared) t.trigger('appear', settings.data);

                } else {

                    //it scrolled out of view
                    t.appeared = false;
                }
            };

            //create a modified fn with some additional logic
            var modifiedFn = function() {

                //mark the element as visible
                t.appeared = true;

                //is this supposed to happen only once?
                if (settings.one) {

                    //remove the check
                    w.unbind('scroll', check);
                    var i = $.inArray(check, $.fn.appear.checks);
                    if (i >= 0) $.fn.appear.checks.splice(i, 1);
                }

                //trigger the original fn
                fn.apply(this, arguments);
            };

            //bind the modified fn to the element
            if (settings.one) t.one('appear', settings.data, modifiedFn);
            else t.bind('appear', settings.data, modifiedFn);

            //check whenever the window scrolls
            w.scroll(check);

            //check whenever the dom changes
            $.fn.appear.checks.push(check);

            //check now
            (check)();
        });
    };

    //keep a queue of appearance checks
    $.extend($.fn.appear, {

        checks: [],
        timeout: null,

        //process the queue
        checkAll: function() {
            var length = $.fn.appear.checks.length;
            if (length > 0) while (length--) {
                if (typeof $.fn.appear.checks[length] == 'function')
                    ($.fn.appear.checks[length])();
            }
        },

        //check the queue asynchronously
        run: function() {
            if ($.fn.appear.timeout) clearTimeout($.fn.appear.timeout);
            $.fn.appear.timeout = setTimeout($.fn.appear.checkAll, 20);
        }
    });

    //run checks when these methods are called
    $.each(['append', 'prepend', 'after', 'before', 'attr',
        'removeAttr', 'addClass', 'removeClass', 'toggleClass',
        'remove', 'css', 'show', 'hide'], function(i, n) {
        var old = $.fn[n];
        if (old) {
            $.fn[n] = function() {
                var r = old.apply(this, arguments);
                $.fn.appear.run();
                return r;
            }
        }
    });

})(jQuery);

/**!
 * easyPieChart
 * Lightweight plugin to render simple, animated and retina optimized pie charts
 *
 * @license 
 * @author Robert Fleischmann <rendro87@gmail.com> (http://robert-fleischmann.de)
 * @version 2.1.4
 **/

(function(root, factory) {
    if(typeof exports === 'object') {
        module.exports = factory(require('jquery'));
    }
    else if(typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    }
    else {
        factory(root.jQuery);
    }
}(this, function($) {
/**
 * Renderer to render the chart on a canvas object
 * @param {DOMElement} el      DOM element to host the canvas (root of the plugin)
 * @param {object}     options options object of the plugin
 */
var CanvasRenderer = function(el, options) {
	var cachedBackground;
	var canvas = document.createElement('canvas');

	el.appendChild(canvas);

	if (typeof(G_vmlCanvasManager) !== 'undefined') {
		G_vmlCanvasManager.initElement(canvas);
	}

	var ctx = canvas.getContext('2d');

	canvas.width = canvas.height = options.size;

	// canvas on retina devices
	var scaleBy = 1;
	if (window.devicePixelRatio > 1) {
		scaleBy = window.devicePixelRatio;
		canvas.style.width = canvas.style.height = [options.size, 'px'].join('');
		canvas.width = canvas.height = options.size * scaleBy;
		ctx.scale(scaleBy, scaleBy);
	}

	// move 0,0 coordinates to the center
	ctx.translate(options.size / 2, options.size / 2);

	// rotate canvas -90deg
	ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);

	var radius = (options.size - options.lineWidth) / 2;
	if (options.scaleColor && options.scaleLength) {
		radius -= options.scaleLength + 2; // 2 is the distance between scale and bar
	}

	// IE polyfill for Date
	Date.now = Date.now || function() {
		return +(new Date());
	};

	/**
	 * Draw a circle around the center of the canvas
	 * @param {strong} color     Valid CSS color string
	 * @param {number} lineWidth Width of the line in px
	 * @param {number} percent   Percentage to draw (float between -1 and 1)
	 */
	var drawCircle = function(color, lineWidth, percent) {
		percent = Math.min(Math.max(-1, percent || 0), 1);
		var isNegative = percent <= 0 ? true : false;

		ctx.beginPath();
		ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, isNegative);

		ctx.strokeStyle = color;
		ctx.lineWidth = lineWidth;

		ctx.stroke();
	};

	/**
	 * Draw the scale of the chart
	 */
	var drawScale = function() {
		var offset;
		var length;

		ctx.lineWidth = 1;
		ctx.fillStyle = options.scaleColor;

		ctx.save();
		for (var i = 24; i > 0; --i) {
			if (i % 6 === 0) {
				length = options.scaleLength;
				offset = 0;
			} else {
				length = options.scaleLength * 0.6;
				offset = options.scaleLength - length;
			}
			ctx.fillRect(-options.size/2 + offset, 0, length, 1);
			ctx.rotate(Math.PI / 12);
		}
		ctx.restore();
	};

	/**
	 * Request animation frame wrapper with polyfill
	 * @return {function} Request animation frame method or timeout fallback
	 */
	var reqAnimationFrame = (function() {
		return  window.requestAnimationFrame ||
				window.webkitRequestAnimationFrame ||
				window.mozRequestAnimationFrame ||
				function(callback) {
					window.setTimeout(callback, 1000 / 60);
				};
	}());

	/**
	 * Draw the background of the plugin including the scale and the track
	 */
	var drawBackground = function() {
		if(options.scaleColor) drawScale();
		if(options.trackColor) drawCircle(options.trackColor, options.lineWidth, 1);
	};

  /**
    * Canvas accessor
   */
  this.getCanvas = function() {
    return canvas;
  };
  
  /**
    * Canvas 2D context 'ctx' accessor
   */
  this.getCtx = function() {
    return ctx;
  };

	/**
	 * Clear the complete canvas
	 */
	this.clear = function() {
		ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size);
	};

	/**
	 * Draw the complete chart
	 * @param {number} percent Percent shown by the chart between -100 and 100
	 */
	this.draw = function(percent) {
		// do we need to render a background
		if (!!options.scaleColor || !!options.trackColor) {
			// getImageData and putImageData are supported
			if (ctx.getImageData && ctx.putImageData) {
				if (!cachedBackground) {
					drawBackground();
					cachedBackground = ctx.getImageData(0, 0, options.size * scaleBy, options.size * scaleBy);
				} else {
					ctx.putImageData(cachedBackground, 0, 0);
				}
			} else {
				this.clear();
				drawBackground();
			}
		} else {
			this.clear();
		}

		ctx.lineCap = options.lineCap;

		// if barcolor is a function execute it and pass the percent as a value
		var color;
		if (typeof(options.barColor) === 'function') {
			color = options.barColor(percent);
		} else {
			color = options.barColor;
		}

		// draw bar
		drawCircle(color, options.lineWidth, percent / 100);
	}.bind(this);

	/**
	 * Animate from some percent to some other percentage
	 * @param {number} from Starting percentage
	 * @param {number} to   Final percentage
	 */
	this.animate = function(from, to) {
		var startTime = Date.now();
		options.onStart(from, to);
		var animation = function() {
			var process = Math.min(Date.now() - startTime, options.animate.duration);
			var currentValue = options.easing(this, process, from, to - from, options.animate.duration);
			this.draw(currentValue);
			options.onStep(from, to, currentValue);
			if (process >= options.animate.duration) {
				options.onStop(from, to);
			} else {
				reqAnimationFrame(animation);
			}
		}.bind(this);

		reqAnimationFrame(animation);
	}.bind(this);
};

var EasyPieChart = function(el, opts) {
	var defaultOptions = {
		barColor: '#ef1e25',
		trackColor: '#f9f9f9',
		scaleColor: '#dfe0e0',
		scaleLength: 5,
		lineCap: 'round',
		lineWidth: 3,
		size: 110,
		rotate: 0,
		animate: {
			duration: 1000,
			enabled: true
		},
		easing: function (x, t, b, c, d) { // more can be found here: http://gsgd.co.uk/sandbox/jquery/easing/
			t = t / (d/2);
			if (t < 1) {
				return c / 2 * t * t + b;
			}
			return -c/2 * ((--t)*(t-2) - 1) + b;
		},
		onStart: function(from, to) {
			return;
		},
		onStep: function(from, to, currentValue) {
			return;
		},
		onStop: function(from, to) {
			return;
		}
	};

	// detect present renderer
	if (typeof(CanvasRenderer) !== 'undefined') {
		defaultOptions.renderer = CanvasRenderer;
	} else if (typeof(SVGRenderer) !== 'undefined') {
		defaultOptions.renderer = SVGRenderer;
	} else {
		throw new Error('Please load either the SVG- or the CanvasRenderer');
	}

	var options = {};
	var currentValue = 0;

	/**
	 * Initialize the plugin by creating the options object and initialize rendering
	 */
	var init = function() {
		this.el = el;
		this.options = options;

		// merge user options into default options
		for (var i in defaultOptions) {
			if (defaultOptions.hasOwnProperty(i)) {
				options[i] = opts && typeof(opts[i]) !== 'undefined' ? opts[i] : defaultOptions[i];
				if (typeof(options[i]) === 'function') {
					options[i] = options[i].bind(this);
				}
			}
		}

		// check for jQuery easing
		if (typeof(options.easing) === 'string' && typeof(jQuery) !== 'undefined' && jQuery.isFunction(jQuery.easing[options.easing])) {
			options.easing = jQuery.easing[options.easing];
		} else {
			options.easing = defaultOptions.easing;
		}

		// process earlier animate option to avoid bc breaks
		if (typeof(options.animate) === 'number') {
			options.animate = {
				duration: options.animate,
				enabled: true
			};
		}

		if (typeof(options.animate) === 'boolean' && !options.animate) {
			options.animate = {
				duration: 1000,
				enabled: options.animate
			};
		}

		// create renderer
		this.renderer = new options.renderer(el, options);

		// initial draw
		this.renderer.draw(currentValue);

		// initial update
		if (el.dataset && el.dataset.percent) {
			this.update(parseFloat(el.dataset.percent));
		} else if (el.getAttribute && el.getAttribute('data-percent')) {
			this.update(parseFloat(el.getAttribute('data-percent')));
		}
	}.bind(this);

	/**
	 * Update the value of the chart
	 * @param  {number} newValue Number between 0 and 100
	 * @return {object}          Instance of the plugin for method chaining
	 */
	this.update = function(newValue) {
		newValue = parseFloat(newValue);
		if (options.animate.enabled) {
			this.renderer.animate(currentValue, newValue);
		} else {
			this.renderer.draw(newValue);
		}
		currentValue = newValue;
		return this;
	}.bind(this);

	/**
	 * Disable animation
	 * @return {object} Instance of the plugin for method chaining
	 */
	this.disableAnimation = function() {
		options.animate.enabled = false;
		return this;
	};

	/**
	 * Enable animation
	 * @return {object} Instance of the plugin for method chaining
	 */
	this.enableAnimation = function() {
		options.animate.enabled = true;
		return this;
	};

	init();
};

$.fn.easyPieChart = function(options) {
	return this.each(function() {
		var instanceOptions;

		if (!$.data(this, 'easyPieChart')) {
			instanceOptions = $.extend({}, options, $(this).data());
			$.data(this, 'easyPieChart', new EasyPieChart(this, instanceOptions));
		}
	});
};

}));


/*global jQuery */
/*jshint browser:true */
/*!
* FitVids 1.1
*
* Copyright 2013, Chris Coyier - http://css-tricks.com + Dave Rupert - http://daverupert.com
* Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/
* Released under the WTFPL license - http://sam.zoy.org/wtfpl/
*
*/

(function( $ ){

  "use strict";

  $.fn.fitVids = function( options ) {
    var settings = {
      customSelector: null
    };

    if(!document.getElementById('fit-vids-style')) {
      // appendStyles: https://github.com/toddmotto/fluidvids/blob/master/dist/fluidvids.js
      var head = document.head || document.getElementsByTagName('head')[0];
      var css = '.fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}';
      var div = document.createElement('div');
      div.innerHTML = '<p>x</p><style id="fit-vids-style">' + css + '</style>';
      head.appendChild(div.childNodes[1]);
    }

    if ( options ) {
      $.extend( settings, options );
    }

    return this.each(function(){
      var selectors = [
        "iframe[src*='player.vimeo.com']",
        "iframe[src*='youtube.com']",
        "iframe[src*='youtube-nocookie.com']",
        "iframe[src*='kickstarter.com'][src*='video.html']",
        "object",
        "embed"
      ];

      if (settings.customSelector) {
        selectors.push(settings.customSelector);
      }

      var $allVideos = $(this).find(selectors.join(','));
      $allVideos = $allVideos.not("object object"); // SwfObj conflict patch

      $allVideos.each(function(){
        var $this = $(this);
        if (this.tagName.toLowerCase() === 'embed' && $this.parent('object').length || $this.parent('.fluid-width-video-wrapper').length) { return; }
        var height = ( this.tagName.toLowerCase() === 'object' || ($this.attr('height') && !isNaN(parseInt($this.attr('height'), 10))) ) ? parseInt($this.attr('height'), 10) : $this.height(),
            width = !isNaN(parseInt($this.attr('width'), 10)) ? parseInt($this.attr('width'), 10) : $this.width(),
            aspectRatio = height / width;
        if(!$this.attr('id')){
          var videoID = 'fitvid' + Math.floor(Math.random()*999999);
          $this.attr('id', videoID);
        }
        $this.wrap('<div class="fluid-width-video-wrapper"></div>').parent('.fluid-width-video-wrapper').css('padding-top', (aspectRatio * 100)+"%");
        $this.removeAttr('height').removeAttr('width');
      });
    });
  };
// Works with either jQuery or Zepto
})( window.jQuery || window.Zepto );


/*
 *	jQuery elevateZoom 3.0.8
 *	Demo's and documentation:
 *	www.elevateweb.co.uk/image-zoom
 *
 *	Copyright (c) 2012 Andrew Eades
 *	www.elevateweb.co.uk
 *
 *	Dual licensed under the GPL and MIT licenses.
 *	http://en.wikipedia.org/wiki/MIT_License
 *	http://en.wikipedia.org/wiki/GNU_General_Public_License
 *

/*
 *	jQuery elevateZoom 3.0.3
 *	Demo's and documentation:
 *	www.elevateweb.co.uk/image-zoom
 *
 *	Copyright (c) 2012 Andrew Eades
 *	www.elevateweb.co.uk
 *
 *	Dual licensed under the GPL and MIT licenses.
 *	http://en.wikipedia.org/wiki/MIT_License
 *	http://en.wikipedia.org/wiki/GNU_General_Public_License
 */


if ( typeof Object.create !== 'function' ) {
	Object.create = function( obj ) {
		function F() {};
		F.prototype = obj;
		return new F();
	};
}

(function( $, window, document, undefined ) {
	var ElevateZoom = {
			init: function( options, elem ) {
				var self = this;

				self.elem = elem;
				self.$elem = $( elem );
                
				self.imageSrc = self.$elem.data("zoom-image") ? self.$elem.data("zoom-image") : self.$elem.attr("src");

				self.options = $.extend( {}, $.fn.elevateZoom.options, options );

				//TINT OVERRIDE SETTINGS
				if(self.options.tint) {
					self.options.lensColour = "none", //colour of the lens background
					self.options.lensOpacity =  "1" //opacity of the lens
				}
				//INNER OVERRIDE SETTINGS
				if(self.options.zoomType == "inner") {self.options.showLens = false;}

                // INIT CONTAINER
                if (self.options.zoomContainer)
                    self.$container = $( self.options.zoomContainer );
                else
                    self.$container = $( 'body' );

				//Remove alt on hover

				self.$elem.parent().removeAttr('title').removeAttr('alt');

				self.zoomImage = self.imageSrc;

				self.refresh( 1 );



				//Create the image swap from the gallery 
				$('#'+self.options.gallery + ' a').click( function(e) { 

					//Set a class on the currently active gallery image
					if(self.options.galleryActiveClass){
						$('#'+self.options.gallery + ' a').removeClass(self.options.galleryActiveClass);
						$(this).addClass(self.options.galleryActiveClass);
					}
					//stop any link on the a tag from working
					e.preventDefault();

					//call the swap image function            
					if($(this).data("zoom-image")){self.zoomImagePre = $(this).data("zoom-image")}
					else{self.zoomImagePre = $(this).data("image");}
					self.swaptheimage($(this).data("image"), self.zoomImagePre);
					return false;
				});

			},

			refresh: function( length ) {
				var self = this;

				setTimeout(function() {
					self.fetch(self.imageSrc);

				}, length || self.options.refresh );
			},

			fetch: function(imgsrc) {
				//get the image
				var self = this;
				var newImg = new Image();
				newImg.onload = function() {
					//set the large image dimensions - used to calculte ratio's
					self.largeWidth = newImg.width;
					self.largeHeight = newImg.height;
					//once image is loaded start the calls
					self.startZoom();
					self.currentImage = self.imageSrc;
					//let caller know image has been loaded
					self.options.onZoomedImageLoaded(self.$elem);
				}
				newImg.src = imgsrc; // this must be done AFTER setting onload

				return;

			},

			startZoom: function( ) {
				var self = this;
				//get dimensions of the non zoomed image
				self.nzWidth = self.$elem.width();
				self.nzHeight = self.$elem.height();

				//activated elements
				self.isWindowActive = false;
				self.isLensActive = false;
				self.isTintActive = false;
				self.overWindow = false;    

				//CrossFade Wrappe
				if(self.options.imageCrossfade){
					self.zoomWrap = self.$elem.wrap('<div style="height:'+self.nzHeight+'px;width:'+self.nzWidth+'px;" class="zoomWrapper" />');        
					self.$elem.css('position', 'absolute'); 
				}

				self.zoomLock = 1;
				self.scrollingLock = false;
				self.changeBgSize = false;
				self.currentZoomLevel = self.options.zoomLevel;


				//get offset of the non zoomed image
				self.nzOffset = self.$elem.offset();
                //get offset of the container
                self.ctOffset = self.$container.offset();
				//calculate the width ratio of the large/small image
				self.widthRatio = (self.largeWidth/self.currentZoomLevel) / self.nzWidth;
				self.heightRatio = (self.largeHeight/self.currentZoomLevel) / self.nzHeight; 


				//if window zoom        
				if(self.options.zoomType == "window") {
					self.zoomWindowStyle = "overflow: hidden;"
						+ "background-position: 0px 0px;text-align:center;"  
						+ "background-color: " + String(self.options.zoomWindowBgColour)            
						+ ";width: " + String(self.options.zoomWindowWidth) + "px;"
						+ "height: " + String(self.options.zoomWindowHeight)
						+ "px;float: left;"
						+ "background-size: "+ self.largeWidth/self.currentZoomLevel+ "px " +self.largeHeight/self.currentZoomLevel + "px;"
						+ "display: none;z-index:100;"
						+ "border: " + String(self.options.borderSize) 
						+ "px solid " + self.options.borderColour 
						+ ";background-repeat: no-repeat;"
						+ "position: absolute;";
				}    


				//if inner  zoom    
				if(self.options.zoomType == "inner") {
					//has a border been put on the image? Lets cater for this

					var borderWidth = self.$elem.css("border-left-width");

					self.zoomWindowStyle = "overflow: hidden;"
						+ "margin-left: -" + String(self.options.borderSize) + "px;" 
						+ "margin-top: -" + String(self.options.borderSize) + "px;"         
						+ "background-position: 0px 0px;"
						+ "width: " + String(self.nzWidth) + "px;"
						+ "height: " + String(self.nzHeight)
						+ "px;float: left;"
						+ "display: none;"
						+ "cursor:"+(self.options.cursor)+";"
                        + "border: " + String(self.options.borderSize)
						+ "px solid " + self.options.borderColour 
						+ ";background-repeat: no-repeat;"
						+ "position: absolute;";
				}    



				//lens style for window zoom
				if(self.options.zoomType == "window") {


					// adjust images less than the window height

					if(self.nzHeight < self.options.zoomWindowWidth/self.widthRatio){
						lensHeight = self.nzHeight;              
					}
					else{
						lensHeight = String((self.options.zoomWindowHeight/self.heightRatio))
					}
					if(self.largeWidth < self.options.zoomWindowWidth){
						lensWidth = self.nzWidth;
					}       
					else{
						lensWidth =  (self.options.zoomWindowWidth/self.widthRatio);
					}


					self.lensStyle = "background-position: 0px 0px;width: " + String((self.options.zoomWindowWidth)/self.widthRatio) + "px;height: " + String((self.options.zoomWindowHeight)/self.heightRatio)
					+ "px;float: right;display: none;"
					+ "overflow: hidden;"
					+ "z-index: 999;"   
					+ "-webkit-transform: translateZ(0);"               
					+ "opacity:"+(self.options.lensOpacity)+";filter: alpha(opacity = "+(self.options.lensOpacity*100)+"); zoom:1;"
					+ "width:"+lensWidth+"px;"
					+ "height:"+lensHeight+"px;"
					+ "background-color:"+(self.options.lensColour)+";"					
					+ "cursor:"+(self.options.cursor)+";"
					+ "border: "+(self.options.lensBorderSize)+"px" +
					" solid "+(self.options.lensBorderColour)+";background-repeat: no-repeat;position: absolute;";
				} 


				//tint style
				self.tintStyle = "display: block;"
					+ "position: absolute;"
					+ "background-color: "+self.options.tintColour+";"	
					+ "filter:alpha(opacity=0);"		
					+ "opacity: 0;"	
					+ "width: " + self.nzWidth + "px;"
					+ "height: " + self.nzHeight + "px;"

					;

				//lens style for lens zoom with optional round for modern browsers
				self.lensRound = '';

				if(self.options.zoomType == "lens") {

					self.lensStyle = "background-position: 0px 0px;"
						+ "float: left;display: none;"
						+ "border: " + String(self.options.borderSize) + "px solid " + self.options.borderColour+";"
						+ "width:"+ String(self.options.lensSize) +"px;"
						+ "height:"+ String(self.options.lensSize)+"px;"
						+ "background-repeat: no-repeat;position: absolute;";


				}


				//does not round in all browsers
				if(self.options.lensShape == "round") {
					self.lensRound = "border-top-left-radius: " + String(self.options.lensSize / 2 + self.options.borderSize) + "px;"
					+ "border-top-right-radius: " + String(self.options.lensSize / 2 + self.options.borderSize) + "px;"
					+ "border-bottom-left-radius: " + String(self.options.lensSize / 2 + self.options.borderSize) + "px;"
					+ "border-bottom-right-radius: " + String(self.options.lensSize / 2 + self.options.borderSize) + "px;";

				}

				//create the div's                                                + ""
				//self.zoomContainer = $('<div/>').addClass('zoomContainer').css({"position":"relative", "height":self.nzHeight, "width":self.nzWidth});

                if (typeof self.ctOffset == 'undefined')
                    return;
                if (self.$container.find('.zoomContainer').length)
                    self.$container.find('.zoomContainer').remove();
				self.zoomContainer = $('<div class="zoomContainer" style="-webkit-transform: translateZ(0);position:absolute;left:'+(self.nzOffset.left-self.ctOffset.left)+'px;top:'+(self.nzOffset.top-self.ctOffset.top)+'px;height:'+self.nzHeight+'px;width:'+self.nzWidth+'px;"></div>');
				self.$container.append(self.zoomContainer);	


				//this will add overflow hidden and contrain the lens on lens mode       
				if(self.options.containLensZoom && self.options.zoomType == "lens"){
					self.zoomContainer.css("overflow", "hidden");
				}
				if(self.options.zoomType != "inner") {
					self.zoomLens = $("<div class='zoomLens' style='" + self.lensStyle + self.lensRound +"'>&nbsp;</div>")
					.appendTo(self.zoomContainer)
					.click(function () {
						self.$elem.trigger('click');
					});


					if(self.options.tint) {
						self.tintContainer = $('<div/>').addClass('tintContainer');	
						self.zoomTint = $("<div class='zoomTint' style='"+self.tintStyle+"'></div>");


						self.zoomLens.wrap(self.tintContainer);


						self.zoomTintcss = self.zoomLens.after(self.zoomTint);	

						//if tint enabled - set an image to show over the tint

						self.zoomTintImage = $('<img style="position: absolute; left: 0px; top: 0px; max-width: none; width: '+self.nzWidth+'px; height: '+self.nzHeight+'px;" src="'+self.imageSrc+'">')
						.appendTo(self.zoomLens)
						.click(function () {

							self.$elem.trigger('click');
						});

					}          

				}

				//create zoom window 
				if(isNaN(self.options.zoomWindowPosition)){
					self.zoomWindow = $("<div style='z-index:999;left:"+(self.windowOffsetLeft)+"px;top:"+(self.windowOffsetTop)+"px;" + self.zoomWindowStyle + "' class='zoomWindow'>&nbsp;</div>")
					.appendTo(self.$container)
					.click(function () {
						self.$elem.trigger('click');
					});
				}else{
					self.zoomWindow = $("<div style='z-index:999;left:"+(self.windowOffsetLeft)+"px;top:"+(self.windowOffsetTop)+"px;" + self.zoomWindowStyle + "' class='zoomWindow'>&nbsp;</div>")
					.appendTo(self.zoomContainer)
					.click(function () {
						self.$elem.trigger('click');
					});
				}              
				self.zoomWindowContainer = $('<div/>').addClass('zoomWindowContainer').css("width",self.options.zoomWindowWidth);
				self.zoomWindow.wrap(self.zoomWindowContainer);

				//  self.captionStyle = "text-align: left;background-color: black;color: white;font-weight: bold;padding: 10px;font-family: sans-serif;font-size: 11px";                                                           
				// self.zoomCaption = $('<div class="elevatezoom-caption" style="'+self.captionStyle+'display: block; width: 280px;">INSERT ALT TAG</div>').appendTo(self.zoomWindow.parent());

				if(self.options.zoomType == "lens") {
					self.zoomLens.css({ backgroundImage: "url('" + self.imageSrc + "')" }); 
				}
				if(self.options.zoomType == "window") {
					self.zoomWindow.css({ backgroundImage: "url('" + self.imageSrc + "')" }); 
				}
				if(self.options.zoomType == "inner") {
					self.zoomWindow.css({ backgroundImage: "url('" + self.imageSrc + "')" }); 
				}
				/*-------------------END THE ZOOM WINDOW AND LENS----------------------------------*/
				//touch events
				self.$elem.bind('touchmove', function(e){    
					e.preventDefault();
					var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];  
					self.setPosition(touch);

				});  
				self.zoomContainer.bind('touchmove', function(e){ 
					if(self.options.zoomType == "inner") {
						self.showHideWindow("show");

					}
					e.preventDefault();
					var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];  
					self.setPosition(touch); 

				});  	
				self.zoomContainer.bind('touchend', function(e){ 
					self.showHideWindow("hide");
					if(self.options.showLens) {self.showHideLens("hide");}
					if(self.options.tint && self.options.zoomType != "inner") {self.showHideTint("hide");}
				});  	

				self.$elem.bind('touchend', function(e){ 
					self.showHideWindow("hide");
					if(self.options.showLens) {self.showHideLens("hide");}
					if(self.options.tint && self.options.zoomType != "inner") {self.showHideTint("hide");}
				});  	
				if(self.options.showLens) {
					self.zoomLens.bind('touchmove', function(e){ 

						e.preventDefault();
						var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];  
						self.setPosition(touch); 
					});    


					self.zoomLens.bind('touchend', function(e){ 
						self.showHideWindow("hide");
						if(self.options.showLens) {self.showHideLens("hide");}
						if(self.options.tint && self.options.zoomType != "inner") {self.showHideTint("hide");}
					});  
				}
				//Needed to work in IE
				self.$elem.bind('mousemove', function(e){   
					if(self.overWindow == false){self.setElements("show");}
					//make sure on orientation change the setposition is not fired
					if(self.lastX !== e.clientX || self.lastY !== e.clientY){
						self.setPosition(e);
						self.currentLoc = e;
					}   
					self.lastX = e.clientX;
					self.lastY = e.clientY;    

				});  	

				self.zoomContainer.bind('mousemove', function(e){ 

					if(self.overWindow == false){self.setElements("show");} 

					//make sure on orientation change the setposition is not fired 
					if(self.lastX !== e.clientX || self.lastY !== e.clientY){
						self.setPosition(e);
						self.currentLoc = e;
					}   
					self.lastX = e.clientX;
					self.lastY = e.clientY;    
				});  	
				if(self.options.zoomType != "inner") {
					self.zoomLens.bind('mousemove', function(e){      
						//make sure on orientation change the setposition is not fired
						if(self.lastX !== e.clientX || self.lastY !== e.clientY){
							self.setPosition(e);
							self.currentLoc = e;
						}   
						self.lastX = e.clientX;
						self.lastY = e.clientY;    
					});
				}
				if(self.options.tint && self.options.zoomType != "inner") {
					self.zoomTint.bind('mousemove', function(e){ 
						//make sure on orientation change the setposition is not fired
						if(self.lastX !== e.clientX || self.lastY !== e.clientY){
							self.setPosition(e);
							self.currentLoc = e;
						}   
						self.lastX = e.clientX;
						self.lastY = e.clientY;    
					});

				}
				if(self.options.zoomType == "inner") {
					self.zoomWindow.bind('mousemove', function(e) {
						//self.overWindow = true;
						//make sure on orientation change the setposition is not fired
						if(self.lastX !== e.clientX || self.lastY !== e.clientY){
							self.setPosition(e);
							self.currentLoc = e;
						}   
						self.lastX = e.clientX;
						self.lastY = e.clientY;    
					});

				}

				//  lensFadeOut: 500,  zoomTintFadeIn
				self.zoomContainer.add(self.$elem).mouseenter(function(){

					if(self.overWindow == false){self.setElements("show");} 


				}).mouseleave(function(){
					if(!self.scrollLock){
						self.setElements("hide");
					}
				});
				//end ove image

				if(self.options.zoomType != "inner") {
					self.zoomWindow.mouseenter(function(){
						self.overWindow = true;   
						self.setElements("hide");                  
					}).mouseleave(function(){

						self.overWindow = false;
					});
				}
				//end ove image


                //	var delta = parseInt(e.originalEvent.wheelDelta || -e.originalEvent.detail);

				//  $(this).empty();    
				//  return false;

				//fix for initial zoom setting
				if (self.options.zoomLevel != 1){
					//	self.changeZoomLevel(self.currentZoomLevel);
				}
				//set the min zoomlevel
				if(self.options.minZoomLevel){
					self.minZoomLevel = self.options.minZoomLevel;
				}
				else{
					self.minZoomLevel = self.options.scrollZoomIncrement * 2;
				}


				if(self.options.scrollZoom){


					self.zoomContainer.add(self.$elem).bind('mousewheel DOMMouseScroll MozMousePixelScroll', function(e){


//						in IE there is issue with firing of mouseleave - So check whether still scrolling
//						and on mouseleave check if scrolllock          
						self.scrollLock = true;
						clearTimeout($.data(this, 'timer'));
						$.data(this, 'timer', setTimeout(function() {
							self.scrollLock = false;
							//do something
						}, 250));

						var theEvent = e.originalEvent.wheelDelta || e.originalEvent.detail*-1


						//this.scrollTop += ( delta < 0 ? 1 : -1 ) * 30;
						//   e.preventDefault();


						e.stopImmediatePropagation();
						e.stopPropagation();
						e.preventDefault();


						if(theEvent /120 > 0) {
							//scrolling up
							if(self.currentZoomLevel >= self.minZoomLevel){ 
								self.changeZoomLevel(self.currentZoomLevel-self.options.scrollZoomIncrement);        
							}

						}
						else{
							//scrolling down


							if(self.options.maxZoomLevel){
								if(self.currentZoomLevel <= self.options.maxZoomLevel){           
									self.changeZoomLevel(parseFloat(self.currentZoomLevel)+self.options.scrollZoomIncrement);
								}
							}
							else{
								//andy 

								self.changeZoomLevel(parseFloat(self.currentZoomLevel)+self.options.scrollZoomIncrement);
							}

						}
						return false;
					});
				}


			},
			setElements: function(type) {
				var self = this;
        if(!self.options.zoomEnabled){return false;}
				if(type=="show"){
					if(self.isWindowSet){
						if(self.options.zoomType == "inner") {self.showHideWindow("show");}
						if(self.options.zoomType == "window") {self.showHideWindow("show");}
						if(self.options.showLens) {self.showHideLens("show");}
						if(self.options.tint && self.options.zoomType != "inner") {self.showHideTint("show");
						}
					}
				}

				if(type=="hide"){
					if(self.options.zoomType == "window") {self.showHideWindow("hide");}
					if(!self.options.tint) {self.showHideWindow("hide");}
					if(self.options.showLens) {self.showHideLens("hide");}
					if(self.options.tint) {	self.showHideTint("hide");}
				}   
			},
			setPosition: function(e) {
      
				var self = this;
        
        if(!self.options.zoomEnabled){return false;}

				//recaclc offset each time in case the image moves
				//this can be caused by other on page elements
				self.nzHeight = self.$elem.height();
				self.nzWidth = self.$elem.width();
				self.nzOffset = self.$elem.offset();
                self.ctOffset = self.$container.offset();

				if(self.options.tint && self.options.zoomType != "inner") {
					self.zoomTint.css({ top: 0});
					self.zoomTint.css({ left: 0});
				}
				//set responsive       
				//will checking if the image needs changing before running this code work faster?
				if(self.options.responsive && !self.options.scrollZoom){
					if(self.options.showLens){ 
						if(self.nzHeight < self.options.zoomWindowWidth/self.widthRatio){
							lensHeight = self.nzHeight;              
						}
						else{
							lensHeight = String((self.options.zoomWindowHeight/self.heightRatio))
						}
						if(self.largeWidth < self.options.zoomWindowWidth){
							lensWidth = self.nzWidth;
						}       
						else{
							lensWidth =  (self.options.zoomWindowWidth/self.widthRatio);
						}
						self.widthRatio = self.largeWidth / self.nzWidth;
						self.heightRatio = self.largeHeight / self.nzHeight;        
						if(self.options.zoomType != "lens") {


							//possibly dont need to keep recalcalculating
							//if the lens is heigher than the image, then set lens size to image size
							if(self.nzHeight < self.options.zoomWindowWidth/self.widthRatio){
								lensHeight = self.nzHeight;  

							}
							else{
								lensHeight = String((self.options.zoomWindowHeight/self.heightRatio))
							}

							if(self.options.zoomWindowWidth < self.options.zoomWindowWidth){
								lensWidth = self.nzWidth;
							}       
							else{
								lensWidth =  (self.options.zoomWindowWidth/self.widthRatio);
							}            

							self.zoomLens.css('width', lensWidth);    
							self.zoomLens.css('height', lensHeight); 

							if(self.options.tint){    
								self.zoomTintImage.css('width', self.nzWidth);    
								self.zoomTintImage.css('height', self.nzHeight); 
							}

						}                     
						if(self.options.zoomType == "lens") {  

							self.zoomLens.css({ width: String(self.options.lensSize) + 'px', height: String(self.options.lensSize) + 'px' })      


						}        
						//end responsive image change
					}
				}

				//container fix
				self.zoomContainer.css({ top: self.nzOffset.top - self.ctOffset.top});
				self.zoomContainer.css({ left: self.nzOffset.left - self.ctOffset.left});
				self.mouseLeft = parseInt(e.pageX - self.nzOffset.left);
				self.mouseTop = parseInt(e.pageY - self.nzOffset.top);
				//calculate the Location of the Lens

				//calculate the bound regions - but only if zoom window
				if(self.options.zoomType == "window") {
					self.Etoppos = (self.mouseTop < (self.zoomLens.height()/2));
					self.Eboppos = (self.mouseTop > self.nzHeight - (self.zoomLens.height()/2)-(self.options.lensBorderSize*2));
					self.Eloppos = (self.mouseLeft < 0+((self.zoomLens.width()/2))); 
					self.Eroppos = (self.mouseLeft > (self.nzWidth - (self.zoomLens.width()/2)-(self.options.lensBorderSize*2)));  
				}
				//calculate the bound regions - but only for inner zoom
				if(self.options.zoomType == "inner"){ 
					self.Etoppos = (self.mouseTop < ((self.nzHeight/2)/self.heightRatio) );
					self.Eboppos = (self.mouseTop > (self.nzHeight - ((self.nzHeight/2)/self.heightRatio)));
					self.Eloppos = (self.mouseLeft < 0+(((self.nzWidth/2)/self.widthRatio)));
					self.Eroppos = (self.mouseLeft > (self.nzWidth - (self.nzWidth/2)/self.widthRatio-(self.options.lensBorderSize*2)));  
				}

				// if the mouse position of the slider is one of the outerbounds, then hide  window and lens
				if (self.mouseLeft <= 0 || self.mouseTop < 0 || self.mouseLeft > self.nzWidth || self.mouseTop > self.nzHeight ) {				          
					self.setElements("hide");
					return;
				}
				//else continue with operations
				else {


					//lens options
					if(self.options.showLens) {
						//		self.showHideLens("show");
						//set background position of lens
						self.lensLeftPos = String(self.mouseLeft - self.zoomLens.width() / 2);
						self.lensTopPos = String(self.mouseTop - self.zoomLens.height() / 2);


					}
					//adjust the background position if the mouse is in one of the outer regions 

					//Top region
					if(self.Etoppos){
						self.lensTopPos = 0;
					}
					//Left Region
					if(self.Eloppos){
						self.windowLeftPos = 0;
						self.lensLeftPos = 0;
						self.tintpos=0;
					}     
					//Set bottom and right region for window mode
					if(self.options.zoomType == "window") {
						if(self.Eboppos){
							self.lensTopPos = Math.max( (self.nzHeight)-self.zoomLens.height()-(self.options.lensBorderSize*2), 0 );
						} 
						if(self.Eroppos){
							self.lensLeftPos = (self.nzWidth-(self.zoomLens.width())-(self.options.lensBorderSize*2));
						}  
					}  
					//Set bottom and right region for inner mode
					if(self.options.zoomType == "inner") {
						if(self.Eboppos){
							self.lensTopPos = Math.max( ((self.nzHeight)-(self.options.lensBorderSize*2)), 0 );
						} 
						if(self.Eroppos){
							self.lensLeftPos = (self.nzWidth-(self.nzWidth)-(self.options.lensBorderSize*2));
						}  

					}
					//if lens zoom
					if(self.options.zoomType == "lens") {  
						self.windowLeftPos = String(((e.pageX - self.nzOffset.left) * self.widthRatio - self.zoomLens.width() / 2) * (-1));   
						self.windowTopPos = String(((e.pageY - self.nzOffset.top) * self.heightRatio - self.zoomLens.height() / 2) * (-1));

						self.zoomLens.css({ backgroundPosition: self.windowLeftPos + 'px ' + self.windowTopPos + 'px' });

						if(self.changeBgSize){  

							if(self.nzHeight>self.nzWidth){  
								if(self.options.zoomType == "lens"){       
									self.zoomLens.css({ "background-size": self.largeWidth/self.newvalueheight + 'px ' + self.largeHeight/self.newvalueheight + 'px' });
								}   

								self.zoomWindow.css({ "background-size": self.largeWidth/self.newvalueheight + 'px ' + self.largeHeight/self.newvalueheight + 'px' });
							}
							else{     
								if(self.options.zoomType == "lens"){       
									self.zoomLens.css({ "background-size": self.largeWidth/self.newvaluewidth + 'px ' + self.largeHeight/self.newvaluewidth + 'px' });
								}   
								self.zoomWindow.css({ "background-size": self.largeWidth/self.newvaluewidth + 'px ' + self.largeHeight/self.newvaluewidth + 'px' });            
							}
							self.changeBgSize = false;
						}    

						self.setWindowPostition(e);  
					}
					//if tint zoom   
					if(self.options.tint && self.options.zoomType != "inner") {
						self.setTintPosition(e);

					}
					//set the css background position 
					if(self.options.zoomType == "window") {
						self.setWindowPostition(e);   
					}
					if(self.options.zoomType == "inner") {
						self.setWindowPostition(e);   
					}
					if(self.options.showLens) {

						if(self.fullwidth && self.options.zoomType != "lens"){
							self.lensLeftPos = 0;

						}
						self.zoomLens.css({ left: self.lensLeftPos + 'px', top: self.lensTopPos + 'px' })  
					}

				} //end else



			},
			showHideWindow: function(change) {
				var self = this;              
				if(change == "show"){      
					if(!self.isWindowActive){
						if(self.options.zoomWindowFadeIn){
							self.zoomWindow.stop(true, true, false).fadeIn(self.options.zoomWindowFadeIn);
						}
						else{self.zoomWindow.show();}
						self.isWindowActive = true;
					}            
				}
				if(change == "hide"){
					if(self.isWindowActive){
						if(self.options.zoomWindowFadeOut){
							self.zoomWindow.stop(true, true).fadeOut(self.options.zoomWindowFadeOut);
						}
						else{self.zoomWindow.hide();}
						self.isWindowActive = false;        
					}      
				}
			},
			showHideLens: function(change) {
				var self = this;              
				if(change == "show"){      
					if(!self.isLensActive){
						if(self.options.lensFadeIn){
							self.zoomLens.stop(true, true, false).fadeIn(self.options.lensFadeIn);
						}
						else{self.zoomLens.show();}
						self.isLensActive = true;
					}            
				}
				if(change == "hide"){
					if(self.isLensActive){
						if(self.options.lensFadeOut){
							self.zoomLens.stop(true, true).fadeOut(self.options.lensFadeOut);
						}
						else{self.zoomLens.hide();}
						self.isLensActive = false;        
					}      
				}
			},
			showHideTint: function(change) {
				var self = this;              
				if(change == "show"){      
					if(!self.isTintActive){

						if(self.options.zoomTintFadeIn){
							self.zoomTint.css({opacity:self.options.tintOpacity}).animate().stop(true, true).fadeIn("slow");
						}
						else{
							self.zoomTint.css({opacity:self.options.tintOpacity}).animate();
							self.zoomTint.show();


						}
						self.isTintActive = true;
					}            
				}
				if(change == "hide"){      
					if(self.isTintActive){ 

						if(self.options.zoomTintFadeOut){
							self.zoomTint.stop(true, true).fadeOut(self.options.zoomTintFadeOut);
						}
						else{self.zoomTint.hide();}
						self.isTintActive = false;        
					}      
				}
			},
			setLensPostition: function( e ) {


			},
			setWindowPostition: function( e ) {
				//return obj.slice( 0, count );
				var self = this;

				if(!isNaN(self.options.zoomWindowPosition)){

					switch (self.options.zoomWindowPosition) { 
					case 1: //done         
						self.windowOffsetTop = (self.options.zoomWindowOffety);//DONE - 1
						self.windowOffsetLeft =(+self.nzWidth); //DONE 1, 2, 3, 4, 16
						break;
					case 2:
						if(self.options.zoomWindowHeight > self.nzHeight){ //positive margin

							self.windowOffsetTop = ((self.options.zoomWindowHeight/2)-(self.nzHeight/2))*(-1);
							self.windowOffsetLeft =(self.nzWidth); //DONE 1, 2, 3, 4, 16
						}
						else{ //negative margin

						}
						break;
					case 3: //done        
						self.windowOffsetTop = (self.nzHeight - self.zoomWindow.height() - (self.options.borderSize*2)); //DONE 3,9
						self.windowOffsetLeft =(self.nzWidth); //DONE 1, 2, 3, 4, 16
						break;      
					case 4: //done  
						self.windowOffsetTop = (self.nzHeight); //DONE - 4,5,6,7,8
						self.windowOffsetLeft =(self.nzWidth); //DONE 1, 2, 3, 4, 16
						break;
					case 5: //done  
						self.windowOffsetTop = (self.nzHeight); //DONE - 4,5,6,7,8
						self.windowOffsetLeft =(self.nzWidth-self.zoomWindow.width()-(self.options.borderSize*2)); //DONE - 5,15
						break;
					case 6: 
						if(self.options.zoomWindowHeight > self.nzHeight){ //positive margin
							self.windowOffsetTop = (self.nzHeight);  //DONE - 4,5,6,7,8

							self.windowOffsetLeft =((self.options.zoomWindowWidth/2)-(self.nzWidth/2)+(self.options.borderSize*2))*(-1);  
						}
						else{ //negative margin

						}


						break;
					case 7: //done  
						self.windowOffsetTop = (self.nzHeight);  //DONE - 4,5,6,7,8
						self.windowOffsetLeft = 0; //DONE 7, 13
						break;
					case 8: //done  
						self.windowOffsetTop = (self.nzHeight); //DONE - 4,5,6,7,8
						self.windowOffsetLeft =(self.zoomWindow.width()+(self.options.borderSize*2) )* (-1);  //DONE 8,9,10,11,12
						break;
					case 9:  //done  
						self.windowOffsetTop = (self.nzHeight - self.zoomWindow.height() - (self.options.borderSize*2)); //DONE 3,9
						self.windowOffsetLeft =(self.zoomWindow.width()+(self.options.borderSize*2) )* (-1);  //DONE 8,9,10,11,12
						break;
					case 10: 
						if(self.options.zoomWindowHeight > self.nzHeight){ //positive margin

							self.windowOffsetTop = ((self.options.zoomWindowHeight/2)-(self.nzHeight/2))*(-1);
							self.windowOffsetLeft =(self.zoomWindow.width()+(self.options.borderSize*2) )* (-1);  //DONE 8,9,10,11,12
						}
						else{ //negative margin

						}
						break;
					case 11: 
						self.windowOffsetTop = (self.options.zoomWindowOffety);
						self.windowOffsetLeft =(self.zoomWindow.width()+(self.options.borderSize*2) )* (-1);  //DONE 8,9,10,11,12
						break;
					case 12: //done  
						self.windowOffsetTop = (self.zoomWindow.height()+(self.options.borderSize*2))*(-1); //DONE 12,13,14,15,16
						self.windowOffsetLeft =(self.zoomWindow.width()+(self.options.borderSize*2) )* (-1);  //DONE 8,9,10,11,12
						break;
					case 13: //done  
						self.windowOffsetTop = (self.zoomWindow.height()+(self.options.borderSize*2))*(-1); //DONE 12,13,14,15,16
						self.windowOffsetLeft =(0); //DONE 7, 13
						break;
					case 14: 
						if(self.options.zoomWindowHeight > self.nzHeight){ //positive margin
							self.windowOffsetTop = (self.zoomWindow.height()+(self.options.borderSize*2))*(-1); //DONE 12,13,14,15,16

							self.windowOffsetLeft =((self.options.zoomWindowWidth/2)-(self.nzWidth/2)+(self.options.borderSize*2))*(-1);  
						}
						else{ //negative margin

						}

						break;
					case 15://done   
						self.windowOffsetTop = (self.zoomWindow.height()+(self.options.borderSize*2))*(-1); //DONE 12,13,14,15,16
						self.windowOffsetLeft =(self.nzWidth-self.zoomWindow.width()-(self.options.borderSize*2)); //DONE - 5,15
						break;
					case 16:  //done  
						self.windowOffsetTop = (self.zoomWindow.height()+(self.options.borderSize*2))*(-1); //DONE 12,13,14,15,16
						self.windowOffsetLeft =(self.nzWidth); //DONE 1, 2, 3, 4, 16
						break;            
					default: //done  
						self.windowOffsetTop = (self.options.zoomWindowOffety);//DONE - 1
					self.windowOffsetLeft =(self.nzWidth); //DONE 1, 2, 3, 4, 16
					} 
				} //end isNAN
				else{
					//WE CAN POSITION IN A CLASS - ASSUME THAT ANY STRING PASSED IS
					self.externalContainer = $('#'+self.options.zoomWindowPosition);
					self.externalContainerWidth = self.externalContainer.width();
					self.externalContainerHeight = self.externalContainer.height();
					self.externalContainerOffset = self.externalContainer.offset();

					self.windowOffsetTop = self.externalContainerOffset.top;//DONE - 1
					self.windowOffsetLeft =self.externalContainerOffset.left; //DONE 1, 2, 3, 4, 16

				}
				self.isWindowSet = true;
				self.windowOffsetTop = self.windowOffsetTop + self.options.zoomWindowOffety;
				self.windowOffsetLeft = self.windowOffsetLeft + self.options.zoomWindowOffetx;

				self.zoomWindow.css({ top: self.windowOffsetTop});
				self.zoomWindow.css({ left: self.windowOffsetLeft});

				if(self.options.zoomType == "inner") {
					self.zoomWindow.css({ top: 0});
					self.zoomWindow.css({ left: 0});

				}   


				self.windowLeftPos = String(((e.pageX - self.nzOffset.left) * self.widthRatio - self.zoomWindow.width() / 2) * (-1));   
				self.windowTopPos = String(((e.pageY - self.nzOffset.top) * self.heightRatio - self.zoomWindow.height() / 2) * (-1));
				if(self.Etoppos){self.windowTopPos = 0;}
				if(self.Eloppos){self.windowLeftPos = 0;}     
				if(self.Eboppos){self.windowTopPos = (self.largeHeight/self.currentZoomLevel-self.zoomWindow.height())*(-1);  } 
				if(self.Eroppos){self.windowLeftPos = ((self.largeWidth/self.currentZoomLevel-self.zoomWindow.width())*(-1));}    

				//stops micro movements
				if(self.fullheight){
					self.windowTopPos = 0;

				}
				if(self.fullwidth){
					self.windowLeftPos = 0;

				}
				//set the css background position 


				if(self.options.zoomType == "window" || self.options.zoomType == "inner") {

					if(self.zoomLock == 1){
						//overrides for images not zoomable
						if(self.widthRatio <= 1){

							self.windowLeftPos = 0;
						}
						if(self.heightRatio <= 1){ 
							self.windowTopPos = 0;
						}
					}
					// adjust images less than the window height

					if(self.largeHeight < self.options.zoomWindowHeight){

						self.windowTopPos = 0;
					}
					if(self.largeWidth < self.options.zoomWindowWidth){
						self.windowLeftPos = 0;
					}       

					//set the zoomwindow background position
					if (self.options.easing){

						//     if(self.changeZoom){
						//           clearInterval(self.loop);
						//           self.changeZoom = false;
						//           self.loop = false;

						//            }
						//set the pos to 0 if not set
						if(!self.xp){self.xp = 0;}
						if(!self.yp){self.yp = 0;}  
						//if loop not already started, then run it 
						if (!self.loop){           
							self.loop = setInterval(function(){                
								//using zeno's paradox    

								self.xp += (self.windowLeftPos  - self.xp) / self.options.easingAmount; 
								self.yp += (self.windowTopPos  - self.yp) / self.options.easingAmount;
								if(self.scrollingLock){


									clearInterval(self.loop);
									self.xp = self.windowLeftPos;
									self.yp = self.windowTopPos            

									self.xp = ((e.pageX - self.nzOffset.left) * self.widthRatio - self.zoomWindow.width() / 2) * (-1);
									self.yp = (((e.pageY - self.nzOffset.top) * self.heightRatio - self.zoomWindow.height() / 2) * (-1));                         

									if(self.changeBgSize){    
										if(self.nzHeight>self.nzWidth){  
											if(self.options.zoomType == "lens"){      
												self.zoomLens.css({ "background-size": self.largeWidth/self.newvalueheight + 'px ' + self.largeHeight/self.newvalueheight + 'px' });
											}   
											self.zoomWindow.css({ "background-size": self.largeWidth/self.newvalueheight + 'px ' + self.largeHeight/self.newvalueheight + 'px' });
										}
										else{   
											if(self.options.zoomType != "lens"){      
												self.zoomLens.css({ "background-size": self.largeWidth/self.newvaluewidth + 'px ' + self.largeHeight/self.newvalueheight + 'px' });
											}            
											self.zoomWindow.css({ "background-size": self.largeWidth/self.newvaluewidth + 'px ' + self.largeHeight/self.newvaluewidth + 'px' });            

										}

										/*
             if(!self.bgxp){self.bgxp = self.largeWidth/self.newvalue;}
						if(!self.bgyp){self.bgyp = self.largeHeight/self.newvalue ;}  
                 if (!self.bgloop){   
                 	self.bgloop = setInterval(function(){   

                 self.bgxp += (self.largeWidth/self.newvalue  - self.bgxp) / self.options.easingAmount; 
								self.bgyp += (self.largeHeight/self.newvalue  - self.bgyp) / self.options.easingAmount;

           self.zoomWindow.css({ "background-size": self.bgxp + 'px ' + self.bgyp + 'px' });


                  }, 16);

                 }
										 */
										self.changeBgSize = false;
									}

									self.zoomWindow.css({ backgroundPosition: self.windowLeftPos + 'px ' + self.windowTopPos + 'px' });
									self.scrollingLock = false;
									self.loop = false;

								}
								else{
									if(self.changeBgSize){    
										if(self.nzHeight>self.nzWidth){ 
											if(self.options.zoomType == "lens"){      
												self.zoomLens.css({ "background-size": self.largeWidth/self.newvalueheight + 'px ' + self.largeHeight/self.newvalueheight + 'px' });
											}         
											self.zoomWindow.css({ "background-size": self.largeWidth/self.newvalueheight + 'px ' + self.largeHeight/self.newvalueheight + 'px' });
										}
										else{                 
											if(self.options.zoomType != "lens"){     
												self.zoomLens.css({ "background-size": self.largeWidth/self.newvaluewidth + 'px ' + self.largeHeight/self.newvaluewidth + 'px' });
											}      
											self.zoomWindow.css({ "background-size": self.largeWidth/self.newvaluewidth + 'px ' + self.largeHeight/self.newvaluewidth + 'px' });            
										}
										self.changeBgSize = false;
									}                   

									self.zoomWindow.css({ backgroundPosition: self.xp + 'px ' + self.yp + 'px' });
								}       
							}, 16);
						}
					}   
					else{    
						if(self.changeBgSize){  
							if(self.nzHeight>self.nzWidth){  
								if(self.options.zoomType == "lens"){      
									self.zoomLens.css({ "background-size": self.largeWidth/self.newvalueheight + 'px ' + self.largeHeight/self.newvalueheight + 'px' });
								} 

								self.zoomWindow.css({ "background-size": self.largeWidth/self.newvalueheight + 'px ' + self.largeHeight/self.newvalueheight + 'px' });
							}
							else{     
								if(self.options.zoomType == "lens"){      
									self.zoomLens.css({ "background-size": self.largeWidth/self.newvaluewidth + 'px ' + self.largeHeight/self.newvaluewidth + 'px' });
								} 
								if((self.largeHeight/self.newvaluewidth) < self.options.zoomWindowHeight){ 

									self.zoomWindow.css({ "background-size": self.largeWidth/self.newvaluewidth + 'px ' + self.largeHeight/self.newvaluewidth + 'px' });            
								}
								else{

									self.zoomWindow.css({ "background-size": self.largeWidth/self.newvalueheight + 'px ' + self.largeHeight/self.newvalueheight + 'px' });   
								}

							}
							self.changeBgSize = false;
						}     

						self.zoomWindow.css({ backgroundPosition: self.windowLeftPos + 'px ' + self.windowTopPos + 'px' });       
					}
				} 
			},
			setTintPosition: function(e){
				var self = this;
				self.nzOffset = self.$elem.offset();
				self.tintpos = String(((e.pageX - self.nzOffset.left)-(self.zoomLens.width() / 2)) * (-1)); 
				self.tintposy = String(((e.pageY - self.nzOffset.top) - self.zoomLens.height() / 2) * (-1));	
				if(self.Etoppos){
					self.tintposy = 0;
				}
				if(self.Eloppos){
					self.tintpos=0;
				}     
				if(self.Eboppos){
					self.tintposy = (self.nzHeight-self.zoomLens.height()-(self.options.lensBorderSize*2))*(-1);
				} 
				if(self.Eroppos){
					self.tintpos = ((self.nzWidth-self.zoomLens.width()-(self.options.lensBorderSize*2))*(-1));
				}    
				if(self.options.tint) {
					//stops micro movements
					if(self.fullheight){
						self.tintposy = 0;

					}
					if(self.fullwidth){ 
						self.tintpos = 0;

					}   
					self.zoomTintImage.css({'left': self.tintpos+'px'});
					self.zoomTintImage.css({'top': self.tintposy+'px'});
				}
			},

			swaptheimage: function(smallimage, largeimage){
				var self = this;
				var newImg = new Image(); 

				if(self.options.loadingIcon){
					self.spinner = $('<div style="background: url(\''+self.options.loadingIcon+'\') no-repeat center;height:'+self.nzHeight+'px;width:'+self.nzWidth+'px;z-index: 2000;position: absolute; background-position: center center;"></div>');
					self.$elem.after(self.spinner);
				}

				self.options.onImageSwap(self.$elem);

				newImg.onload = function() {
					self.largeWidth = newImg.width;
					self.largeHeight = newImg.height;
					self.zoomImage = largeimage;
                    if (typeof self.zoomWindow == 'undefined') return;
					self.zoomWindow.css({ "background-size": self.largeWidth + 'px ' + self.largeHeight + 'px' });
					self.zoomWindow.css({ "background-size": self.largeWidth + 'px ' + self.largeHeight + 'px' });


					self.swapAction(smallimage, largeimage);
					return;              
				}          
				newImg.src = largeimage; // this must be done AFTER setting onload

			},
			swapAction: function(smallimage, largeimage){


				var self = this;    

				var newImg2 = new Image(); 
				newImg2.onload = function() {
					//re-calculate values
					self.nzHeight = newImg2.height;
					self.nzWidth = newImg2.width;
					self.options.onImageSwapComplete(self.$elem);

					self.doneCallback();  
					return;      
				}          
				newImg2.src = smallimage; 

				//reset the zoomlevel to that initially set in options
				self.currentZoomLevel = self.options.zoomLevel;
				self.options.maxZoomLevel = false;

				//swaps the main image
				//self.$elem.attr("src",smallimage);
				//swaps the zoom image     
				if(self.options.zoomType == "lens") {
					self.zoomLens.css({ backgroundImage: "url('" + largeimage + "')" }); 
				}
				if(self.options.zoomType == "window") {
					self.zoomWindow.css({ backgroundImage: "url('" + largeimage + "')" }); 
				}
				if(self.options.zoomType == "inner") {
					self.zoomWindow.css({ backgroundImage: "url('" + largeimage + "')" }); 
				} 



				self.currentImage = largeimage;

				if(self.options.imageCrossfade){
					var oldImg = self.$elem;
					var newImg = oldImg.clone();         
					self.$elem.attr("src",smallimage)
					self.$elem.after(newImg);
					newImg.stop(true).fadeOut(self.options.imageCrossfade, function() {
						$(this).remove();         
					});

					//       				if(self.options.zoomType == "inner"){
					//remove any attributes on the cloned image so we can resize later
					self.$elem.width("auto").removeAttr("width");
					self.$elem.height("auto").removeAttr("height");
					//   }

					oldImg.fadeIn(self.options.imageCrossfade);

					if(self.options.tint && self.options.zoomType != "inner") {

						var oldImgTint = self.zoomTintImage;
						var newImgTint = oldImgTint.clone();         
						self.zoomTintImage.attr("src",largeimage)
						self.zoomTintImage.after(newImgTint);
						newImgTint.stop(true).fadeOut(self.options.imageCrossfade, function() {
							$(this).remove();         
						});



						oldImgTint.fadeIn(self.options.imageCrossfade);


						//self.zoomTintImage.attr("width",elem.data("image"));

						//resize the tint window
						self.zoomTint.css({ height: self.$elem.height()});
						self.zoomTint.css({ width: self.$elem.width()});
					}    

					self.zoomContainer.css("height", self.$elem.height());
					self.zoomContainer.css("width", self.$elem.width());

					if(self.options.zoomType == "inner"){ 
						if(!self.options.constrainType){
							self.zoomWrap.parent().css("height", self.$elem.height());
							self.zoomWrap.parent().css("width", self.$elem.width());

							self.zoomWindow.css("height", self.$elem.height());
							self.zoomWindow.css("width", self.$elem.width());
						}
					} 

					if(self.options.imageCrossfade){  
						self.zoomWrap.css("height", self.$elem.height());
						self.zoomWrap.css("width", self.$elem.width());
					} 
				}
				else{
					self.$elem.attr("src",smallimage); 
					if(self.options.tint) {
						self.zoomTintImage.attr("src",largeimage);
						//self.zoomTintImage.attr("width",elem.data("image"));
						self.zoomTintImage.attr("height",self.$elem.height());
						//self.zoomTintImage.attr('src') = elem.data("image");
						self.zoomTintImage.css({ height: self.$elem.height()}); 
						self.zoomTint.css({ height: self.$elem.height()});

					}
					self.zoomContainer.css("height", self.$elem.height());
					self.zoomContainer.css("width", self.$elem.width());

					if(self.options.imageCrossfade){  
						self.zoomWrap.css("height", self.$elem.height());
						self.zoomWrap.css("width", self.$elem.width());
					} 
				}              
				if(self.options.constrainType){     

					//This will contrain the image proportions
					if(self.options.constrainType == "height"){ 

						self.zoomContainer.css("height", self.options.constrainSize);
						self.zoomContainer.css("width", "auto");

						if(self.options.imageCrossfade){  
							self.zoomWrap.css("height", self.options.constrainSize);
							self.zoomWrap.css("width", "auto"); 
							self.constwidth = self.zoomWrap.width();


						}
						else{                  
							self.$elem.css("height", self.options.constrainSize);
							self.$elem.css("width", "auto");
							self.constwidth = self.$elem.width();
						} 

						if(self.options.zoomType == "inner"){

							self.zoomWrap.parent().css("height", self.options.constrainSize);
							self.zoomWrap.parent().css("width", self.constwidth);   
							self.zoomWindow.css("height", self.options.constrainSize);
							self.zoomWindow.css("width", self.constwidth);    
						}        
						if(self.options.tint){
							self.tintContainer.css("height", self.options.constrainSize);
							self.tintContainer.css("width", self.constwidth);
							self.zoomTint.css("height", self.options.constrainSize);
							self.zoomTint.css("width", self.constwidth);
							self.zoomTintImage.css("height", self.options.constrainSize);
							self.zoomTintImage.css("width", self.constwidth); 
						} 

					}
					if(self.options.constrainType == "width"){       
						self.zoomContainer.css("height", "auto");
						self.zoomContainer.css("width", self.options.constrainSize);

						if(self.options.imageCrossfade){
							self.zoomWrap.css("height", "auto");
							self.zoomWrap.css("width", self.options.constrainSize);
							self.constheight = self.zoomWrap.height();
						}
						else{            
							self.$elem.css("height", "auto");
							self.$elem.css("width", self.options.constrainSize); 
							self.constheight = self.$elem.height();              
						} 
						if(self.options.zoomType == "inner"){
							self.zoomWrap.parent().css("height", self.constheight);
							self.zoomWrap.parent().css("width", self.options.constrainSize);   
							self.zoomWindow.css("height", self.constheight);
							self.zoomWindow.css("width", self.options.constrainSize);    
						} 
						if(self.options.tint){
							self.tintContainer.css("height", self.constheight);
							self.tintContainer.css("width", self.options.constrainSize);
							self.zoomTint.css("height", self.constheight);
							self.zoomTint.css("width", self.options.constrainSize);
							self.zoomTintImage.css("height", self.constheight);
							self.zoomTintImage.css("width", self.options.constrainSize); 
						}   

					}        


				}

			},
			doneCallback: function(){

				var self = this;
				if(self.options.loadingIcon){
					self.spinner.hide();     
				}   

				self.nzOffset = self.$elem.offset();
				self.nzWidth = self.$elem.width();
				self.nzHeight = self.$elem.height();

				// reset the zoomlevel back to default
				self.currentZoomLevel = self.options.zoomLevel;

				//ratio of the large to small image
				self.widthRatio = self.largeWidth / self.nzWidth;
				self.heightRatio = self.largeHeight / self.nzHeight; 

				//NEED TO ADD THE LENS SIZE FOR ROUND
				// adjust images less than the window height
				if(self.options.zoomType == "window") {

					if(self.nzHeight < self.options.zoomWindowWidth/self.widthRatio){
						lensHeight = self.nzHeight;  

					}
					else{
						lensHeight = String((self.options.zoomWindowHeight/self.heightRatio))
					}

					if(self.options.zoomWindowWidth < self.options.zoomWindowWidth){
						lensWidth = self.nzWidth;
					}       
					else{
						lensWidth =  (self.options.zoomWindowWidth/self.widthRatio);
					}


					if(self.zoomLens){

						self.zoomLens.css('width', lensWidth);    
						self.zoomLens.css('height', lensHeight); 


					}
				}
			},
			getCurrentImage: function(){
				var self = this;  
				return self.zoomImage; 
			}, 
			getGalleryList: function(){
				var self = this;   
				//loop through the gallery options and set them in list for fancybox
				self.gallerylist = [];
				if (self.options.gallery){ 


					$('#'+self.options.gallery + ' a').each(function() {

						var img_src = '';
						if($(this).data("zoom-image")){
							img_src = $(this).data("zoom-image");
						}
						else if($(this).data("image")){
							img_src = $(this).data("image");
						}			
						//put the current image at the start
						if(img_src == self.zoomImage){
							self.gallerylist.unshift({
								href: ''+img_src+'',
								title: $(this).find('img').attr("title")
							});	
						}
						else{
							self.gallerylist.push({
								href: ''+img_src+'',
								title: $(this).find('img').attr("title")
							});
						}


					});
				}                                                       
				//if no gallery - return current image
				else{
					self.gallerylist.push({
						href: ''+self.zoomImage+'',
						title: $(this).find('img').attr("title")
					}); 
				}
				return self.gallerylist;

			},
			changeZoomLevel: function(value){
				var self = this;   

				//flag a zoom, so can adjust the easing during setPosition     
				self.scrollingLock = true;   

				//round to two decimal places
				self.newvalue = parseFloat(value).toFixed(2);
				newvalue = parseFloat(value).toFixed(2);




				//maxwidth & Maxheight of the image
				maxheightnewvalue = self.largeHeight/((self.options.zoomWindowHeight / self.nzHeight) * self.nzHeight);     
				maxwidthtnewvalue = self.largeWidth/((self.options.zoomWindowWidth / self.nzWidth) * self.nzWidth);   	




				//calculate new heightratio
				if(self.options.zoomType != "inner")
				{
					if(maxheightnewvalue <= newvalue){
						self.heightRatio = (self.largeHeight/maxheightnewvalue) / self.nzHeight;
						self.newvalueheight = maxheightnewvalue;
						self.fullheight = true;

					}
					else{
						self.heightRatio = (self.largeHeight/newvalue) / self.nzHeight; 
						self.newvalueheight = newvalue;
						self.fullheight = false;

					}


//					calculate new width ratio

					if(maxwidthtnewvalue <= newvalue){
						self.widthRatio = (self.largeWidth/maxwidthtnewvalue) / self.nzWidth;
						self.newvaluewidth = maxwidthtnewvalue;
						self.fullwidth = true;

					}
					else{
						self.widthRatio = (self.largeWidth/newvalue) / self.nzWidth; 
						self.newvaluewidth = newvalue;
						self.fullwidth = false;

					}
					if(self.options.zoomType == "lens"){
						if(maxheightnewvalue <= newvalue){
							self.fullwidth = true;
							self.newvaluewidth = maxheightnewvalue;

						} else{
							self.widthRatio = (self.largeWidth/newvalue) / self.nzWidth; 
							self.newvaluewidth = newvalue;

							self.fullwidth = false;
						}}
				}



				if(self.options.zoomType == "inner")
				{
					maxheightnewvalue = parseFloat(self.largeHeight/self.nzHeight).toFixed(2);     
					maxwidthtnewvalue = parseFloat(self.largeWidth/self.nzWidth).toFixed(2);      
					if(newvalue > maxheightnewvalue){
						newvalue = maxheightnewvalue;
					}
					if(newvalue > maxwidthtnewvalue){
						newvalue = maxwidthtnewvalue;
					}      


					if(maxheightnewvalue <= newvalue){


						self.heightRatio = (self.largeHeight/newvalue) / self.nzHeight; 
						if(newvalue > maxheightnewvalue){
							self.newvalueheight = maxheightnewvalue;
						}else{
							self.newvalueheight = newvalue;
						}
						self.fullheight = true;


					}
					else{



						self.heightRatio = (self.largeHeight/newvalue) / self.nzHeight; 

						if(newvalue > maxheightnewvalue){

							self.newvalueheight = maxheightnewvalue;
						}else{
							self.newvalueheight = newvalue;
						}
						self.fullheight = false;
					}




					if(maxwidthtnewvalue <= newvalue){   

						self.widthRatio = (self.largeWidth/newvalue) / self.nzWidth; 
						if(newvalue > maxwidthtnewvalue){

							self.newvaluewidth = maxwidthtnewvalue;
						}else{
							self.newvaluewidth = newvalue;
						}

						self.fullwidth = true;


					}
					else{  

						self.widthRatio = (self.largeWidth/newvalue) / self.nzWidth; 
						self.newvaluewidth = newvalue;
						self.fullwidth = false;
					}        


				} //end inner
				scrcontinue = false;

				if(self.options.zoomType == "inner"){

					if(self.nzWidth > self.nzHeight){
						if( self.newvaluewidth <= maxwidthtnewvalue){
							scrcontinue = true;
						}
						else{

							scrcontinue = false;
							self.fullheight = true;
							self.fullwidth = true;
						}
					}
					if(self.nzHeight > self.nzWidth){     
						if( self.newvaluewidth <= maxwidthtnewvalue){
							scrcontinue = true;
						}
						else{
							scrcontinue = false;  

							self.fullheight = true;
							self.fullwidth = true;
						}
					}
				}

				if(self.options.zoomType != "inner"){
					scrcontinue = true;
				}

				if(scrcontinue){



					self.zoomLock = 0;
					self.changeZoom = true;

					//if lens height is less than image height


					if(((self.options.zoomWindowHeight)/self.heightRatio) <= self.nzHeight){


						self.currentZoomLevel = self.newvalueheight; 
						if(self.options.zoomType != "lens" && self.options.zoomType != "inner") {
							self.changeBgSize = true;

							self.zoomLens.css({height: String((self.options.zoomWindowHeight)/self.heightRatio) + 'px' }) 
						}
						if(self.options.zoomType == "lens" || self.options.zoomType == "inner") {  
							self.changeBgSize = true;  
						}	


					} 




					if((self.options.zoomWindowWidth/self.widthRatio) <= self.nzWidth){



						if(self.options.zoomType != "inner"){
							if(self.newvaluewidth > self.newvalueheight)   {
								self.currentZoomLevel = self.newvaluewidth;                 

							}
						}

						if(self.options.zoomType != "lens" && self.options.zoomType != "inner") {
							self.changeBgSize = true;

							self.zoomLens.css({width: String((self.options.zoomWindowWidth)/self.widthRatio) + 'px' })
						}
						if(self.options.zoomType == "lens" || self.options.zoomType == "inner") {  
							self.changeBgSize = true;
						}	

					}
					if(self.options.zoomType == "inner"){
						self.changeBgSize = true;  

						if(self.nzWidth > self.nzHeight){
							self.currentZoomLevel = self.newvaluewidth;
						}
						if(self.nzHeight > self.nzWidth){
							self.currentZoomLevel = self.newvaluewidth;
						}
					}

				}      //under

				//sets the boundry change, called in setWindowPos
				self.setPosition(self.currentLoc);
				//
			},
			closeAll: function(){
				if(self.zoomWindow){self.zoomWindow.hide();}
				if(self.zoomLens){self.zoomLens.hide();}
				if(self.zoomTint){self.zoomTint.hide();}
			},
			changeState: function(value){
      	var self = this;
				if(value == 'enable'){self.options.zoomEnabled = true;}
				if(value == 'disable'){self.options.zoomEnabled = false;}

			}

	};




	$.fn.elevateZoom = function( options ) {
		return this.each(function() {
			var elevate = Object.create( ElevateZoom );

			elevate.init( options, this );

			$.data( this, 'elevateZoom', elevate );

		});
	};

	$.fn.elevateZoom.options = {
			zoomActivation: "hover", // Can also be click (PLACEHOLDER FOR NEXT VERSION)
      zoomEnabled: true, //false disables zoomwindow from showing
			preloading: 1, //by default, load all the images, if 0, then only load images after activated (PLACEHOLDER FOR NEXT VERSION)
			zoomLevel: 1, //default zoom level of image
			scrollZoom: false, //allow zoom on mousewheel, true to activate
			scrollZoomIncrement: 0.1,  //steps of the scrollzoom
			minZoomLevel: false,
			maxZoomLevel: false,
			easing: false,
			easingAmount: 12,
			lensSize: 200,
			zoomWindowWidth: 400,
			zoomWindowHeight: 400,
			zoomWindowOffetx: 0,
			zoomWindowOffety: 0,
			zoomWindowPosition: 1,
			zoomWindowBgColour: "#fff",
			lensFadeIn: false,
			lensFadeOut: false,
			debug: false,
			zoomWindowFadeIn: false,
			zoomWindowFadeOut: false,
			zoomWindowAlwaysShow: false,
			zoomTintFadeIn: false,
			zoomTintFadeOut: false,
			borderSize: 4,
			showLens: true,
			borderColour: "#888",
			lensBorderSize: 1,
			lensBorderColour: "#000",
			lensShape: "square", //can be "round"
			zoomType: "window", //window is default,  also "lens" available -
			containLensZoom: false,
			lensColour: "white", //colour of the lens background
			lensOpacity: 0.4, //opacity of the lens
			lenszoom: false,
			tint: false, //enable the tinting
			tintColour: "#333", //default tint color, can be anything, red, #ccc, rgb(0,0,0)
			tintOpacity: 0.4, //opacity of the tint
			gallery: false,
			galleryActiveClass: "zoomGalleryActive",
			imageCrossfade: false,
			constrainType: false,  //width or height
			constrainSize: false,  //in pixels the dimensions you want to constrain on
			loadingIcon: false, //http://www.example.com/spinner.gif
			cursor:"default", // user should set to what they want the cursor as, if they have set a click function
			responsive:true,
			onComplete: $.noop,
			onZoomedImageLoaded: function() {},
			onImageSwap: $.noop,
			onImageSwapComplete: $.noop,
            zoomContainer: 'body' // will be body
	};

})( jQuery, window, document );

/*!

 * fancyBox - jQuery Plugin

 * version: 2.1.5 (Fri, 14 Jun 2013)

 * requires jQuery v1.6 or later

 *

 * Examples at http://fancyapps.com/fancybox/

 * License: www.fancyapps.com/fancybox/#license

 *

 * Copyright 2012 Janis Skarnelis - janis@fancyapps.com

 *

 */



;(function (window, document, $, undefined) {

    "use strict";



    var H = $("html"),

        W = $(window),

        D = $(document),

        F = $.fancybox = function () {

            F.open.apply( this, arguments );

        },

        IE =  navigator.userAgent.match(/msie/i),

        didUpdate	= null,

        isTouch		= document.createTouch !== undefined,



        isQuery	= function(obj) {

            return obj && obj.hasOwnProperty && obj instanceof $;

        },

        isString = function(str) {

            return str && $.type(str) === "string";

        },

        isPercentage = function(str) {

            return isString(str) && str.indexOf('%') > 0;

        },

        isScrollable = function(el) {

            return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight)));

        },

        getScalar = function(orig, dim) {

            var value = parseInt(orig, 10) || 0;



            if (dim && isPercentage(orig)) {

                value = F.getViewport()[ dim ] / 100 * value;

            }



            return Math.ceil(value);

        },

        getValue = function(value, dim) {

            return getScalar(value, dim) + 'px';

        };



    $.extend(F, {

        // The current version of fancyBox

        version: '2.1.5',



        defaults: {

            padding : 15,

            margin  : 20,



            width     : 800,

            height    : 600,

            minWidth  : 100,

            minHeight : 100,

            maxWidth  : 9999,

            maxHeight : 9999,

            pixelRatio: 1, // Set to 2 for retina display support



            autoSize   : true,

            autoHeight : false,

            autoWidth  : false,



            autoResize  : true,

            autoCenter  : !isTouch,

            fitToView   : true,

            aspectRatio : false,

            topRatio    : 0.5,

            leftRatio   : 0.5,



            scrolling : 'auto', // 'auto', 'yes' or 'no'

            wrapCSS   : '',



            arrows     : true,

            closeBtn   : true,

            closeClick : false,

            nextClick  : false,

            mouseWheel : true,

            autoPlay   : false,

            playSpeed  : 3000,

            preload    : 3,

            modal      : false,

            loop       : true,



            ajax  : {

                dataType : 'html',

                headers  : { 'X-fancyBox': true }

            },

            iframe : {

                scrolling : 'auto',

                preload   : true

            },

            swf : {

                wmode: 'transparent',

                allowfullscreen   : 'true',

                allowscriptaccess : 'always'

            },



            keys  : {

                next : {

                    13 : 'left', // enter

                    34 : 'up',   // page down

                    39 : 'left', // right arrow

                    40 : 'up'    // down arrow

                },

                prev : {

                    8  : 'right',  // backspace

                    33 : 'down',   // page up

                    37 : 'right',  // left arrow

                    38 : 'down'    // up arrow

                },

                close  : [27], // escape key

                play   : [32], // space - start/stop slideshow

                toggle : [70]  // letter "f" - toggle fullscreen

            },



            direction : {

                next : 'left',

                prev : 'right'

            },



            scrollOutside  : true,



            // Override some properties

            index   : 0,

            type    : null,

            href    : null,

            content : null,

            title   : null,



            // HTML templates

            tpl: {

                wrap     : '<div class="fancybox-wrap" tabIndex="-1"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>',

                image    : '<img class="fancybox-image" src="{href}" alt="" />',

                iframe   : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen' + (IE ? ' allowtransparency="true"' : '') + '></iframe>',

                error    : '<p class="fancybox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',

                closeBtn : '<a title="Close" class="fancybox-item fancybox-close" href="javascript:;"></a>',

                next     : '<a title="Next" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>',

                prev     : '<a title="Previous" class="fancybox-nav fancybox-prev" href="javascript:;"><span></span></a>',

                loading  : '<div id="fancybox-loading"><div></div></div>'

            },



            // Properties for each animation type

            // Opening fancyBox

            openEffect  : 'fade', // 'elastic', 'fade' or 'none'

            openSpeed   : 250,

            openEasing  : 'swing',

            openOpacity : true,

            openMethod  : 'zoomIn',



            // Closing fancyBox

            closeEffect  : 'fade', // 'elastic', 'fade' or 'none'

            closeSpeed   : 250,

            closeEasing  : 'swing',

            closeOpacity : true,

            closeMethod  : 'zoomOut',



            // Changing next gallery item

            nextEffect : 'elastic', // 'elastic', 'fade' or 'none'

            nextSpeed  : 250,

            nextEasing : 'swing',

            nextMethod : 'changeIn',



            // Changing previous gallery item

            prevEffect : 'elastic', // 'elastic', 'fade' or 'none'

            prevSpeed  : 250,

            prevEasing : 'swing',

            prevMethod : 'changeOut',



            // Enable default helpers

            helpers : {

                overlay : true,

                title   : true

            },



            // Callbacks

            onCancel     : $.noop, // If canceling

            beforeLoad   : $.noop, // Before loading

            afterLoad    : $.noop, // After loading

            beforeShow   : $.noop, // Before changing in current item

            afterShow    : $.noop, // After opening

            beforeChange : $.noop, // Before changing gallery item

            beforeClose  : $.noop, // Before closing

            afterClose   : $.noop  // After closing

        },



        //Current state

        group    : {}, // Selected group

        opts     : {}, // Group options

        previous : null,  // Previous element

        coming   : null,  // Element being loaded

        current  : null,  // Currently loaded element

        isActive : false, // Is activated

        isOpen   : false, // Is currently open

        isOpened : false, // Have been fully opened at least once



        wrap  : null,

        skin  : null,

        outer : null,

        inner : null,



        player : {

            timer    : null,

            isActive : false

        },



        // Loaders

        ajaxLoad   : null,

        imgPreload : null,



        // Some collections

        transitions : {},

        helpers     : {},



        /*

         *	Static methods

         */



        open: function (group, opts) {

            if (!group) {

                return;

            }



            if (!$.isPlainObject(opts)) {

                opts = {};

            }



            // Close if already active

            if (false === F.close(true)) {

                return;

            }



            // Normalize group

            if (!$.isArray(group)) {

                group = isQuery(group) ? $(group).get() : [group];

            }



            // Recheck if the type of each element is `object` and set content type (image, ajax, etc)

            $.each(group, function(i, element) {

                var obj = {},

                    href,

                    title,

                    content,

                    type,

                    rez,

                    hrefParts,

                    selector;



                if ($.type(element) === "object") {

                    // Check if is DOM element

                    if (element.nodeType) {

                        element = $(element);

                    }



                    if (isQuery(element)) {

                        obj = {

                            href    : element.data('fancybox-href') || element.attr('href'),

                            title   : $('<div/>').text( element.data('fancybox-title') || element.attr('title') || '' ).html(),

                            isDom   : true,

                            element : element

                        };



                        if ($.metadata) {

                            $.extend(true, obj, element.metadata());

                        }



                    } else {

                        obj = element;

                    }

                }



                href  = opts.href  || obj.href || (isString(element) ? element : null);

                title = opts.title !== undefined ? opts.title : obj.title || '';



                content = opts.content || obj.content;

                type    = content ? 'html' : (opts.type  || obj.type);



                if (!type && obj.isDom) {

                    type = element.data('fancybox-type');



                    if (!type) {

                        rez  = element.prop('class').match(/fancybox\.(\w+)/);

                        type = rez ? rez[1] : null;

                    }

                }



                if (isString(href)) {

                    // Try to guess the content type

                    if (!type) {

                        if (F.isImage(href)) {

                            type = 'image';



                        } else if (F.isSWF(href)) {

                            type = 'swf';



                        } else if (href.charAt(0) === '#') {

                            type = 'inline';



                        } else if (isString(element)) {

                            type    = 'html';

                            content = element;

                        }

                    }



                    // Split url into two pieces with source url and content selector, e.g,

                    // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id"

                    if (type === 'ajax') {

                        hrefParts = href.split(/\s+/, 2);

                        href      = hrefParts.shift();

                        selector  = hrefParts.shift();

                    }

                }



                if (!content) {

                    if (type === 'inline') {

                        if (href) {

                            content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7



                        } else if (obj.isDom) {

                            content = element;

                        }



                    } else if (type === 'html') {

                        content = href;



                    } else if (!type && !href && obj.isDom) {

                        type    = 'inline';

                        content = element;

                    }

                }



                $.extend(obj, {

                    href     : href,

                    type     : type,

                    content  : content,

                    title    : title,

                    selector : selector

                });



                group[ i ] = obj;

            });



            // Extend the defaults

            F.opts = $.extend(true, {}, F.defaults, opts);



            // All options are merged recursive except keys

            if (opts.keys !== undefined) {

                F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false;

            }



            F.group = group;



            return F._start(F.opts.index);

        },



        // Cancel image loading or abort ajax request

        cancel: function () {

            var coming = F.coming;



            if (coming && false === F.trigger('onCancel')) {

                return;

            }



            F.hideLoading();



            if (!coming) {

                return;

            }



            if (F.ajaxLoad) {

                F.ajaxLoad.abort();

            }



            F.ajaxLoad = null;



            if (F.imgPreload) {

                F.imgPreload.onload = F.imgPreload.onerror = null;

            }



            if (coming.wrap) {

                coming.wrap.stop(true, true).trigger('onReset').remove();

            }



            F.coming = null;



            // If the first item has been canceled, then clear everything

            if (!F.current) {

                F._afterZoomOut( coming );

            }

        },



        // Start closing animation if is open; remove immediately if opening/closing

        close: function (event) {

            F.cancel();



            if (false === F.trigger('beforeClose')) {

                return;

            }



            F.unbindEvents();



            if (!F.isActive) {

                return;

            }



            if (!F.isOpen || event === true) {

                $('.fancybox-wrap').stop(true).trigger('onReset').remove();



                F._afterZoomOut();



            } else {

                F.isOpen = F.isOpened = false;

                F.isClosing = true;



                $('.fancybox-item, .fancybox-nav').remove();



                F.wrap.stop(true, true).removeClass('fancybox-opened');



                F.transitions[ F.current.closeMethod ]();

            }

        },



        // Manage slideshow:

        //   $.fancybox.play(); - toggle slideshow

        //   $.fancybox.play( true ); - start

        //   $.fancybox.play( false ); - stop

        play: function ( action ) {

            var clear = function () {

                    clearTimeout(F.player.timer);

                },

                set = function () {

                    clear();



                    if (F.current && F.player.isActive) {

                        F.player.timer = setTimeout(F.next, F.current.playSpeed);

                    }

                },

                stop = function () {

                    clear();



                    D.unbind('.player');



                    F.player.isActive = false;



                    F.trigger('onPlayEnd');

                },

                start = function () {

                    if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) {

                        F.player.isActive = true;



                        D.bind({

                            'onCancel.player beforeClose.player' : stop,

                            'onUpdate.player'   : set,

                            'beforeLoad.player' : clear

                        });



                        set();



                        F.trigger('onPlayStart');

                    }

                };



            if (action === true || (!F.player.isActive && action !== false)) {

                start();

            } else {

                stop();

            }

        },



        // Navigate to next gallery item

        next: function ( direction ) {

            var current = F.current;



            if (current) {

                if (!isString(direction)) {

                    direction = current.direction.next;

                }



                F.jumpto(current.index + 1, direction, 'next');

            }

        },



        // Navigate to previous gallery item

        prev: function ( direction ) {

            var current = F.current;



            if (current) {

                if (!isString(direction)) {

                    direction = current.direction.prev;

                }



                F.jumpto(current.index - 1, direction, 'prev');

            }

        },



        // Navigate to gallery item by index

        jumpto: function ( index, direction, router ) {

            var current = F.current;



            if (!current) {

                return;

            }



            index = getScalar(index);



            F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ];

            F.router    = router || 'jumpto';



            if (current.loop) {

                if (index < 0) {

                    index = current.group.length + (index % current.group.length);

                }



                index = index % current.group.length;

            }



            if (current.group[ index ] !== undefined) {

                F.cancel();



                F._start(index);

            }

        },



        // Center inside viewport and toggle position type to fixed or absolute if needed

        reposition: function (e, onlyAbsolute) {

            var current = F.current,

                wrap    = current ? current.wrap : null,

                pos;



            if (wrap) {

                pos = F._getPosition(onlyAbsolute);



                if (e && e.type === 'scroll') {

                    delete pos.position;



                    wrap.stop(true, true).animate(pos, 200);



                } else {

                    wrap.css(pos);



                    current.pos = $.extend({}, current.dim, pos);

                }

            }

        },



        update: function (e) {

            var type = (e && e.originalEvent && e.originalEvent.type),

                anyway = !type || type === 'orientationchange';



            if (anyway) {

                clearTimeout(didUpdate);



                didUpdate = null;

            }



            if (!F.isOpen || didUpdate) {

                return;

            }



            didUpdate = setTimeout(function() {

                var current = F.current;



                if (!current || F.isClosing) {

                    return;

                }



                F.wrap.removeClass('fancybox-tmp');



                if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) {

                    F._setDimension();

                }



                if (!(type === 'scroll' && current.canShrink)) {

                    F.reposition(e);

                }



                F.trigger('onUpdate');



                didUpdate = null;



            }, (anyway && !isTouch ? 0 : 300));

        },



        // Shrink content to fit inside viewport or restore if resized

        toggle: function ( action ) {

            if (F.isOpen) {

                F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView;



                // Help browser to restore document dimensions

                if (isTouch) {

                    F.wrap.removeAttr('style').addClass('fancybox-tmp');



                    F.trigger('onUpdate');

                }



                F.update();

            }

        },



        hideLoading: function () {

            D.unbind('.loading');



            $('#fancybox-loading').remove();

        },



        showLoading: function () {

            var el, viewport;



            F.hideLoading();



            el = $(F.opts.tpl.loading).click(F.cancel).appendTo('body');



            // If user will press the escape-button, the request will be canceled

            D.bind('keydown.loading', function(e) {

                if ((e.which || e.keyCode) === 27) {

                    e.preventDefault();



                    F.cancel();

                }

            });



            if (!F.defaults.fixed) {

                viewport = F.getViewport();



                el.css({

                    position : 'absolute',

                    top  : (viewport.h * 0.5) + viewport.y,

                    left : (viewport.w * 0.5) + viewport.x

                });

            }



            F.trigger('onLoading');

        },



        getViewport: function () {

            var locked = (F.current && F.current.locked) || false,

                rez    = {

                    x: W.scrollLeft(),

                    y: W.scrollTop()

                };



            if (locked && locked.length) {

                rez.w = locked[0].clientWidth;

                rez.h = locked[0].clientHeight;



            } else {

                // See http://bugs.jquery.com/ticket/6724

                rez.w = isTouch && window.innerWidth  ? window.innerWidth  : W.width();

                rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height();

            }



            return rez;

        },



        // Unbind the keyboard / clicking actions

        unbindEvents: function () {

            if (F.wrap && isQuery(F.wrap)) {

                F.wrap.unbind('.fb');

            }



            D.unbind('.fb');

            W.unbind('.fb');

        },



        bindEvents: function () {

            var current = F.current,

                keys;



            if (!current) {

                return;

            }



            // Changing document height on iOS devices triggers a 'resize' event,

            // that can change document height... repeating infinitely

            W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update);



            keys = current.keys;



            if (keys) {

                D.bind('keydown.fb', function (e) {

                    var code   = e.which || e.keyCode,

                        target = e.target || e.srcElement;



                    // Skip esc key if loading, because showLoading will cancel preloading

                    if (code === 27 && F.coming) {

                        return false;

                    }



                    // Ignore key combinations and key events within form elements

                    if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) {

                        $.each(keys, function(i, val) {

                            if (current.group.length > 1 && val[ code ] !== undefined) {

                                F[ i ]( val[ code ] );



                                e.preventDefault();

                                return false;

                            }



                            if ($.inArray(code, val) > -1) {

                                F[ i ] ();



                                e.preventDefault();

                                return false;

                            }

                        });

                    }

                });

            }



            if ($.fn.mousewheel && current.mouseWheel) {

                F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) {

                    var target = e.target || null,

                        parent = $(target),

                        canScroll = false;



                    while (parent.length) {

                        if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) {

                            break;

                        }



                        canScroll = isScrollable( parent[0] );

                        parent    = $(parent).parent();

                    }



                    if (delta !== 0 && !canScroll) {

                        if (F.group.length > 1 && !current.canShrink) {

                            if (deltaY > 0 || deltaX > 0) {

                                F.prev( deltaY > 0 ? 'down' : 'left' );



                            } else if (deltaY < 0 || deltaX < 0) {

                                F.next( deltaY < 0 ? 'up' : 'right' );

                            }



                            e.preventDefault();

                        }

                    }

                });

            }

        },



        trigger: function (event, o) {

            var ret, obj = o || F.coming || F.current;



            if (obj) {

                if ($.isFunction( obj[event] )) {

                    ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1));

                }



                if (ret === false) {

                    return false;

                }



                if (obj.helpers) {

                    $.each(obj.helpers, function (helper, opts) {

                        if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) {

                            F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj);

                        }

                    });

                }

            }



            D.trigger(event);

        },



        isImage: function (str) {

            return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i);

        },



        isSWF: function (str) {

            return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i);

        },



        _start: function (index) {

            var coming = {},

                obj,

                href,

                type,

                margin,

                padding;



            index = getScalar( index );

            obj   = F.group[ index ] || null;



            if (!obj) {

                return false;

            }



            coming = $.extend(true, {}, F.opts, obj);



            // Convert margin and padding properties to array - top, right, bottom, left

            margin  = coming.margin;

            padding = coming.padding;



            if ($.type(margin) === 'number') {

                coming.margin = [margin, margin, margin, margin];

            }



            if ($.type(padding) === 'number') {

                coming.padding = [padding, padding, padding, padding];

            }



            // 'modal' propery is just a shortcut

            if (coming.modal) {

                $.extend(true, coming, {

                    closeBtn   : false,

                    closeClick : false,

                    nextClick  : false,

                    arrows     : false,

                    mouseWheel : false,

                    keys       : null,

                    helpers: {

                        overlay : {

                            closeClick : false

                        }

                    }

                });

            }



            // 'autoSize' property is a shortcut, too

            if (coming.autoSize) {

                coming.autoWidth = coming.autoHeight = true;

            }



            if (coming.width === 'auto') {

                coming.autoWidth = true;

            }



            if (coming.height === 'auto') {

                coming.autoHeight = true;

            }



            /*

             * Add reference to the group, so it`s possible to access from callbacks, example:

             * afterLoad : function() {

             *     this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : '');

             * }

             */



            coming.group  = F.group;

            coming.index  = index;



            // Give a chance for callback or helpers to update coming item (type, title, etc)

            F.coming = coming;



            if (false === F.trigger('beforeLoad')) {

                F.coming = null;



                return;

            }



            type = coming.type;

            href = coming.href;



            if (!type) {

                F.coming = null;



                //If we can not determine content type then drop silently or display next/prev item if looping through gallery

                if (F.current && F.router && F.router !== 'jumpto') {

                    F.current.index = index;



                    return F[ F.router ]( F.direction );

                }



                return false;

            }



            F.isActive = true;



            if (type === 'image' || type === 'swf') {

                coming.autoHeight = coming.autoWidth = false;

                coming.scrolling  = 'visible';

            }



            if (type === 'image') {

                coming.aspectRatio = true;

            }



            if (type === 'iframe' && isTouch) {

                coming.scrolling = 'scroll';

            }



            // Build the neccessary markup

            coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' );



            $.extend(coming, {

                skin  : $('.fancybox-skin',  coming.wrap),

                outer : $('.fancybox-outer', coming.wrap),

                inner : $('.fancybox-inner', coming.wrap)

            });



            $.each(["Top", "Right", "Bottom", "Left"], function(i, v) {

                coming.skin.css('padding' + v, getValue(coming.padding[ i ]));

            });



            F.trigger('onReady');



            // Check before try to load; 'inline' and 'html' types need content, others - href

            if (type === 'inline' || type === 'html') {

                if (!coming.content || !coming.content.length) {

                    return F._error( 'content' );

                }



            } else if (!href) {

                return F._error( 'href' );

            }



            if (type === 'image') {

                F._loadImage();



            } else if (type === 'ajax') {

                F._loadAjax();



            } else if (type === 'iframe') {

                F._loadIframe();



            } else {

                F._afterLoad();

            }

        },



        _error: function ( type ) {

            $.extend(F.coming, {

                type       : 'html',

                autoWidth  : true,

                autoHeight : true,

                minWidth   : 0,

                minHeight  : 0,

                scrolling  : 'no',

                hasError   : type,

                content    : F.coming.tpl.error

            });



            F._afterLoad();

        },



        _loadImage: function () {

            // Reset preload image so it is later possible to check "complete" property

            var img = F.imgPreload = new Image();



            img.onload = function () {

                this.onload = this.onerror = null;



                F.coming.width  = this.width / F.opts.pixelRatio;

                F.coming.height = this.height / F.opts.pixelRatio;



                F._afterLoad();

            };



            img.onerror = function () {

                this.onload = this.onerror = null;



                F._error( 'image' );

            };



            img.src = F.coming.href;



            if (img.complete !== true) {

                F.showLoading();

            }

        },



        _loadAjax: function () {

            var coming = F.coming;



            F.showLoading();



            F.ajaxLoad = $.ajax($.extend({}, coming.ajax, {

                url: coming.href,

                error: function (jqXHR, textStatus) {

                    if (F.coming && textStatus !== 'abort') {

                        F._error( 'ajax', jqXHR );



                    } else {

                        F.hideLoading();

                    }

                },

                success: function (data, textStatus) {

                    if (textStatus === 'success') {

                        coming.content = data;



                        F._afterLoad();

                    }

                }

            }));

        },



        _loadIframe: function() {

            var coming = F.coming,

                iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime()))

                    .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling)

                    .attr('src', coming.href);



            // This helps IE

            $(coming.wrap).bind('onReset', function () {

                try {

                    $(this).find('iframe').hide().attr('src', '//about:blank').end().empty();

                } catch (e) {}

            });



            if (coming.iframe.preload) {

                F.showLoading();



                iframe.one('load', function() {

                    $(this).data('ready', 1);



                    // iOS will lose scrolling if we resize

                    if (!isTouch) {

                        $(this).bind('load.fb', F.update);

                    }



                    // Without this trick:

                    //   - iframe won't scroll on iOS devices

                    //   - IE7 sometimes displays empty iframe

                    $(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show();



                    F._afterLoad();

                });

            }



            coming.content = iframe.appendTo( coming.inner );



            if (!coming.iframe.preload) {

                F._afterLoad();

            }

        },



        _preloadImages: function() {

            var group   = F.group,

                current = F.current,

                len     = group.length,

                cnt     = current.preload ? Math.min(current.preload, len - 1) : 0,

                item,

                i;



            for (i = 1; i <= cnt; i += 1) {

                item = group[ (current.index + i ) % len ];



                if (item.type === 'image' && item.href) {

                    new Image().src = item.href;

                }

            }

        },



        _afterLoad: function () {

            var coming   = F.coming,

                previous = F.current,

                placeholder = 'fancybox-placeholder',

                current,

                content,

                type,

                scrolling,

                href,

                embed;



            F.hideLoading();



            if (!coming || F.isActive === false) {

                return;

            }



            if (false === F.trigger('afterLoad', coming, previous)) {

                coming.wrap.stop(true).trigger('onReset').remove();



                F.coming = null;



                return;

            }



            if (previous) {

                F.trigger('beforeChange', previous);



                previous.wrap.stop(true).removeClass('fancybox-opened')

                    .find('.fancybox-item, .fancybox-nav')

                    .remove();

            }



            F.unbindEvents();



            current   = coming;

            content   = coming.content;

            type      = coming.type;

            scrolling = coming.scrolling;



            $.extend(F, {

                wrap  : current.wrap,

                skin  : current.skin,

                outer : current.outer,

                inner : current.inner,

                current  : current,

                previous : previous

            });



            href = current.href;



            switch (type) {

                case 'inline':

                case 'ajax':

                case 'html':

                    if (current.selector) {

                        content = $('<div>').html(content).find(current.selector);



                    } else if (isQuery(content)) {

                        if (!content.data(placeholder)) {

                            content.data(placeholder, $('<div class="' + placeholder + '"></div>').insertAfter( content ).hide() );

                        }



                        content = content.show().detach();



                        current.wrap.bind('onReset', function () {

                            if ($(this).find(content).length) {

                                content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false);

                            }

                        });

                    }

                    break;



                case 'image':

                    content = current.tpl.image.replace(/\{href\}/g, href);

                    break;



                case 'swf':

                    content = '<object id="fancybox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="' + href + '"></param>';

                    embed   = '';



                    $.each(current.swf, function(name, val) {

                        content += '<param name="' + name + '" value="' + val + '"></param>';

                        embed   += ' ' + name + '="' + val + '"';

                    });



                    content += '<embed src="' + href + '" type="application/x-shockwave-flash" width="100%" height="100%"' + embed + '></embed></object>';

                    break;

            }



            if (!(isQuery(content) && content.parent().is(current.inner))) {

                current.inner.append( content );

            }



            // Give a chance for helpers or callbacks to update elements

            F.trigger('beforeShow');



            // Set scrolling before calculating dimensions

            current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling));



            // Set initial dimensions and start position

            F._setDimension();



            F.reposition();



            F.isOpen = false;

            F.coming = null;



            F.bindEvents();



            if (!F.isOpened) {

                $('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove();



            } else if (previous.prevMethod) {

                F.transitions[ previous.prevMethod ]();

            }



            F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ]();



            F._preloadImages();

        },



        _setDimension: function () {

            var viewport   = F.getViewport(),

                steps      = 0,

                canShrink  = false,

                canExpand  = false,

                wrap       = F.wrap,

                skin       = F.skin,

                inner      = F.inner,

                current    = F.current,

                width      = current.width,

                height     = current.height,

                minWidth   = current.minWidth,

                minHeight  = current.minHeight,

                maxWidth   = current.maxWidth,

                maxHeight  = current.maxHeight,

                scrolling  = current.scrolling,

                scrollOut  = current.scrollOutside ? current.scrollbarWidth : 0,

                margin     = current.margin,

                wMargin    = getScalar(margin[1] + margin[3]),

                hMargin    = getScalar(margin[0] + margin[2]),

                wPadding,

                hPadding,

                wSpace,

                hSpace,

                origWidth,

                origHeight,

                origMaxWidth,

                origMaxHeight,

                ratio,

                width_,

                height_,

                maxWidth_,

                maxHeight_,

                iframe,

                body;



            // Reset dimensions so we could re-check actual size

            wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp');



            wPadding = getScalar(skin.outerWidth(true)  - skin.width());

            hPadding = getScalar(skin.outerHeight(true) - skin.height());



            // Any space between content and viewport (margin, padding, border, title)

            wSpace = wMargin + wPadding;

            hSpace = hMargin + hPadding;



            origWidth  = isPercentage(width)  ? (viewport.w - wSpace) * getScalar(width)  / 100 : width;

            origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height;



            if (current.type === 'iframe') {

                iframe = current.content;



                if (current.autoHeight && iframe && iframe.data('ready') === 1) {

                    try {

                        if (iframe[0].contentWindow.document.location) {

                            inner.width( origWidth ).height(9999);



                            body = iframe.contents().find('body');



                            if (scrollOut) {

                                body.css('overflow-x', 'hidden');

                            }



                            origHeight = body.outerHeight(true);

                        }



                    } catch (e) {}

                }



            } else if (current.autoWidth || current.autoHeight) {

                inner.addClass( 'fancybox-tmp' );



                // Set width or height in case we need to calculate only one dimension

                if (!current.autoWidth) {

                    inner.width( origWidth );

                }



                if (!current.autoHeight) {

                    inner.height( origHeight );

                }



                if (current.autoWidth) {

                    origWidth = inner.width();

                }



                if (current.autoHeight) {

                    origHeight = inner.height();

                }



                inner.removeClass( 'fancybox-tmp' );

            }



            width  = getScalar( origWidth );

            height = getScalar( origHeight );



            ratio  = origWidth / origHeight;



            // Calculations for the content

            minWidth  = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth);

            maxWidth  = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth);



            minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight);

            maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight);



            // These will be used to determine if wrap can fit in the viewport

            origMaxWidth  = maxWidth;

            origMaxHeight = maxHeight;



            if (current.fitToView) {

                maxWidth  = Math.min(viewport.w - wSpace, maxWidth);

                maxHeight = Math.min(viewport.h - hSpace, maxHeight);

            }



            maxWidth_  = viewport.w - wMargin;

            maxHeight_ = viewport.h - hMargin;



            if (current.aspectRatio) {

                if (width > maxWidth) {

                    width  = maxWidth;

                    height = getScalar(width / ratio);

                }



                if (height > maxHeight) {

                    height = maxHeight;

                    width  = getScalar(height * ratio);

                }



                if (width < minWidth) {

                    width  = minWidth;

                    height = getScalar(width / ratio);

                }



                if (height < minHeight) {

                    height = minHeight;

                    width  = getScalar(height * ratio);

                }



            } else {

                width = Math.max(minWidth, Math.min(width, maxWidth));



                if (current.autoHeight && current.type !== 'iframe') {

                    inner.width( width );



                    height = inner.height();

                }



                height = Math.max(minHeight, Math.min(height, maxHeight));

            }



            // Try to fit inside viewport (including the title)

            if (current.fitToView) {

                inner.width( width ).height( height );



                wrap.width( width + wPadding );



                // Real wrap dimensions

                width_  = wrap.width();

                height_ = wrap.height();



                if (current.aspectRatio) {

                    while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) {

                        if (steps++ > 19) {

                            break;

                        }



                        height = Math.max(minHeight, Math.min(maxHeight, height - 10));

                        width  = getScalar(height * ratio);



                        if (width < minWidth) {

                            width  = minWidth;

                            height = getScalar(width / ratio);

                        }



                        if (width > maxWidth) {

                            width  = maxWidth;

                            height = getScalar(width / ratio);

                        }



                        inner.width( width ).height( height );



                        wrap.width( width + wPadding );



                        width_  = wrap.width();

                        height_ = wrap.height();

                    }



                } else {

                    width  = Math.max(minWidth,  Math.min(width,  width  - (width_  - maxWidth_)));

                    height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_)));

                }

            }



            if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) {

                width += scrollOut;

            }



            inner.width( width ).height( height );



            wrap.width( width + wPadding );



            width_  = wrap.width();

            height_ = wrap.height();



            canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight;

            canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight));



            $.extend(current, {

                dim : {

                    width	: getValue( width_ ),

                    height	: getValue( height_ )

                },

                origWidth  : origWidth,

                origHeight : origHeight,

                canShrink  : canShrink,

                canExpand  : canExpand,

                wPadding   : wPadding,

                hPadding   : hPadding,

                wrapSpace  : height_ - skin.outerHeight(true),

                skinSpace  : skin.height() - height

            });



            if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) {

                inner.height('auto');

            }

        },



        _getPosition: function (onlyAbsolute) {

            var current  = F.current,

                viewport = F.getViewport(),

                margin   = current.margin,

                width    = F.wrap.width()  + margin[1] + margin[3],

                height   = F.wrap.height() + margin[0] + margin[2],

                rez      = {

                    position: 'absolute',

                    top  : margin[0],

                    left : margin[3]

                };



            if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) {

                rez.position = 'fixed';



            } else if (!current.locked) {

                rez.top  += viewport.y;

                rez.left += viewport.x;

            }



            rez.top  = getValue(Math.max(rez.top,  rez.top  + ((viewport.h - height) * current.topRatio)));

            rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width)  * current.leftRatio)));



            return rez;

        },



        _afterZoomIn: function () {

            var current = F.current;



            if (!current) {

                return;

            }



            F.isOpen = F.isOpened = true;



            F.wrap.css('overflow', 'visible').addClass('fancybox-opened').hide().show(0);



            F.update();



            // Assign a click event

            if ( current.closeClick || (current.nextClick && F.group.length > 1) ) {

                F.inner.css('cursor', 'pointer').bind('click.fb', function(e) {

                    if (!$(e.target).is('a') && !$(e.target).parent().is('a')) {

                        e.preventDefault();



                        F[ current.closeClick ? 'close' : 'next' ]();

                    }

                });

            }



            // Create a close button

            if (current.closeBtn) {

                $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) {

                    e.preventDefault();



                    F.close();

                });

            }



            // Create navigation arrows

            if (current.arrows && F.group.length > 1) {

                if (current.loop || current.index > 0) {

                    $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev);

                }



                if (current.loop || current.index < F.group.length - 1) {

                    $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next);

                }

            }



            F.trigger('afterShow');



            // Stop the slideshow if this is the last item

            if (!current.loop && current.index === current.group.length - 1) {



                F.play( false );



            } else if (F.opts.autoPlay && !F.player.isActive) {

                F.opts.autoPlay = false;



                F.play(true);

            }

        },



        _afterZoomOut: function ( obj ) {

            obj = obj || F.current;



            $('.fancybox-wrap').trigger('onReset').remove();



            $.extend(F, {

                group  : {},

                opts   : {},

                router : false,

                current   : null,

                isActive  : false,

                isOpened  : false,

                isOpen    : false,

                isClosing : false,

                wrap   : null,

                skin   : null,

                outer  : null,

                inner  : null

            });



            F.trigger('afterClose', obj);

        }

    });



    /*

     *	Default transitions

     */



    F.transitions = {

        getOrigPosition: function () {

            var current  = F.current,

                element  = current.element,

                orig     = current.orig,

                pos      = {},

                width    = 50,

                height   = 50,

                hPadding = current.hPadding,

                wPadding = current.wPadding,

                viewport = F.getViewport();



            if (!orig && current.isDom && element.is(':visible')) {

                orig = element.find('img:first');



                if (!orig.length) {

                    orig = element;

                }

            }



            if (isQuery(orig)) {

                pos = orig.offset();



                if (orig.is('img')) {

                    width  = orig.outerWidth();

                    height = orig.outerHeight();

                }



            } else {

                pos.top  = viewport.y + (viewport.h - height) * current.topRatio;

                pos.left = viewport.x + (viewport.w - width)  * current.leftRatio;

            }



            if (F.wrap.css('position') === 'fixed' || current.locked) {

                pos.top  -= viewport.y;

                pos.left -= viewport.x;

            }



            pos = {

                top     : getValue(pos.top  - hPadding * current.topRatio),

                left    : getValue(pos.left - wPadding * current.leftRatio),

                width   : getValue(width  + wPadding),

                height  : getValue(height + hPadding)

            };



            return pos;

        },



        step: function (now, fx) {

            var ratio,

                padding,

                value,

                prop       = fx.prop,

                current    = F.current,

                wrapSpace  = current.wrapSpace,

                skinSpace  = current.skinSpace;



            if (prop === 'width' || prop === 'height') {

                ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start);



                if (F.isClosing) {

                    ratio = 1 - ratio;

                }



                padding = prop === 'width' ? current.wPadding : current.hPadding;

                value   = now - padding;



                F.skin[ prop ](  getScalar( prop === 'width' ?  value : value - (wrapSpace * ratio) ) );

                F.inner[ prop ]( getScalar( prop === 'width' ?  value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) );

            }

        },



        zoomIn: function () {

            var current  = F.current,

                startPos = current.pos,

                effect   = current.openEffect,

                elastic  = effect === 'elastic',

                endPos   = $.extend({opacity : 1}, startPos);



            // Remove "position" property that breaks older IE

            delete endPos.position;



            if (elastic) {

                startPos = this.getOrigPosition();



                if (current.openOpacity) {

                    startPos.opacity = 0.1;

                }



            } else if (effect === 'fade') {

                startPos.opacity = 0.1;

            }



            F.wrap.css(startPos).animate(endPos, {

                duration : effect === 'none' ? 0 : current.openSpeed,

                easing   : current.openEasing,

                step     : elastic ? this.step : null,

                complete : F._afterZoomIn

            });

        },



        zoomOut: function () {

            var current  = F.current,

                effect   = current.closeEffect,

                elastic  = effect === 'elastic',

                endPos   = {opacity : 0.1};



            if (elastic) {

                endPos = this.getOrigPosition();



                if (current.closeOpacity) {

                    endPos.opacity = 0.1;

                }

            }



            F.wrap.animate(endPos, {

                duration : effect === 'none' ? 0 : current.closeSpeed,

                easing   : current.closeEasing,

                step     : elastic ? this.step : null,

                complete : F._afterZoomOut

            });

        },



        changeIn: function () {

            var current   = F.current,

                effect    = current.nextEffect,

                startPos  = current.pos,

                endPos    = { opacity : 1 },

                direction = F.direction,

                distance  = 200,

                field;



            startPos.opacity = 0.1;



            if (effect === 'elastic') {

                field = direction === 'down' || direction === 'up' ? 'top' : 'left';



                if (direction === 'down' || direction === 'right') {

                    startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance);

                    endPos[ field ]   = '+=' + distance + 'px';



                } else {

                    startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance);

                    endPos[ field ]   = '-=' + distance + 'px';

                }

            }



            // Workaround for http://bugs.jquery.com/ticket/12273

            if (effect === 'none') {

                F._afterZoomIn();



            } else {

                F.wrap.css(startPos).animate(endPos, {

                    duration : current.nextSpeed,

                    easing   : current.nextEasing,

                    complete : F._afterZoomIn

                });

            }

        },



        changeOut: function () {

            var previous  = F.previous,

                effect    = previous.prevEffect,

                endPos    = { opacity : 0.1 },

                direction = F.direction,

                distance  = 200;



            if (effect === 'elastic') {

                endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px';

            }



            previous.wrap.animate(endPos, {

                duration : effect === 'none' ? 0 : previous.prevSpeed,

                easing   : previous.prevEasing,

                complete : function () {

                    $(this).trigger('onReset').remove();

                }

            });

        }

    };



    /*

     *	Overlay helper

     */



    F.helpers.overlay = {

        defaults : {

            closeClick : true,      // if true, fancyBox will be closed when user clicks on the overlay

            speedOut   : 200,       // duration of fadeOut animation

            showEarly  : true,      // indicates if should be opened immediately or wait until the content is ready

            css        : {},        // custom CSS properties

            locked     : !isTouch,  // if true, the content will be locked into overlay

            fixed      : true       // if false, the overlay CSS position property will not be set to "fixed"

        },



        overlay : null,      // current handle

        fixed   : false,     // indicates if the overlay has position "fixed"

        el      : $('html'), // element that contains "the lock"



        // Public methods

        create : function(opts) {

            var parent;



            opts = $.extend({}, this.defaults, opts);



            if (this.overlay) {

                this.close();

            }



            parent = F.coming ? F.coming.parent : opts.parent;



            this.overlay = $('<div class="fancybox-overlay"></div>').appendTo( parent && parent.length ? parent : 'body' );

            this.fixed   = false;



            if (opts.fixed && F.defaults.fixed) {

                this.overlay.addClass('fancybox-overlay-fixed');



                this.fixed = true;

            }

        },



        open : function(opts) {

            var that = this;



            opts = $.extend({}, this.defaults, opts);



            if (this.overlay) {

                this.overlay.unbind('.overlay').width('auto').height('auto');



            } else {

                this.create(opts);

            }



            if (!this.fixed) {

                W.bind('resize.overlay', $.proxy( this.update, this) );



                this.update();

            }



            if (opts.closeClick) {

                this.overlay.bind('click.overlay', function(e) {

                    if ($(e.target).hasClass('fancybox-overlay')) {

                        if (F.isActive) {

                            F.close();

                        } else {

                            that.close();

                        }



                        return false;

                    }

                });

            }



            this.overlay.css( opts.css ).show();

        },



        close : function() {

            W.unbind('resize.overlay');



            if (this.el.hasClass('fancybox-lock')) {

                $('.fancybox-margin').removeClass('fancybox-margin');



                this.el.removeClass('fancybox-lock');



                W.scrollTop( this.scrollV ).scrollLeft( this.scrollH );

            }



            $('.fancybox-overlay').remove().hide();



            $.extend(this, {

                overlay : null,

                fixed   : false

            });

        },



        // Private, callbacks



        update : function () {

            var width = '100%', offsetWidth;



            // Reset width/height so it will not mess

            this.overlay.width(width).height('100%');



            // jQuery does not return reliable result for IE

            if (IE) {

                offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth);



                if (D.width() > offsetWidth) {

                    width = D.width();

                }



            } else if (D.width() > W.width()) {

                width = D.width();

            }



            this.overlay.width(width).height(D.height());

        },



        // This is where we can manipulate DOM, because later it would cause iframes to reload

        onReady : function (opts, obj) {

            var overlay = this.overlay;



            $('.fancybox-overlay').stop(true, true);



            if (!overlay) {

                this.create(opts);

            }



            if (opts.locked && this.fixed && obj.fixed) {

                obj.locked = this.overlay.append( obj.wrap );

                obj.fixed  = false;

            }



            if (opts.showEarly === true) {

                this.beforeShow.apply(this, arguments);

            }

        },



        beforeShow : function(opts, obj) {

            if (obj.locked && !this.el.hasClass('fancybox-lock')) {

                if (this.fixPosition !== false) {

                    $('*:not(object)').filter(function(){

                        return ($(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && !$(this).hasClass("fancybox-wrap") );

                    }).addClass('fancybox-margin');

                }



                this.el.addClass('fancybox-margin');



                this.scrollV = W.scrollTop();

                this.scrollH = W.scrollLeft();



                this.el.addClass('fancybox-lock');



                W.scrollTop( this.scrollV ).scrollLeft( this.scrollH );

            }



            this.open(opts);

        },



        onUpdate : function() {

            if (!this.fixed) {

                this.update();

            }

        },



        afterClose: function (opts) {

            // Remove overlay if exists and fancyBox is not opening

            // (e.g., it is not being open using afterClose callback)

            if (this.overlay && !F.coming) {

                this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this ));

            }

        }

    };



    /*

     *	Title helper

     */



    F.helpers.title = {

        defaults : {

            type     : 'float', // 'float', 'inside', 'outside' or 'over',

            position : 'bottom' // 'top' or 'bottom'

        },



        beforeShow: function (opts) {

            var current = F.current,

                text    = current.title,

                type    = opts.type,

                title,

                target;



            if ($.isFunction(text)) {

                text = text.call(current.element, current);

            }



            if (!isString(text) || $.trim(text) === '') {

                return;

            }



            title = $('<div class="fancybox-title fancybox-title-' + type + '-wrap">' + text + '</div>');



            switch (type) {

                case 'inside':

                    target = F.skin;

                    break;



                case 'outside':

                    target = F.wrap;

                    break;



                case 'over':

                    target = F.inner;

                    break;



                default: // 'float'

                    target = F.skin;



                    title.appendTo('body');



                    if (IE) {

                        title.width( title.width() );

                    }



                    title.wrapInner('<span class="child"></span>');



                    //Increase bottom margin so this title will also fit into viewport

                    F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) );

                    break;

            }



            title[ (opts.position === 'top' ? 'prependTo'  : 'appendTo') ](target);

        }

    };



    // jQuery plugin initialization

    $.fn.fancybox = function (options) {

        var index,

            that     = $(this),

            selector = this.selector || '',

            run      = function(e) {

                var what = $(this).blur(), idx = index, relType, relVal;



                if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) {

                    relType = options.groupAttr || 'data-fancybox-group';

                    relVal  = what.attr(relType);



                    if (!relVal) {

                        relType = 'rel';

                        relVal  = what.get(0)[ relType ];

                    }



                    if (relVal && relVal !== '' && relVal !== 'nofollow') {

                        what = selector.length ? $(selector) : that;

                        what = what.filter('[' + relType + '="' + relVal + '"]');

                        idx  = what.index(this);

                    }



                    options.index = idx;



                    // Stop an event from bubbling if everything is fine

                    if (F.open(what, options) !== false) {

                        e.preventDefault();

                    }

                }

            };



        options = options || {};

        index   = options.index || 0;



        if (!selector || options.live === false) {

            that.unbind('click.fb-start').bind('click.fb-start', run);



        } else {

            D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run);

        }



        this.filter('[data-fancybox-start=1]').trigger('click');



        return this;

    };



    // Tests that need a body at doc ready

    D.ready(function() {

        var w1, w2;



        if ( $.scrollbarWidth === undefined ) {

            // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth

            $.scrollbarWidth = function() {

                var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body'),

                    child  = parent.children(),

                    width  = child.innerWidth() - child.height( 99 ).innerWidth();



                parent.remove();



                return width;

            };

        }



        if ( $.support.fixedPosition === undefined ) {

            $.support.fixedPosition = (function() {

                var elem  = $('<div style="position:fixed;top:20px;"></div>').appendTo('body'),

                    fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 );



                elem.remove();



                return fixed;

            }());

        }



        $.extend(F.defaults, {

            scrollbarWidth : $.scrollbarWidth(),

            fixed  : $.support.fixedPosition,

            parent : $('body')

        });



        //Get real width of page scroll-bar

        w1 = $(window).width();



        H.addClass('fancybox-lock-test');



        w2 = $(window).width();



        H.removeClass('fancybox-lock-test');



        $("<style type='text/css'>.fancybox-margin{margin-right:" + (w2 - w1) + "px;}</style>").appendTo("head");

    });



}(window, document, jQuery));

//** jQuery Scroll to Top Control script- (c) Dynamic Drive DHTML code library: http://www.dynamicdrive.com.

//** Available/ usage terms at http://www.dynamicdrive.com (March 30th, 09')

//** v1.1 (April 7th, 09'):

//** 1) Adds ability to scroll to an absolute position (from top of page) or specific element on the page instead.

//** 2) Fixes scroll animation not working in Opera. 





var scrolltotop={

	//startline: Integer. Number of pixels from top of doc scrollbar is scrolled before showing control

	//scrollto: Keyword (Integer, or "Scroll_to_Element_ID"). How far to scroll document up when control is clicked on (0=top).

	setting: {startline:100, scrollto: 0, scrollduration:1000, fadeduration:[500, 100]},

	controlHTML: '<img src="assets/img/up.png" style="width:40px; height:40px" />', //HTML for control, which is auto wrapped in DIV w/ ID="topcontrol"

	controlattrs: {offsetx:10, offsety:10}, //offset of control relative to right/ bottom of window corner

	anchorkeyword: '#top', //Enter href value of HTML anchors on the page that should also act as "Scroll Up" links



	state: {isvisible:false, shouldvisible:false},



	scrollup:function(){

		if (!this.cssfixedsupport) //if control is positioned using JavaScript

			this.$control.css({opacity:0}); //hide control immediately after clicking it

		var dest=isNaN(this.setting.scrollto)? this.setting.scrollto : parseInt(this.setting.scrollto);

		if (typeof dest=="string" && jQuery('#'+dest).length==1) //check element set by string exists

			dest=jQuery('#'+dest).offset().top;

		else

			dest=0;

		this.$body.animate({scrollTop: dest}, this.setting.scrollduration);

	},



	keepfixed:function(){

		var $window=jQuery(window);

		var controlx=$window.scrollLeft() + $window.width() - this.$control.width() - this.controlattrs.offsetx;

		var controly=$window.scrollTop() + $window.height() - this.$control.height() - this.controlattrs.offsety;

		this.$control.css({left:controlx+'px', top:controly+'px'})

	},



	togglecontrol:function(){

		var scrolltop=jQuery(window).scrollTop();

		if (!this.cssfixedsupport)

			this.keepfixed();

		this.state.shouldvisible=(scrolltop>=this.setting.startline)? true : false;

		if (this.state.shouldvisible && !this.state.isvisible){

			this.$control.stop().animate({opacity:1}, this.setting.fadeduration[0]);

			this.state.isvisible=true

		}

		else if (this.state.shouldvisible==false && this.state.isvisible){

			this.$control.stop().animate({opacity:0}, this.setting.fadeduration[1]);

			this.state.isvisible=false

		}

	},

	

	init:function(){

		jQuery(document).ready(function($){

			var mainobj=scrolltotop;

			var iebrws=document.all;

			mainobj.cssfixedsupport=!iebrws || iebrws && document.compatMode=="CSS1Compat" && window.XMLHttpRequest //not IE or IE7+ browsers in standards mode

			mainobj.$body=(window.opera)? (document.compatMode=="CSS1Compat"? $('html') : $('body')) : $('html,body');

			mainobj.$control=$('<div id="topcontrol">'+mainobj.controlHTML+'</div>')

				.css({position:mainobj.cssfixedsupport? 'fixed' : 'absolute', bottom:mainobj.controlattrs.offsety, opacity:0, cursor:'pointer'})

				.attr({title:''})

				.click(function(){mainobj.scrollup(); return false})

				.appendTo('body');

			if (document.all && !window.XMLHttpRequest && mainobj.$control.text()!='') //loose check for IE6 and below, plus whether control contains any text

				mainobj.$control.css({width:mainobj.$control.width()}); //IE6- seems to require an explicit width on a DIV containing text

			mainobj.togglecontrol();

			$('a[href="' + mainobj.anchorkeyword +'"]').click(function(){

				mainobj.scrollup();

				return false

			});

			$(window).bind('scroll resize', function(e){

				mainobj.togglecontrol();

			});

		})

	}

};



//scrolltotop.init()

/**

* jquery.matchHeight.js master

* http://brm.io/jquery-match-height/

* License: MIT

*/



;(function($) {

    /*

    *  internal

    */



    var _previousResizeWidth = -1,

        _updateTimeout = -1;



    /*

    *  _parse

    *  value parse utility function

    */



    var _parse = function(value) {

        // parse value and convert NaN to 0

        return parseFloat(value) || 0;

    };



    /*

    *  _rows

    *  utility function returns array of jQuery selections representing each row

    *  (as displayed after float wrapping applied by browser)

    */



    var _rows = function(elements) {

        var tolerance = 1,

            $elements = $(elements),

            lastTop = null,

            rows = [];



        // group elements by their top position

        $elements.each(function(){

            var $that = $(this),

                top = $that.offset().top - _parse($that.css('margin-top')),

                lastRow = rows.length > 0 ? rows[rows.length - 1] : null;



            if (lastRow === null) {

                // first item on the row, so just push it

                rows.push($that);

            } else {

                // if the row top is the same, add to the row group

                if (Math.floor(Math.abs(lastTop - top)) <= tolerance) {

                    rows[rows.length - 1] = lastRow.add($that);

                } else {

                    // otherwise start a new row group

                    rows.push($that);

                }

            }



            // keep track of the last row top

            lastTop = top;

        });



        return rows;

    };



    /*

    *  _parseOptions

    *  handle plugin options

    */



    var _parseOptions = function(options) {

        var opts = {

            byRow: true,

            property: 'height',

            target: null,

            remove: false

        };



        if (typeof options === 'object') {

            return $.extend(opts, options);

        }



        if (typeof options === 'boolean') {

            opts.byRow = options;

        } else if (options === 'remove') {

            opts.remove = true;

        }



        return opts;

    };



    /*

    *  matchHeight

    *  plugin definition

    */



    var matchHeight = $.fn.matchHeight = function(options) {

        var opts = _parseOptions(options);



        // handle remove

        if (opts.remove) {

            var that = this;



            // remove fixed height from all selected elements

            this.css(opts.property, '');



            // remove selected elements from all groups

            $.each(matchHeight._groups, function(key, group) {

                group.elements = group.elements.not(that);

            });



            // TODO: cleanup empty groups



            return this;

        }



        if (this.length <= 1 && !opts.target) {

            return this;

        }



        // keep track of this group so we can re-apply later on load and resize events

        matchHeight._groups.push({

            elements: this,

            options: opts

        });



        // match each element's height to the tallest element in the selection

        matchHeight._apply(this, opts);



        return this;

    };



    /*

    *  plugin global options

    */



    matchHeight._groups = [];

    matchHeight._throttle = 80;

    matchHeight._maintainScroll = false;

    matchHeight._beforeUpdate = null;

    matchHeight._afterUpdate = null;



    /*

    *  matchHeight._apply

    *  apply matchHeight to given elements

    */



    matchHeight._apply = function(elements, options) {

        var opts = _parseOptions(options),

            $elements = $(elements),

            rows = [$elements];



        // take note of scroll position

        var scrollTop = $(window).scrollTop(),

            htmlHeight = $('html').outerHeight(true);



        // get hidden parents

        var $hiddenParents = $elements.parents().filter(':hidden');



        // cache the original inline style

        $hiddenParents.each(function() {

            var $that = $(this);

            $that.data('style-cache', $that.attr('style'));

        });



        // temporarily must force hidden parents visible

        $hiddenParents.css('display', 'block');



        // get rows if using byRow, otherwise assume one row

        if (opts.byRow && !opts.target) {



            // must first force an arbitrary equal height so floating elements break evenly

            $elements.each(function() {

                var $that = $(this),

                    display = $that.css('display') === 'inline-block' ? 'inline-block' : 'block';



                // cache the original inline style

                $that.data('style-cache', $that.attr('style'));



                $that.css({

                    'display': display,

                    'padding-top': '0',

                    'padding-bottom': '0',

                    'margin-top': '0',

                    'margin-bottom': '0',

                    'border-top-width': '0',

                    'border-bottom-width': '0',

                    'height': '100px'

                });

            });



            // get the array of rows (based on element top position)

            rows = _rows($elements);



            // revert original inline styles

            $elements.each(function() {

                var $that = $(this);

                $that.attr('style', $that.data('style-cache') || '');

            });

        }



        $.each(rows, function(key, row) {

            var $row = $(row),

                targetHeight = 0;



            if (!opts.target) {

                // skip apply to rows with only one item

                if (opts.byRow && $row.length <= 1) {

                    $row.css(opts.property, '');

                    return;

                }



                // iterate the row and find the max height

                $row.each(function(){

                    var $that = $(this),

                        display = $that.css('display') === 'inline-block' ? 'inline-block' : 'block';



                    // ensure we get the correct actual height (and not a previously set height value)

                    var css = { 'display': display };

                    css[opts.property] = '';

                    $that.css(css);



                    // find the max height (including padding, but not margin)

                    if ($that.outerHeight(false) > targetHeight) {

                        targetHeight = $that.outerHeight(false);

                    }



                    // revert display block

                    $that.css('display', '');

                });

            } else {

                // if target set, use the height of the target element

                targetHeight = opts.target.outerHeight(false);

            }



            // iterate the row and apply the height to all elements

            $row.each(function(){

                var $that = $(this),

                    verticalPadding = 0;



                // don't apply to a target

                if (opts.target && $that.is(opts.target)) {

                    return;

                }



                // handle padding and border correctly (required when not using border-box)

                if ($that.css('box-sizing') !== 'border-box') {

                    verticalPadding += _parse($that.css('border-top-width')) + _parse($that.css('border-bottom-width'));

                    verticalPadding += _parse($that.css('padding-top')) + _parse($that.css('padding-bottom'));

                }



                // set the height (accounting for padding and border)

                $that.css(opts.property, targetHeight - verticalPadding);

            });

        });



        // revert hidden parents

        $hiddenParents.each(function() {

            var $that = $(this);

            $that.attr('style', $that.data('style-cache') || null);

        });



        // restore scroll position if enabled

        if (matchHeight._maintainScroll) {

            $(window).scrollTop((scrollTop / htmlHeight) * $('html').outerHeight(true));

        }



        return this;

    };



    /*

    *  matchHeight._applyDataApi

    *  applies matchHeight to all elements with a data-match-height attribute

    */



    matchHeight._applyDataApi = function() {

        var groups = {};



        // generate groups by their groupId set by elements using data-match-height

        $('[data-match-height], [data-mh]').each(function() {

            var $this = $(this),

                groupId = $this.attr('data-mh') || $this.attr('data-match-height');



            if (groupId in groups) {

                groups[groupId] = groups[groupId].add($this);

            } else {

                groups[groupId] = $this;

            }

        });



        // apply matchHeight to each group

        $.each(groups, function() {

            this.matchHeight(true);

        });

    };



    /*

    *  matchHeight._update

    *  updates matchHeight on all current groups with their correct options

    */



    var _update = function(event) {

        if (matchHeight._beforeUpdate) {

            matchHeight._beforeUpdate(event, matchHeight._groups);

        }



        $.each(matchHeight._groups, function() {

            matchHeight._apply(this.elements, this.options);

        });



        if (matchHeight._afterUpdate) {

            matchHeight._afterUpdate(event, matchHeight._groups);

        }

    };



    matchHeight._update = function(throttle, event) {

        // prevent update if fired from a resize event

        // where the viewport width hasn't actually changed

        // fixes an event looping bug in IE8

        if (event && event.type === 'resize') {

            var windowWidth = $(window).width();

            if (windowWidth === _previousResizeWidth) {

                return;

            }

            _previousResizeWidth = windowWidth;

        }



        // throttle updates

        if (!throttle) {

            _update(event);

        } else if (_updateTimeout === -1) {

            _updateTimeout = setTimeout(function() {

                _update(event);

                _updateTimeout = -1;

            }, matchHeight._throttle);

        }

    };



    /*

    *  bind events

    */



    // apply on DOM ready event

    $(matchHeight._applyDataApi);



    // update heights on load and resize events

    $(window).bind('load', function(event) {

        matchHeight._update(false, event);

    });



    // throttled update heights on resize events

    $(window).bind('resize orientationchange', function(event) {

        matchHeight._update(true, event);

    });



})(jQuery);



/* Modernizr (Custom Build) | MIT & BSD
 * Build: http://modernizr.com/download/#-csstransforms3d-csstransitions-touch-shiv-load-cssclasses-prefixed-teststyles-testprops-testallprops-prefixes-domprefixes-mq-respond
 */
;window.Modernizr=function(e,t,n){function C(e){f.cssText=e}function k(e,t){return C(h.join(e+";")+(t||""))}function L(e,t){return typeof e===t}function A(e,t){return!!~(""+e).indexOf(t)}function O(e,t){for(var r in e){var i=e[r];if(!A(i,"-")&&f[i]!==n)return t=="pfx"?i:!0}return!1}function M(e,t,r){for(var i in e){var s=t[e[i]];if(s!==n)return r===!1?e[i]:L(s,"function")?s.bind(r||t):s}return!1}function _(e,t,n){var r=e.charAt(0).toUpperCase()+e.slice(1),i=(e+" "+d.join(r+" ")+r).split(" ");return L(t,"string")||L(t,"undefined")?O(i,t):(i=(e+" "+v.join(r+" ")+r).split(" "),M(i,t,n))}var r="2.8.3",i={},s=!0,o=t.documentElement,u="modernizr",a=t.createElement(u),f=a.style,l,c={}.toString,h=" -webkit- -moz- -o- -ms- ".split(" "),p="Webkit Moz O ms",d=p.split(" "),v=p.toLowerCase().split(" "),m={},g={},y={},b=[],w=b.slice,E,S=function(e,n,r,i){var s,a,f,l,c=t.createElement("div"),h=t.body,p=h||t.createElement("body");if(parseInt(r,10))while(r--)f=t.createElement("div"),f.id=i?i[r]:u+(r+1),c.appendChild(f);return s=["&#173;",'<style id="s',u,'">',e,"</style>"].join(""),c.id=u,(h?c:p).innerHTML+=s,p.appendChild(c),h||(p.style.background="",p.style.overflow="hidden",l=o.style.overflow,o.style.overflow="hidden",o.appendChild(p)),a=n(c,e),h?c.parentNode.removeChild(c):(p.parentNode.removeChild(p),o.style.overflow=l),!!a},x=function(t){var n=e.matchMedia||e.msMatchMedia;if(n)return n(t)&&n(t).matches||!1;var r;return S("@media "+t+" { #"+u+" { position: absolute; } }",function(t){r=(e.getComputedStyle?getComputedStyle(t,null):t.currentStyle)["position"]=="absolute"}),r},T={}.hasOwnProperty,N;!L(T,"undefined")&&!L(T.call,"undefined")?N=function(e,t){return T.call(e,t)}:N=function(e,t){return t in e&&L(e.constructor.prototype[t],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError;var r=w.call(arguments,1),i=function(){if(this instanceof i){var e=function(){};e.prototype=n.prototype;var s=new e,o=n.apply(s,r.concat(w.call(arguments)));return Object(o)===o?o:s}return n.apply(t,r.concat(w.call(arguments)))};return i}),m.touch=function(){var n;return"ontouchstart"in e||e.DocumentTouch&&t instanceof DocumentTouch?n=!0:S(["@media (",h.join("touch-enabled),("),u,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(e){n=e.offsetTop===9}),n},m.csstransforms3d=function(){var e=!!_("perspective");return e&&"webkitPerspective"in o.style&&S("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(t,n){e=t.offsetLeft===9&&t.offsetHeight===3}),e},m.csstransitions=function(){return _("transition")};for(var D in m)N(m,D)&&(E=D.toLowerCase(),i[E]=m[D](),b.push((i[E]?"":"no-")+E));return i.addTest=function(e,t){if(typeof e=="object")for(var r in e)N(e,r)&&i.addTest(r,e[r]);else{e=e.toLowerCase();if(i[e]!==n)return i;t=typeof t=="function"?t():t,typeof s!="undefined"&&s&&(o.className+=" "+(t?"":"no-")+e),i[e]=t}return i},C(""),a=l=null,function(e,t){function c(e,t){var n=e.createElement("p"),r=e.getElementsByTagName("head")[0]||e.documentElement;return n.innerHTML="x<style>"+t+"</style>",r.insertBefore(n.lastChild,r.firstChild)}function h(){var e=y.elements;return typeof e=="string"?e.split(" "):e}function p(e){var t=f[e[u]];return t||(t={},a++,e[u]=a,f[a]=t),t}function d(e,n,r){n||(n=t);if(l)return n.createElement(e);r||(r=p(n));var o;return r.cache[e]?o=r.cache[e].cloneNode():s.test(e)?o=(r.cache[e]=r.createElem(e)).cloneNode():o=r.createElem(e),o.canHaveChildren&&!i.test(e)&&!o.tagUrn?r.frag.appendChild(o):o}function v(e,n){e||(e=t);if(l)return e.createDocumentFragment();n=n||p(e);var r=n.frag.cloneNode(),i=0,s=h(),o=s.length;for(;i<o;i++)r.createElement(s[i]);return r}function m(e,t){t.cache||(t.cache={},t.createElem=e.createElement,t.createFrag=e.createDocumentFragment,t.frag=t.createFrag()),e.createElement=function(n){return y.shivMethods?d(n,e,t):t.createElem(n)},e.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+h().join().replace(/[\w\-]+/g,function(e){return t.createElem(e),t.frag.createElement(e),'c("'+e+'")'})+");return n}")(y,t.frag)}function g(e){e||(e=t);var n=p(e);return y.shivCSS&&!o&&!n.hasCSS&&(n.hasCSS=!!c(e,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||m(e,n),e}var n="3.7.0",r=e.html5||{},i=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,s=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,o,u="_html5shiv",a=0,f={},l;(function(){try{var e=t.createElement("a");e.innerHTML="<xyz></xyz>",o="hidden"in e,l=e.childNodes.length==1||function(){t.createElement("a");var e=t.createDocumentFragment();return typeof e.cloneNode=="undefined"||typeof e.createDocumentFragment=="undefined"||typeof e.createElement=="undefined"}()}catch(n){o=!0,l=!0}})();var y={elements:r.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:n,shivCSS:r.shivCSS!==!1,supportsUnknownElements:l,shivMethods:r.shivMethods!==!1,type:"default",shivDocument:g,createElement:d,createDocumentFragment:v};e.html5=y,g(t)}(this,t),i._version=r,i._prefixes=h,i._domPrefixes=v,i._cssomPrefixes=d,i.mq=x,i.testProp=function(e){return O([e])},i.testAllProps=_,i.testStyles=S,i.prefixed=function(e,t,n){return t?_(e,t,n):_(e,"pfx")},o.className=o.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(s?" js "+b.join(" "):""),i}(this,this.document),function(e,t,n){function r(e){return"[object Function]"==d.call(e)}function i(e){return"string"==typeof e}function s(){}function o(e){return!e||"loaded"==e||"complete"==e||"uninitialized"==e}function u(){var e=v.shift();m=1,e?e.t?h(function(){("c"==e.t?k.injectCss:k.injectJs)(e.s,0,e.a,e.x,e.e,1)},0):(e(),u()):m=0}function a(e,n,r,i,s,a,f){function l(t){if(!d&&o(c.readyState)&&(w.r=d=1,!m&&u(),c.onload=c.onreadystatechange=null,t)){"img"!=e&&h(function(){b.removeChild(c)},50);for(var r in T[n])T[n].hasOwnProperty(r)&&T[n][r].onload()}}var f=f||k.errorTimeout,c=t.createElement(e),d=0,g=0,w={t:r,s:n,e:s,a:a,x:f};1===T[n]&&(g=1,T[n]=[]),"object"==e?c.data=n:(c.src=n,c.type=e),c.width=c.height="0",c.onerror=c.onload=c.onreadystatechange=function(){l.call(this,g)},v.splice(i,0,w),"img"!=e&&(g||2===T[n]?(b.insertBefore(c,y?null:p),h(l,f)):T[n].push(c))}function f(e,t,n,r,s){return m=0,t=t||"j",i(e)?a("c"==t?E:w,e,t,this.i++,n,r,s):(v.splice(this.i++,0,e),1==v.length&&u()),this}function l(){var e=k;return e.loader={load:f,i:0},e}var c=t.documentElement,h=e.setTimeout,p=t.getElementsByTagName("script")[0],d={}.toString,v=[],m=0,g="MozAppearance"in c.style,y=g&&!!t.createRange().compareNode,b=y?c:p.parentNode,c=e.opera&&"[object Opera]"==d.call(e.opera),c=!!t.attachEvent&&!c,w=g?"object":c?"script":"img",E=c?"script":w,S=Array.isArray||function(e){return"[object Array]"==d.call(e)},x=[],T={},N={timeout:function(e,t){return t.length&&(e.timeout=t[0]),e}},C,k;k=function(e){function t(e){var e=e.split("!"),t=x.length,n=e.pop(),r=e.length,n={url:n,origUrl:n,prefixes:e},i,s,o;for(s=0;s<r;s++)o=e[s].split("="),(i=N[o.shift()])&&(n=i(n,o));for(s=0;s<t;s++)n=x[s](n);return n}function o(e,i,s,o,u){var a=t(e),f=a.autoCallback;a.url.split(".").pop().split("?").shift(),a.bypass||(i&&(i=r(i)?i:i[e]||i[o]||i[e.split("/").pop().split("?")[0]]),a.instead?a.instead(e,i,s,o,u):(T[a.url]?a.noexec=!0:T[a.url]=1,s.load(a.url,a.forceCSS||!a.forceJS&&"css"==a.url.split(".").pop().split("?").shift()?"c":n,a.noexec,a.attrs,a.timeout),(r(i)||r(f))&&s.load(function(){l(),i&&i(a.origUrl,u,o),f&&f(a.origUrl,u,o),T[a.url]=2})))}function u(e,t){function n(e,n){if(e){if(i(e))n||(f=function(){var e=[].slice.call(arguments);l.apply(this,e),c()}),o(e,f,t,0,u);else if(Object(e)===e)for(p in h=function(){var t=0,n;for(n in e)e.hasOwnProperty(n)&&t++;return t}(),e)e.hasOwnProperty(p)&&(!n&&!--h&&(r(f)?f=function(){var e=[].slice.call(arguments);l.apply(this,e),c()}:f[p]=function(e){return function(){var t=[].slice.call(arguments);e&&e.apply(this,t),c()}}(l[p])),o(e[p],f,t,p,u))}else!n&&c()}var u=!!e.test,a=e.load||e.both,f=e.callback||s,l=f,c=e.complete||s,h,p;n(u?e.yep:e.nope,!!a),a&&n(a)}var a,f,c=this.yepnope.loader;if(i(e))o(e,0,c,0);else if(S(e))for(a=0;a<e.length;a++)f=e[a],i(f)?o(f,0,c,0):S(f)?k(f):Object(f)===f&&u(f,c);else Object(e)===e&&u(e,c)},k.addPrefix=function(e,t){N[e]=t},k.addFilter=function(e){x.push(e)},k.errorTimeout=1e4,null==t.readyState&&t.addEventListener&&(t.readyState="loading",t.addEventListener("DOMContentLoaded",C=function(){t.removeEventListener("DOMContentLoaded",C,0),t.readyState="complete"},0)),e.yepnope=l(),e.yepnope.executeStack=u,e.yepnope.injectJs=function(e,n,r,i,a,f){var l=t.createElement("script"),c,d,i=i||k.errorTimeout;l.src=e;for(d in r)l.setAttribute(d,r[d]);n=f?u:n||s,l.onreadystatechange=l.onload=function(){!c&&o(l.readyState)&&(c=1,n(),l.onload=l.onreadystatechange=null)},h(function(){c||(c=1,n(1))},i),a?l.onload():p.parentNode.insertBefore(l,p)},e.yepnope.injectCss=function(e,n,r,i,o,a){var i=t.createElement("link"),f,n=a?u:n||s;i.href=e,i.rel="stylesheet",i.type="text/css";for(f in r)i.setAttribute(f,r[f]);o||(p.parentNode.insertBefore(i,p),h(n,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};

/**

 * jquery.flipshow.js v1.0.0

 * http://www.codrops.com

 *

 * Licensed under the MIT license.

 * http://www.opensource.org/licenses/mit-license.php

 *

 * Copyright 2013, Codrops

 * http://www.codrops.com

 */

;( function( $, window, undefined ) {



	'use strict';



	// ======================= imagesLoaded Plugin ===============================

	// https://github.com/desandro/imagesloaded



	// $('#my-container').imagesLoaded(myFunction)

	// execute a callback when all images have loaded.

	// needed because .load() doesn't work on cached images



	// callback function gets image collection as argument

	//  this is the container



	// original: mit license. paul irish. 2010.

	// contributors: Oren Solomianik, David DeSandro, Yiannis Chatzikonstantinou



	// blank image data-uri bypasses webkit log warning (thx doug jones)

	// blank image data-uri bypasses webkit log warning (thx doug jones)

	var BLANK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';



	$.fn.imagesLoaded = function( callback ) {

		var $this = this,

			deferred = $.isFunction($.Deferred) ? $.Deferred() : 0,

			hasNotify = $.isFunction(deferred.notify),

			$images = $this.find('img').add( $this.filter('img') ),

			loaded = [],

			proper = [],

			broken = [];



		// Register deferred callbacks

		if ($.isPlainObject(callback)) {

			$.each(callback, function (key, value) {

				if (key === 'callback') {

					callback = value;

				} else if (deferred) {

					deferred[key](value);

				}

			});

		}



		function doneLoading() {

			var $proper = $(proper),

				$broken = $(broken);



			if ( deferred ) {

				if ( broken.length ) {

					deferred.reject( $images, $proper, $broken );

				} else {

					deferred.resolve( $images );

				}

			}



			if ( $.isFunction( callback ) ) {

				callback.call( $this, $images, $proper, $broken );

			}

		}



		function imgLoadedHandler( event ) {

			imgLoaded( event.target, event.type === 'error' );

		}



		function imgLoaded( img, isBroken ) {

			// don't proceed if BLANK image, or image is already loaded

			if ( img.src === BLANK || $.inArray( img, loaded ) !== -1 ) {

				return;

			}



			// store element in loaded images array

			loaded.push( img );



			// keep track of broken and properly loaded images

			if ( isBroken ) {

				broken.push( img );

			} else {

				proper.push( img );

			}



			// cache image and its state for future calls

			$.data( img, 'imagesLoaded', { isBroken: isBroken, src: img.src } );



			// trigger deferred progress method if present

			if ( hasNotify ) {

				deferred.notifyWith( $(img), [ isBroken, $images, $(proper), $(broken) ] );

			}



			// call doneLoading and clean listeners if all images are loaded

			if ( $images.length === loaded.length ) {

				setTimeout( doneLoading );

				$images.unbind( '.imagesLoaded', imgLoadedHandler );

			}

		}



		// if no images, trigger immediately

		if ( !$images.length ) {

			doneLoading();

		} else {

			$images.bind( 'load.imagesLoaded error.imagesLoaded', imgLoadedHandler )

			.each( function( i, el ) {

				var src = el.src;



				// find out if this image has been already checked for status

				// if it was, and src has not changed, call imgLoaded on it

				var cached = $.data( el, 'imagesLoaded' );

				if ( cached && cached.src === src ) {

					imgLoaded( el, cached.isBroken );

					return;

				}



				// if complete is true and browser supports natural sizes, try

				// to check for image status manually

				if ( el.complete && el.naturalWidth !== undefined ) {

					imgLoaded( el, el.naturalWidth === 0 || el.naturalHeight === 0 );

					return;

				}



				// cached images don't fire load sometimes, so we reset src, but only when

				// dealing with IE, or image is complete (loaded) and failed manual check

				// webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f

				if ( el.readyState || el.complete ) {

					el.src = BLANK;

					el.src = src;

				}

			});

		}



		return deferred ? deferred.promise( $this ) : $this;

	};



	// global

	var Modernizr = window.Modernizr;



	$.Flipshow = function( options, element ) {

		this.$el = $( element );

		this._init( options );

	};



	// the options

	$.Flipshow.defaults = {

		// default transition speed (ms)

		speed : 700,

		// default transition easing

		easing : 'ease-out'

	};



	$.Flipshow.prototype = {

		_init : function( options ) {



			// options

			this.options = $.extend( true, {}, $.Flipshow.defaults, options );

			// support for CSS Transitions & 3D transforms

			this.support = Modernizr.csstransitions && Modernizr.csstransforms3d && !(/MSIE (\d+\.\d+);/.test(navigator.userAgent));

			// transition end event name and transform name

			var transEndEventNames = {

					'WebkitTransition' : 'webkitTransitionEnd',

					'MozTransition' : 'transitionend',

					'OTransition' : 'oTransitionEnd',

					'msTransition' : 'MSTransitionEnd',

					'transition' : 'transitionend'

				},

				transformNames = {

					'WebkitTransform' : '-webkit-transform',

					'MozTransform' : '-moz-transform',

					'OTransform' : '-o-transform',

					'msTransform' : '-ms-transform',

					'transform' : 'transform'

				};



			if( this.support ) {

				this.transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ] + '.cbpFWSlider';

				this.transformName = transformNames[ Modernizr.prefixed( 'transform' ) ];

			}

			this.transitionProperties = this.transformName + ' ' + this.options.speed + 'ms ' + this.options.easing;



			// the list of items

			this.$listItems = this.$el.children( 'ul.fc-slides' );

			// the items

			this.$items = this.$listItems.children( 'li' ).hide();

			// total number of items

			this.itemsCount = this.$items.length;

			// current item´s index

			this.current = 0;

			this.$listItems.imagesLoaded( $.proxy( function() {

				// show first item

				this.$items.eq( this.current ).show();

				// add navigation and flipping structure

				if( this.itemsCount > 0 ) {

					this._addNav();

					if( this.support ) {

						this._layout();

					}

				}

			}, this ) );



		},

		_addNav : function() {



			var self = this,

				$navLeft = $( '<div class="fc-left"><span></span><span></span><span></span><i class="fa fa-arrow-left"></i></div>' ),

				$navRight = $( '<div class="fc-right"><span></span><span></span><span></span><i class="fa fa-arrow-right"></i></div>' );



			$( '<nav></nav>' ).append( $navLeft, $navRight ).appendTo( this.$el );



			$navLeft.find( 'span' ).on( 'click.flipshow touchstart.flipshow', function() {

				self._navigate( $( this ), 'left' );

			} );



			$navRight.find( 'span' ).on( 'click.flipshow touchstart.flipshow', function() {

				self._navigate( $( this ), 'right' );

			} );



		},

		_layout : function( $current, $next ) {



			this.$flipFront = $( '<div class="fc-front"><div></div></div>' );

			this.$frontContent = this.$flipFront.children( 'div:first' );

			this.$flipBack = $( '<div class="fc-back"><div></div></div>' );

			this.$backContent = this.$flipBack.children( 'div:first' );

			this.$flipEl = $( '<div class="fc-flip"></div>' ).append( this.$flipFront, this.$flipBack ).hide().appendTo( this.$el );



		},

		_navigate : function( $nav, dir ) {



			if( this.isAnimating && this.support ) {

				return false;

			}

			this.isAnimating = true;



			var $currentItem = this.$items.eq( this.current ).hide();



			if( dir === 'right' ) {

				this.current < this.itemsCount - 1 ? ++this.current : this.current = 0;

			}

			else if( dir === 'left' ) {

				this.current > 0 ? --this.current : this.current = this.itemsCount - 1;

			}



			var $nextItem = this.$items.eq( this.current );



			if( this.support ) {

				this._flip( $currentItem, $nextItem, dir, $nav.index() );

			}

			else {

				$nextItem.show();

			}



		},

		_flip : function( $currentItem, $nextItem, dir, angle ) {



			var transformProperties = '',

				// overlays

				$overlayLight = $( '<div class="fc-overlay-light"></div>' ),

				$overlayDark = $( '<div class="fc-overlay-dark"></div>' );



            if (typeof this.$flipEl == 'undefined')

                return;



			this.$flipEl.css( 'transition', this.transitionProperties );



			this.$flipFront.find( 'div.fc-overlay-light, div.fc-overlay-dark' ).remove();

			this.$flipBack.find( 'div.fc-overlay-light, div.fc-overlay-dark' ).remove();



			if( dir === 'right' ) {

				this.$flipFront.append( $overlayLight );

				this.$flipBack.append( $overlayDark );

				$overlayDark.css( 'opacity', 1 );

			}

			else if( dir === 'left' ) {

				this.$flipFront.append( $overlayDark );

				this.$flipBack.append( $overlayLight );

				$overlayLight.css( 'opacity', 1 );

			}

			var overlayStyle = { transition : 'opacity ' + ( this.options.speed / 1.3 ) + 'ms' };

			$overlayLight.css( overlayStyle );

			$overlayDark.css( overlayStyle );



			switch( angle ) {

				case 0 :

					transformProperties = dir === 'left' ? 'rotate3d(-1,1,0,-179deg) rotate3d(-1,1,0,-1deg)' : 'rotate3d(1,1,0,180deg)';

					break;

				case 1 :

					transformProperties = dir === 'left' ? 'rotate3d(0,1,0,-179deg) rotate3d(0,1,0,-1deg)' : 'rotate3d(0,1,0,180deg)';

					break;

				case 2 :

					transformProperties = dir === 'left' ? 'rotate3d(1,1,0,-179deg) rotate3d(1,1,0,-1deg)' : 'rotate3d(-1,1,0,179deg) rotate3d(-1,1,0,1deg)';

					break;

			}



			this.$flipBack.css( 'transform', transformProperties );



			this.$frontContent.empty().html( $currentItem.html() );

			this.$backContent.empty().html( $nextItem.html() );

			this.$flipEl.show();



			var self = this;

			setTimeout( function() {



				self.$flipEl.css( 'transform', transformProperties );

				$overlayLight.css( 'opacity', dir === 'right' ? 1 : 0 );

				$overlayDark.css( 'opacity', dir === 'right' ? 0 : 1 );

				self.$flipEl.on( self.transEndEventName, function( event ) {

					if( event.target.className === 'fc-overlay-light' || event.target.className === 'fc-overlay-dark' ) return;

					self._ontransitionend( $nextItem );

				} );



			}, 25 );



		},

		_ontransitionend : function( $nextItem ) {

			$nextItem.show();

			this.$flipEl.off( this.transEndEventName ).css( {

				transition : 'none',

				transform : 'none'

			} ).hide();

			this.isAnimating = false;

		}

	};



	var logError = function( message ) {

		if ( window.console ) {

			window.console.error( message );

		}

	};



	$.fn.flipshow = function( options ) {

		if ( typeof options === 'string' ) {

			var args = Array.prototype.slice.call( arguments, 1 );

			this.each(function() {

				var instance = $.data( this, 'flipshow' );

				if ( !instance ) {

					logError( "cannot call methods on flipshow prior to initialization; " +

					"attempted to call method '" + options + "'" );

					return;

				}

				if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {

					logError( "no such method '" + options + "' for flipshow instance" );

					return;

				}

				instance[ options ].apply( instance, args );

			});

		}

		else {

			this.each(function() {

				var instance = $.data( this, 'flipshow' );

				if ( instance ) {

					instance._init();

				}

				else {

					instance = $.data( this, 'flipshow', new $.Flipshow( options, this ) );

				}

			});

		}

		return this;

	};



} )( jQuery, window );

/*! Magnific Popup - v1.1.0 - 2016-02-20
* http://dimsemenov.com/plugins/magnific-popup/
* Copyright (c) 2016 Dmitry Semenov; */
;(function (factory) { 
if (typeof define === 'function' && define.amd) { 
 // AMD. Register as an anonymous module. 
 define(['jquery'], factory); 
 } else if (typeof exports === 'object') { 
 // Node/CommonJS 
 factory(require('jquery')); 
 } else { 
 // Browser globals 
 factory(window.jQuery || window.Zepto); 
 } 
 }(function($) { 

/*>>core*/
/**
 * 
 * Magnific Popup Core JS file
 * 
 */


/**
 * Private static constants
 */
var CLOSE_EVENT = 'Close',
	BEFORE_CLOSE_EVENT = 'BeforeClose',
	AFTER_CLOSE_EVENT = 'AfterClose',
	BEFORE_APPEND_EVENT = 'BeforeAppend',
	MARKUP_PARSE_EVENT = 'MarkupParse',
	OPEN_EVENT = 'Open',
	CHANGE_EVENT = 'Change',
	NS = 'mfp',
	EVENT_NS = '.' + NS,
	READY_CLASS = 'mfp-ready',
	REMOVING_CLASS = 'mfp-removing',
	PREVENT_CLOSE_CLASS = 'mfp-prevent-close';


/**
 * Private vars 
 */
/*jshint -W079 */
var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this'
	MagnificPopup = function(){},
	_isJQ = !!(window.jQuery),
	_prevStatus,
	_window = $(window),
	_document,
	_prevContentType,
	_wrapClasses,
	_currPopupType;


/**
 * Private functions
 */
var _mfpOn = function(name, f) {
		mfp.ev.on(NS + name + EVENT_NS, f);
	},
	_getEl = function(className, appendTo, html, raw) {
		var el = document.createElement('div');
		el.className = 'mfp-'+className;
		if(html) {
			el.innerHTML = html;
		}
		if(!raw) {
			el = $(el);
			if(appendTo) {
				el.appendTo(appendTo);
			}
		} else if(appendTo) {
			appendTo.appendChild(el);
		}
		return el;
	},
	_mfpTrigger = function(e, data) {
		mfp.ev.triggerHandler(NS + e, data);

		if(mfp.st.callbacks) {
			// converts "mfpEventName" to "eventName" callback and triggers it if it's present
			e = e.charAt(0).toLowerCase() + e.slice(1);
			if(mfp.st.callbacks[e]) {
				mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]);
			}
		}
	},
	_getCloseBtn = function(type) {
		if(type !== _currPopupType || !mfp.currTemplate.closeBtn) {
			mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) );
			_currPopupType = type;
		}
		return mfp.currTemplate.closeBtn;
	},
	// Initialize Magnific Popup only when called at least once
	_checkInstance = function() {
		if(!$.magnificPopup.instance) {
			/*jshint -W020 */
			mfp = new MagnificPopup();
			mfp.init();
			$.magnificPopup.instance = mfp;
		}
	},
	// CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
	supportsTransitions = function() {
		var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist
			v = ['ms','O','Moz','Webkit']; // 'v' for vendor

		if( s['transition'] !== undefined ) {
			return true; 
		}
			
		while( v.length ) {
			if( v.pop() + 'Transition' in s ) {
				return true;
			}
		}
				
		return false;
	};



/**
 * Public functions
 */
MagnificPopup.prototype = {

	constructor: MagnificPopup,

	/**
	 * Initializes Magnific Popup plugin. 
	 * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed
	 */
	init: function() {
		var appVersion = navigator.appVersion;
		mfp.isLowIE = mfp.isIE8 = document.all && !document.addEventListener;
		mfp.isAndroid = (/android/gi).test(appVersion);
		mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion);
		mfp.supportsTransition = supportsTransitions();

		// We disable fixed positioned lightbox on devices that don't handle it nicely.
		// If you know a better way of detecting this - let me know.
		mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) );
		_document = $(document);

		mfp.popupsCache = {};
	},

	/**
	 * Opens popup
	 * @param  data [description]
	 */
	open: function(data) {

		var i;

		if(data.isObj === false) { 
			// convert jQuery collection to array to avoid conflicts later
			mfp.items = data.items.toArray();

			mfp.index = 0;
			var items = data.items,
				item;
			for(i = 0; i < items.length; i++) {
				item = items[i];
				if(item.parsed) {
					item = item.el[0];
				}
				if(item === data.el[0]) {
					mfp.index = i;
					break;
				}
			}
		} else {
			mfp.items = $.isArray(data.items) ? data.items : [data.items];
			mfp.index = data.index || 0;
		}

		// if popup is already opened - we just update the content
		if(mfp.isOpen) {
			mfp.updateItemHTML();
			return;
		}
		
		mfp.types = []; 
		_wrapClasses = '';
		if(data.mainEl && data.mainEl.length) {
			mfp.ev = data.mainEl.eq(0);
		} else {
			mfp.ev = _document;
		}

		if(data.key) {
			if(!mfp.popupsCache[data.key]) {
				mfp.popupsCache[data.key] = {};
			}
			mfp.currTemplate = mfp.popupsCache[data.key];
		} else {
			mfp.currTemplate = {};
		}



		mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data ); 
		mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos;

		if(mfp.st.modal) {
			mfp.st.closeOnContentClick = false;
			mfp.st.closeOnBgClick = false;
			mfp.st.showCloseBtn = false;
			mfp.st.enableEscapeKey = false;
		}
		

		// Building markup
		// main containers are created only once
		if(!mfp.bgOverlay) {

			// Dark overlay
			mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() {
				mfp.close();
			});

			mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) {
				if(mfp._checkIfClose(e.target)) {
					mfp.close();
				}
			});

			mfp.container = _getEl('container', mfp.wrap);
		}

		mfp.contentContainer = _getEl('content');
		if(mfp.st.preloader) {
			mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading);
		}


		// Initializing modules
		var modules = $.magnificPopup.modules;
		for(i = 0; i < modules.length; i++) {
			var n = modules[i];
			n = n.charAt(0).toUpperCase() + n.slice(1);
			mfp['init'+n].call(mfp);
		}
		_mfpTrigger('BeforeOpen');


		if(mfp.st.showCloseBtn) {
			// Close button
			if(!mfp.st.closeBtnInside) {
				mfp.wrap.append( _getCloseBtn() );
			} else {
				_mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
					values.close_replaceWith = _getCloseBtn(item.type);
				});
				_wrapClasses += ' mfp-close-btn-in';
			}
		}

		if(mfp.st.alignTop) {
			_wrapClasses += ' mfp-align-top';
		}

	

		if(mfp.fixedContentPos) {
			mfp.wrap.css({
				overflow: mfp.st.overflowY,
				overflowX: 'hidden',
				overflowY: mfp.st.overflowY
			});
		} else {
			mfp.wrap.css({ 
				top: _window.scrollTop(),
				position: 'absolute'
			});
		}
		if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) {
			mfp.bgOverlay.css({
				height: _document.height(),
				position: 'absolute'
			});
		}

		

		if(mfp.st.enableEscapeKey) {
			// Close on ESC key
			_document.on('keyup' + EVENT_NS, function(e) {
				if(e.keyCode === 27) {
					mfp.close();
				}
			});
		}

		_window.on('resize' + EVENT_NS, function() {
			mfp.updateSize();
		});


		if(!mfp.st.closeOnContentClick) {
			_wrapClasses += ' mfp-auto-cursor';
		}
		
		if(_wrapClasses)
			mfp.wrap.addClass(_wrapClasses);


		// this triggers recalculation of layout, so we get it once to not to trigger twice
		var windowHeight = mfp.wH = _window.height();

		
		var windowStyles = {};

		if( mfp.fixedContentPos ) {
            if(mfp._hasScrollBar(windowHeight)){
                var s = mfp._getScrollbarSize();
                if(s) {
                    if ($('html').hasClass('browser-rtl'))
                        windowStyles.marginLeft = s;
                    else
                        windowStyles.marginRight = s;
                }
            }
        }

		if(mfp.fixedContentPos) {
			if(!mfp.isIE7) {
				windowStyles.overflow = 'hidden';
			} else {
				// ie7 double-scroll bug
				$('body, html').css('overflow', 'hidden');
			}
		}

		
		
		var classesToadd = mfp.st.mainClass;
		if(mfp.isIE7) {
			classesToadd += ' mfp-ie7';
		}
		if(classesToadd) {
			mfp._addClassToMFP( classesToadd );
		}

		// add content
		mfp.updateItemHTML();

		_mfpTrigger('BuildControls');

		// remove scrollbar, add margin e.t.c
		$('html').css(windowStyles);
		
		// add everything to DOM
		mfp.bgOverlay.add(mfp.wrap).prependTo( mfp.st.prependTo || $(document.body) );

		// Save last focused element
		mfp._lastFocusedEl = document.activeElement;
		
		// Wait for next cycle to allow CSS transition
		setTimeout(function() {
			
			if(mfp.content) {
				mfp._addClassToMFP(READY_CLASS);
				mfp._setFocus();
			} else {
				// if content is not defined (not loaded e.t.c) we add class only for BG
				mfp.bgOverlay.addClass(READY_CLASS);
			}
			
			// Trap the focus in popup
			_document.on('focusin' + EVENT_NS, mfp._onFocusIn);

		}, 16);

		mfp.isOpen = true;
		mfp.updateSize(windowHeight);
		_mfpTrigger(OPEN_EVENT);

		return data;
	},

	/**
	 * Closes the popup
	 */
	close: function() {
		if(!mfp.isOpen) return;
		_mfpTrigger(BEFORE_CLOSE_EVENT);

		mfp.isOpen = false;
		// for CSS3 animation
		if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition )  {
			mfp._addClassToMFP(REMOVING_CLASS);
			setTimeout(function() {
				mfp._close();
			}, mfp.st.removalDelay);
		} else {
			mfp._close();
		}
	},

	/**
	 * Helper for close() function
	 */
	_close: function() {
		_mfpTrigger(CLOSE_EVENT);

		var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' ';

		mfp.bgOverlay.detach();
		mfp.wrap.detach();
		mfp.container.empty();

		if(mfp.st.mainClass) {
			classesToRemove += mfp.st.mainClass + ' ';
		}

		mfp._removeClassFromMFP(classesToRemove);

		if(mfp.fixedContentPos) {
            var windowStyles;
            if ($('html').hasClass('browser-rtl'))
                windowStyles = {marginLeft: ''};
            else
                windowStyles = {marginRight: ''};
			if(mfp.isIE7) {
				$('body, html').css('overflow', '');
			} else {
				windowStyles.overflow = '';
			}
			$('html').css(windowStyles);
		}
		
		_document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS);
		mfp.ev.off(EVENT_NS);

		// clean up DOM elements that aren't removed
		mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style');
		mfp.bgOverlay.attr('class', 'mfp-bg');
		mfp.container.attr('class', 'mfp-container');

		// remove close button from target element
		if(mfp.st.showCloseBtn &&
		(!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) {
			if(mfp.currTemplate.closeBtn)
				mfp.currTemplate.closeBtn.detach();
		}


		if(mfp.st.autoFocusLast && mfp._lastFocusedEl) {
			$(mfp._lastFocusedEl).focus(); // put tab focus back
		}
		mfp.currItem = null;	
		mfp.content = null;
		mfp.currTemplate = null;
		mfp.prevHeight = 0;

		_mfpTrigger(AFTER_CLOSE_EVENT);
	},
	
	updateSize: function(winHeight) {

		if(mfp.isIOS) {
			// fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2
			var zoomLevel = document.documentElement.clientWidth / window.innerWidth;
			var height = window.innerHeight * zoomLevel;
			mfp.wrap.css('height', height);
			mfp.wH = height;
		} else {
			mfp.wH = winHeight || _window.height();
		}
		// Fixes #84: popup incorrectly positioned with position:relative on body
		if(!mfp.fixedContentPos) {
			mfp.wrap.css('height', mfp.wH);
		}

		_mfpTrigger('Resize');

	},

	/**
	 * Set content of popup based on current index
	 */
	updateItemHTML: function() {
		var item = mfp.items[mfp.index];

		// Detach and perform modifications
		mfp.contentContainer.detach();

		if(mfp.content)
			mfp.content.detach();

		if(!item.parsed) {
			item = mfp.parseEl( mfp.index );
		}

		var type = item.type;

		_mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]);
		// BeforeChange event works like so:
		// _mfpOn('BeforeChange', function(e, prevType, newType) { });

		mfp.currItem = item;

		if(!mfp.currTemplate[type]) {
			var markup = mfp.st[type] ? mfp.st[type].markup : false;

			// allows to modify markup
			_mfpTrigger('FirstMarkupParse', markup);

			if(markup) {
				mfp.currTemplate[type] = $(markup);
			} else {
				// if there is no markup found we just define that template is parsed
				mfp.currTemplate[type] = true;
			}
		}

		if(_prevContentType && _prevContentType !== item.type) {
			mfp.container.removeClass('mfp-'+_prevContentType+'-holder');
		}

		var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]);
		mfp.appendContent(newContent, type);

		item.preloaded = true;

		_mfpTrigger(CHANGE_EVENT, item);
		_prevContentType = item.type;

		// Append container back after its content changed
		mfp.container.prepend(mfp.contentContainer);

		_mfpTrigger('AfterChange');
	},


	/**
	 * Set HTML content of popup
	 */
	appendContent: function(newContent, type) {
		mfp.content = newContent;

		if(newContent) {
			if(mfp.st.showCloseBtn && mfp.st.closeBtnInside &&
				mfp.currTemplate[type] === true) {
				// if there is no markup, we just append close button element inside
				if(!mfp.content.find('.mfp-close').length) {
					mfp.content.append(_getCloseBtn());
				}
			} else {
				mfp.content = newContent;
			}
		} else {
			mfp.content = '';
		}

		_mfpTrigger(BEFORE_APPEND_EVENT);
		mfp.container.addClass('mfp-'+type+'-holder');

		mfp.contentContainer.append(mfp.content);
	},


	/**
	 * Creates Magnific Popup data object based on given data
	 * @param  {int} index Index of item to parse
	 */
	parseEl: function(index) {
		var item = mfp.items[index],
			type;

		if(item.tagName) {
			item = { el: $(item) };
		} else {
			type = item.type;
			item = { data: item, src: item.src };
		}

		if(item.el) {
			var types = mfp.types;

			// check for 'mfp-TYPE' class
			for(var i = 0; i < types.length; i++) {
				if( item.el.hasClass('mfp-'+types[i]) ) {
					type = types[i];
					break;
				}
			}

			item.src = item.el.attr('data-mfp-src');
			if(!item.src) {
				item.src = item.el.attr('href');
			}
		}

		item.type = type || mfp.st.type || 'inline';
		item.index = index;
		item.parsed = true;
		mfp.items[index] = item;
		_mfpTrigger('ElementParse', item);

		return mfp.items[index];
	},


	/**
	 * Initializes single popup or a group of popups
	 */
	addGroup: function(el, options) {
		var eHandler = function(e) {
			e.mfpEl = this;
			mfp._openClick(e, el, options);
		};

		if(!options) {
			options = {};
		}

		var eName = 'click.magnificPopup';
		options.mainEl = el;

		if(options.items) {
			options.isObj = true;
			el.off(eName).on(eName, eHandler);
		} else {
			options.isObj = false;
			if(options.delegate) {
				el.off(eName).on(eName, options.delegate , eHandler);
			} else {
				options.items = el;
				el.off(eName).on(eName, eHandler);
			}
		}
	},
	_openClick: function(e, el, options) {
		var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick;


		if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey ) ) {
			return;
		}

		var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn;

		if(disableOn) {
			if($.isFunction(disableOn)) {
				if( !disableOn.call(mfp) ) {
					return true;
				}
			} else { // else it's number
				if( _window.width() < disableOn ) {
					return true;
				}
			}
		}

		if(e.type) {
			e.preventDefault();

			// This will prevent popup from closing if element is inside and popup is already opened
			if(mfp.isOpen) {
				e.stopPropagation();
			}
		}

		options.el = $(e.mfpEl);
		if(options.delegate) {
			options.items = el.find(options.delegate);
		}
		mfp.open(options);
	},


	/**
	 * Updates text on preloader
	 */
	updateStatus: function(status, text) {

		if(mfp.preloader) {
			if(_prevStatus !== status) {
				mfp.container.removeClass('mfp-s-'+_prevStatus);
			}

			if(!text && status === 'loading') {
				text = mfp.st.tLoading;
			}

			var data = {
				status: status,
				text: text
			};
			// allows to modify status
			_mfpTrigger('UpdateStatus', data);

			status = data.status;
			text = data.text;

			mfp.preloader.html(text);

			mfp.preloader.find('a').on('click', function(e) {
				e.stopImmediatePropagation();
			});

			mfp.container.addClass('mfp-s-'+status);
			_prevStatus = status;
		}
	},


	/*
		"Private" helpers that aren't private at all
	 */
	// Check to close popup or not
	// "target" is an element that was clicked
	_checkIfClose: function(target) {

		if($(target).hasClass(PREVENT_CLOSE_CLASS)) {
			return;
		}

		var closeOnContent = mfp.st.closeOnContentClick;
		var closeOnBg = mfp.st.closeOnBgClick;

		if(closeOnContent && closeOnBg) {
			return true;
		} else {

			// We close the popup if click is on close button or on preloader. Or if there is no content.
			if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) {
				return true;
			}

			// if click is outside the content
			if(  (target !== mfp.content[0] && !$.contains(mfp.content[0], target))  ) {
				if(closeOnBg) {
					// last check, if the clicked element is in DOM, (in case it's removed onclick)
					if( $.contains(document, target) ) {
						return true;
					}
				}
			} else if(closeOnContent) {
				return true;
			}

		}
		return false;
	},
	_addClassToMFP: function(cName) {
		mfp.bgOverlay.addClass(cName);
		mfp.wrap.addClass(cName);
	},
	_removeClassFromMFP: function(cName) {
		this.bgOverlay.removeClass(cName);
		mfp.wrap.removeClass(cName);
	},
	_hasScrollBar: function(winHeight) {
		return (  (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) );
	},
	_setFocus: function() {
		(mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus();
	},
	_onFocusIn: function(e) {
		if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) {
			mfp._setFocus();
			return false;
		}
	},
	_parseMarkup: function(template, values, item) {
		var arr;
		if(item.data) {
			values = $.extend(item.data, values);
		}
		_mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] );

		$.each(values, function(key, value) {
			if(value === undefined || value === false) {
				return true;
			}
			arr = key.split('_');
			if(arr.length > 1) {
				var el = template.find(EVENT_NS + '-'+arr[0]);

				if(el.length > 0) {
					var attr = arr[1];
					if(attr === 'replaceWith') {
						if(el[0] !== value[0]) {
							el.replaceWith(value);
						}
					} else if(attr === 'img') {
						if(el.is('img')) {
							el.attr('src', value);
						} else {
							el.replaceWith( $('<img>').attr('src', value).attr('class', el.attr('class')) );
						}
					} else {
						el.attr(arr[1], value);
					}
				}

			} else {
				template.find(EVENT_NS + '-'+key).html(value);
			}
		});
	},

	_getScrollbarSize: function() {
		// thx David
		if(mfp.scrollbarSize === undefined) {
			var scrollDiv = document.createElement("div");
			scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';
			document.body.appendChild(scrollDiv);
			mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;
			document.body.removeChild(scrollDiv);
		}
		return mfp.scrollbarSize;
	}

}; /* MagnificPopup core prototype end */




/**
 * Public static functions
 */
$.magnificPopup = {
	instance: null,
	proto: MagnificPopup.prototype,
	modules: [],

	open: function(options, index) {
		_checkInstance();

		if(!options) {
			options = {};
		} else {
			options = $.extend(true, {}, options);
		}

		options.isObj = true;
		options.index = index || 0;
		return this.instance.open(options);
	},

	close: function() {
		return $.magnificPopup.instance && $.magnificPopup.instance.close();
	},

	registerModule: function(name, module) {
		if(module.options) {
			$.magnificPopup.defaults[name] = module.options;
		}
		$.extend(this.proto, module.proto);
		this.modules.push(name);
	},

	defaults: {

		// Info about options is in docs:
		// http://dimsemenov.com/plugins/magnific-popup/documentation.html#options

		disableOn: 0,

		key: null,

		midClick: false,

		mainClass: '',

		preloader: true,

		focus: '', // CSS selector of input to focus after popup is opened

		closeOnContentClick: false,

		closeOnBgClick: true,

		closeBtnInside: true,

		showCloseBtn: true,

		enableEscapeKey: true,

		modal: false,

		alignTop: false,

		removalDelay: 0,

		prependTo: null,

		fixedContentPos: 'auto',

		fixedBgPos: 'auto',

		overflowY: 'auto',

		closeMarkup: '<button title="%title%" type="button" class="mfp-close">&#215;</button>',

		tClose: 'Close (Esc)',

		tLoading: 'Loading...',

		autoFocusLast: true

	}
};



$.fn.magnificPopup = function(options) {
	_checkInstance();

	var jqEl = $(this);

	// We call some API method of first param is a string
	if (typeof options === "string" ) {

		if(options === 'open') {
			var items,
				itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup,
				index = parseInt(arguments[1], 10) || 0;

			if(itemOpts.items) {
				items = itemOpts.items[index];
			} else {
				items = jqEl;
				if(itemOpts.delegate) {
					items = items.find(itemOpts.delegate);
				}
				items = items.eq( index );
			}
			mfp._openClick({mfpEl:items}, jqEl, itemOpts);
		} else {
			if(mfp.isOpen)
				mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1));
		}

	} else {
		// clone options obj
		options = $.extend(true, {}, options);

		/*
		 * As Zepto doesn't support .data() method for objects
		 * and it works only in normal browsers
		 * we assign "options" object directly to the DOM element. FTW!
		 */
		if(_isJQ) {
			jqEl.data('magnificPopup', options);
		} else {
			jqEl[0].magnificPopup = options;
		}

		mfp.addGroup(jqEl, options);

	}
	return jqEl;
};

/*>>core*/

/*>>inline*/

var INLINE_NS = 'inline',
	_hiddenClass,
	_inlinePlaceholder,
	_lastInlineElement,
	_putInlineElementsBack = function() {
		if(_lastInlineElement) {
			_inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach();
			_lastInlineElement = null;
		}
	};

$.magnificPopup.registerModule(INLINE_NS, {
	options: {
		hiddenClass: 'hide', // will be appended with `mfp-` prefix
		markup: '',
		tNotFound: 'Content not found'
	},
	proto: {

		initInline: function() {
			mfp.types.push(INLINE_NS);

			_mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() {
				_putInlineElementsBack();
			});
		},

		getInline: function(item, template) {

			_putInlineElementsBack();

			if(item.src) {
				var inlineSt = mfp.st.inline,
					el = $(item.src);

				if(el.length) {

					// If target element has parent - we replace it with placeholder and put it back after popup is closed
					var parent = el[0].parentNode;
					if(parent && parent.tagName) {
						if(!_inlinePlaceholder) {
							_hiddenClass = inlineSt.hiddenClass;
							_inlinePlaceholder = _getEl(_hiddenClass);
							_hiddenClass = 'mfp-'+_hiddenClass;
						}
						// replace target inline element with placeholder
						_lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass);
					}

					mfp.updateStatus('ready');
				} else {
					mfp.updateStatus('error', inlineSt.tNotFound);
					el = $('<div>');
				}

				item.inlineElement = el;
				return el;
			}

			mfp.updateStatus('ready');
			mfp._parseMarkup(template, {}, item);
			return template;
		}
	}
});

/*>>inline*/

/*>>ajax*/
var AJAX_NS = 'ajax',
	_ajaxCur,
	_removeAjaxCursor = function() {
		if(_ajaxCur) {
			$(document.body).removeClass(_ajaxCur);
		}
	},
	_destroyAjaxRequest = function() {
		_removeAjaxCursor();
		if(mfp.req) {
			mfp.req.abort();
		}
	};

$.magnificPopup.registerModule(AJAX_NS, {

	options: {
		settings: null,
		cursor: 'mfp-ajax-cur',
		tError: '<a href="%url%">The content</a> could not be loaded.'
	},

	proto: {
		initAjax: function() {
			mfp.types.push(AJAX_NS);
			_ajaxCur = mfp.st.ajax.cursor;

			_mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest);
			_mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest);
		},
		getAjax: function(item) {

			if(_ajaxCur) {
				$(document.body).addClass(_ajaxCur);
			}

			mfp.updateStatus('loading');

			var opts = $.extend({
				url: item.src,
				success: function(data, textStatus, jqXHR) {
					var temp = {
						data:data,
						xhr:jqXHR
					};

					_mfpTrigger('ParseAjax', temp);

					mfp.appendContent( $(temp.data), AJAX_NS );

					item.finished = true;

					_removeAjaxCursor();

					mfp._setFocus();

					setTimeout(function() {
						mfp.wrap.addClass(READY_CLASS);
					}, 16);

					mfp.updateStatus('ready');

					_mfpTrigger('AjaxContentAdded');
				},
				error: function() {
					_removeAjaxCursor();
					item.finished = item.loadError = true;
					mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src));
				}
			}, mfp.st.ajax.settings);

			mfp.req = $.ajax(opts);

			return '';
		}
	}
});

/*>>ajax*/

/*>>image*/
var _imgInterval,
	_getTitle = function(item) {
		if(item.data && item.data.title !== undefined)
			return item.data.title;

		var src = mfp.st.image.titleSrc;

		if(src) {
			if($.isFunction(src)) {
				return src.call(mfp, item);
			} else if(item.el) {
				return item.el.attr(src) || '';
			}
		}
		return '';
	};

$.magnificPopup.registerModule('image', {

	options: {
		markup: '<div class="mfp-figure">'+
					'<div class="mfp-close"></div>'+
					'<figure>'+
						'<div class="mfp-img"></div>'+
						'<figcaption>'+
							'<div class="mfp-bottom-bar">'+
								'<div class="mfp-title"></div>'+
								'<div class="mfp-counter"></div>'+
							'</div>'+
						'</figcaption>'+
					'</figure>'+
				'</div>',
		cursor: 'mfp-zoom-out-cur',
		titleSrc: 'title',
		verticalFit: true,
		tError: '<a href="%url%">The image</a> could not be loaded.'
	},

	proto: {
		initImage: function() {
			var imgSt = mfp.st.image,
				ns = '.image';

			mfp.types.push('image');

			_mfpOn(OPEN_EVENT+ns, function() {
				if(mfp.currItem.type === 'image' && imgSt.cursor) {
					$(document.body).addClass(imgSt.cursor);
				}
			});

			_mfpOn(CLOSE_EVENT+ns, function() {
				if(imgSt.cursor) {
					$(document.body).removeClass(imgSt.cursor);
				}
				_window.off('resize' + EVENT_NS);
			});

			_mfpOn('Resize'+ns, mfp.resizeImage);
			if(mfp.isLowIE) {
				_mfpOn('AfterChange', mfp.resizeImage);
			}
		},
		resizeImage: function() {
			var item = mfp.currItem;
			if(!item || !item.img) return;

			if(mfp.st.image.verticalFit) {
				var decr = 0;
				// fix box-sizing in ie7/8
				if(mfp.isLowIE) {
					decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10);
				}
				item.img.css('max-height', mfp.wH-decr);
			}
		},
		_onImageHasSize: function(item) {
			if(item.img) {

				item.hasSize = true;

				if(_imgInterval) {
					clearInterval(_imgInterval);
				}

				item.isCheckingImgSize = false;

				_mfpTrigger('ImageHasSize', item);

				if(item.imgHidden) {
					if(mfp.content)
						mfp.content.removeClass('mfp-loading');

					item.imgHidden = false;
				}

			}
		},

		/**
		 * Function that loops until the image has size to display elements that rely on it asap
		 */
		findImageSize: function(item) {

			var counter = 0,
				img = item.img[0],
				mfpSetInterval = function(delay) {

					if(_imgInterval) {
						clearInterval(_imgInterval);
					}
					// decelerating interval that checks for size of an image
					_imgInterval = setInterval(function() {
						if(img.naturalWidth > 0) {
							mfp._onImageHasSize(item);
							return;
						}

						if(counter > 200) {
							clearInterval(_imgInterval);
						}

						counter++;
						if(counter === 3) {
							mfpSetInterval(10);
						} else if(counter === 40) {
							mfpSetInterval(50);
						} else if(counter === 100) {
							mfpSetInterval(500);
						}
					}, delay);
				};

			mfpSetInterval(1);
		},

		getImage: function(item, template) {

			var guard = 0,

				// image load complete handler
				onLoadComplete = function() {
					if(item) {
						if (item.img[0].complete) {
							item.img.off('.mfploader');

							if(item === mfp.currItem){
								mfp._onImageHasSize(item);

								mfp.updateStatus('ready');
							}

							item.hasSize = true;
							item.loaded = true;

							_mfpTrigger('ImageLoadComplete');

						}
						else {
							// if image complete check fails 200 times (20 sec), we assume that there was an error.
							guard++;
							if(guard < 200) {
								setTimeout(onLoadComplete,100);
							} else {
								onLoadError();
							}
						}
					}
				},

				// image error handler
				onLoadError = function() {
					if(item) {
						item.img.off('.mfploader');
						if(item === mfp.currItem){
							mfp._onImageHasSize(item);
							mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
						}

						item.hasSize = true;
						item.loaded = true;
						item.loadError = true;
					}
				},
				imgSt = mfp.st.image;


			var el = template.find('.mfp-img');
			if(el.length) {
				var img = document.createElement('img');
				img.className = 'mfp-img';
				if(item.el && item.el.find('img').length) {
					img.alt = item.el.find('img').attr('alt');
				}
				item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError);
				img.src = item.src;

				// without clone() "error" event is not firing when IMG is replaced by new IMG
				// TODO: find a way to avoid such cloning
				if(el.is('img')) {
					item.img = item.img.clone();
				}

				img = item.img[0];
				if(img.naturalWidth > 0) {
					item.hasSize = true;
				} else if(!img.width) {
					item.hasSize = false;
				}
			}

			mfp._parseMarkup(template, {
				title: _getTitle(item),
				img_replaceWith: item.img
			}, item);

			mfp.resizeImage();

			if(item.hasSize) {
				if(_imgInterval) clearInterval(_imgInterval);

				if(item.loadError) {
					template.addClass('mfp-loading');
					mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) );
				} else {
					template.removeClass('mfp-loading');
					mfp.updateStatus('ready');
				}
				return template;
			}

			mfp.updateStatus('loading');
			item.loading = true;

			if(!item.hasSize) {
				item.imgHidden = true;
				template.addClass('mfp-loading');
				mfp.findImageSize(item);
			}

			return template;
		}
	}
});

/*>>image*/

/*>>zoom*/
var hasMozTransform,
	getHasMozTransform = function() {
		if(hasMozTransform === undefined) {
			hasMozTransform = document.createElement('p').style.MozTransform !== undefined;
		}
		return hasMozTransform;
	};

$.magnificPopup.registerModule('zoom', {

	options: {
		enabled: false,
		easing: 'ease-in-out',
		duration: 300,
		opener: function(element) {
			return element.is('img') ? element : element.find('img');
		}
	},

	proto: {

		initZoom: function() {
			var zoomSt = mfp.st.zoom,
				ns = '.zoom',
				image;

			if(!zoomSt.enabled || !mfp.supportsTransition) {
				return;
			}

			var duration = zoomSt.duration,
				getElToAnimate = function(image) {
					var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'),
						transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing,
						cssObj = {
							position: 'fixed',
							zIndex: 9999,
							left: 0,
							top: 0,
							'-webkit-backface-visibility': 'hidden'
						},
						t = 'transition';

					cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition;

					newImg.css(cssObj);
					return newImg;
				},
				showMainContent = function() {
					mfp.content.css('visibility', 'visible');
				},
				openTimeout,
				animatedImg;

			_mfpOn('BuildControls'+ns, function() {
				if(mfp._allowZoom()) {

					clearTimeout(openTimeout);
					mfp.content.css('visibility', 'hidden');

					// Basically, all code below does is clones existing image, puts in on top of the current one and animated it

					image = mfp._getItemToZoom();

					if(!image) {
						showMainContent();
						return;
					}

					animatedImg = getElToAnimate(image);

					animatedImg.css( mfp._getOffset() );

					mfp.wrap.append(animatedImg);

					openTimeout = setTimeout(function() {
						animatedImg.css( mfp._getOffset( true ) );
						openTimeout = setTimeout(function() {

							showMainContent();

							setTimeout(function() {
								animatedImg.remove();
								image = animatedImg = null;
								_mfpTrigger('ZoomAnimationEnded');
							}, 16); // avoid blink when switching images

						}, duration); // this timeout equals animation duration

					}, 16); // by adding this timeout we avoid short glitch at the beginning of animation


					// Lots of timeouts...
				}
			});
			_mfpOn(BEFORE_CLOSE_EVENT+ns, function() {
				if(mfp._allowZoom()) {

					clearTimeout(openTimeout);

					mfp.st.removalDelay = duration;

					if(!image) {
						image = mfp._getItemToZoom();
						if(!image) {
							return;
						}
						animatedImg = getElToAnimate(image);
					}

					animatedImg.css( mfp._getOffset(true) );
					mfp.wrap.append(animatedImg);
					mfp.content.css('visibility', 'hidden');

					setTimeout(function() {
						animatedImg.css( mfp._getOffset() );
					}, 16);
				}

			});

			_mfpOn(CLOSE_EVENT+ns, function() {
				if(mfp._allowZoom()) {
					showMainContent();
					if(animatedImg) {
						animatedImg.remove();
					}
					image = null;
				}
			});
		},

		_allowZoom: function() {
			return mfp.currItem.type === 'image';
		},

		_getItemToZoom: function() {
			if(mfp.currItem.hasSize) {
				return mfp.currItem.img;
			} else {
				return false;
			}
		},

		// Get element postion relative to viewport
		_getOffset: function(isLarge) {
			var el;
			if(isLarge) {
				el = mfp.currItem.img;
			} else {
				el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem);
			}

			var offset = el.offset();
			var paddingTop = parseInt(el.css('padding-top'),10);
			var paddingBottom = parseInt(el.css('padding-bottom'),10);
			offset.top -= ( $(window).scrollTop() - paddingTop );


			/*

			Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa.

			 */
			var obj = {
				width: el.width(),
				// fix Zepto height+padding issue
				height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop
			};

			// I hate to do this, but there is no another option
			if( getHasMozTransform() ) {
				obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)';
			} else {
				obj.left = offset.left;
				obj.top = offset.top;
			}
			return obj;
		}

	}
});



/*>>zoom*/

/*>>iframe*/

var IFRAME_NS = 'iframe',
	_emptyPage = '//about:blank',

	_fixIframeBugs = function(isShowing) {
		if(mfp.currTemplate[IFRAME_NS]) {
			var el = mfp.currTemplate[IFRAME_NS].find('iframe');
			if(el.length) {
				// reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug
				if(!isShowing) {
					el[0].src = _emptyPage;
				}

				// IE8 black screen bug fix
				if(mfp.isIE8) {
					el.css('display', isShowing ? 'block' : 'none');
				}
			}
		}
	};

$.magnificPopup.registerModule(IFRAME_NS, {

	options: {
		markup: '<div class="mfp-iframe-scaler">'+
					'<div class="mfp-close"></div>'+
					'<iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe>'+
				'</div>',

		srcAction: 'iframe_src',

		// we don't care and support only one default type of URL by default
		patterns: {
			youtube: {
				index: 'youtube.com',
				id: 'v=',
				src: '//www.youtube.com/embed/%id%?autoplay=1'
			},
			vimeo: {
				index: 'vimeo.com/',
				id: '/',
				src: '//player.vimeo.com/video/%id%?autoplay=1'
			},
			gmaps: {
				index: '//maps.google.',
				src: '%id%&output=embed'
			}
		}
	},

	proto: {
		initIframe: function() {
			mfp.types.push(IFRAME_NS);

			_mfpOn('BeforeChange', function(e, prevType, newType) {
				if(prevType !== newType) {
					if(prevType === IFRAME_NS) {
						_fixIframeBugs(); // iframe if removed
					} else if(newType === IFRAME_NS) {
						_fixIframeBugs(true); // iframe is showing
					}
				}// else {
					// iframe source is switched, don't do anything
				//}
			});

			_mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
				_fixIframeBugs();
			});
		},

		getIframe: function(item, template) {
			var embedSrc = item.src;
			var iframeSt = mfp.st.iframe;

			$.each(iframeSt.patterns, function() {
				if(embedSrc.indexOf( this.index ) > -1) {
					if(this.id) {
						if(typeof this.id === 'string') {
							embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length);
						} else {
							embedSrc = this.id.call( this, embedSrc );
						}
					}
					embedSrc = this.src.replace('%id%', embedSrc );
					return false; // break;
				}
			});

			var dataObj = {};
			if(iframeSt.srcAction) {
				dataObj[iframeSt.srcAction] = embedSrc;
			}
			mfp._parseMarkup(template, dataObj, item);

			mfp.updateStatus('ready');

			return template;
		}
	}
});



/*>>iframe*/

/*>>gallery*/
/**
 * Get looped index depending on number of slides
 */
var _getLoopedId = function(index) {
		var numSlides = mfp.items.length;
		if(index > numSlides - 1) {
			return index - numSlides;
		} else  if(index < 0) {
			return numSlides + index;
		}
		return index;
	},
	_replaceCurrTotal = function(text, curr, total) {
		return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total);
	};

$.magnificPopup.registerModule('gallery', {

	options: {
		enabled: false,
		arrowMarkup: '<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',
		preload: [0,2],
		navigateByImgClick: true,
		arrows: true,

		tPrev: 'Previous (Left arrow key)',
		tNext: 'Next (Right arrow key)',
		tCounter: '%curr% of %total%'
	},

	proto: {
		initGallery: function() {

			var gSt = mfp.st.gallery,
				ns = '.mfp-gallery';

			mfp.direction = true; // true - next, false - prev

			if(!gSt || !gSt.enabled ) return false;

			_wrapClasses += ' mfp-gallery';

			_mfpOn(OPEN_EVENT+ns, function() {

				if(gSt.navigateByImgClick) {
					mfp.wrap.on('click'+ns, '.mfp-img', function() {
						if(mfp.items.length > 1) {
							mfp.next();
							return false;
						}
					});
				}

				_document.on('keydown'+ns, function(e) {
					if (e.keyCode === 37) {
						mfp.prev();
					} else if (e.keyCode === 39) {
						mfp.next();
					}
				});
			});

			_mfpOn('UpdateStatus'+ns, function(e, data) {
				if(data.text) {
					data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length);
				}
			});

			_mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) {
				var l = mfp.items.length;
				values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : '';
			});

			_mfpOn('BuildControls' + ns, function() {
				if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) {
					var markup = gSt.arrowMarkup,
						arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS),
						arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS);

					arrowLeft.click(function() {
						mfp.prev();
					});
					arrowRight.click(function() {
						mfp.next();
					});

					mfp.container.append(arrowLeft.add(arrowRight));
				}
			});

			_mfpOn(CHANGE_EVENT+ns, function() {
				if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout);

				mfp._preloadTimeout = setTimeout(function() {
					mfp.preloadNearbyImages();
					mfp._preloadTimeout = null;
				}, 16);
			});


			_mfpOn(CLOSE_EVENT+ns, function() {
				_document.off(ns);
				mfp.wrap.off('click'+ns);
				mfp.arrowRight = mfp.arrowLeft = null;
			});

		},
		next: function() {
			mfp.direction = true;
			mfp.index = _getLoopedId(mfp.index + 1);
			mfp.updateItemHTML();
		},
		prev: function() {
			mfp.direction = false;
			mfp.index = _getLoopedId(mfp.index - 1);
			mfp.updateItemHTML();
		},
		goTo: function(newIndex) {
			mfp.direction = (newIndex >= mfp.index);
			mfp.index = newIndex;
			mfp.updateItemHTML();
		},
		preloadNearbyImages: function() {
			var p = mfp.st.gallery.preload,
				preloadBefore = Math.min(p[0], mfp.items.length),
				preloadAfter = Math.min(p[1], mfp.items.length),
				i;

			for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) {
				mfp._preloadItem(mfp.index+i);
			}
			for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) {
				mfp._preloadItem(mfp.index-i);
			}
		},
		_preloadItem: function(index) {
			index = _getLoopedId(index);

			if(mfp.items[index].preloaded) {
				return;
			}

			var item = mfp.items[index];
			if(!item.parsed) {
				item = mfp.parseEl( index );
			}

			_mfpTrigger('LazyLoad', item);

			if(item.type === 'image') {
				item.img = $('<img class="mfp-img" />').on('load.mfploader', function() {
					item.hasSize = true;
				}).on('error.mfploader', function() {
					item.hasSize = true;
					item.loadError = true;
					_mfpTrigger('LazyLoadError', item);
				}).attr('src', item.src);
			}


			item.preloaded = true;
		}
	}
});

/*>>gallery*/

/*>>retina*/

var RETINA_NS = 'retina';

$.magnificPopup.registerModule(RETINA_NS, {
	options: {
		replaceSrc: function(item) {
			return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; });
		},
		ratio: 1 // Function or number.  Set to 1 to disable.
	},
	proto: {
		initRetina: function() {
			if(window.devicePixelRatio > 1) {

				var st = mfp.st.retina,
					ratio = st.ratio;

				ratio = !isNaN(ratio) ? ratio : ratio();

				if(ratio > 1) {
					_mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) {
						item.img.css({
							'max-width': item.img[0].naturalWidth / ratio,
							'width': '100%'
						});
					});
					_mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) {
						item.src = st.replaceSrc(item, ratio);
					});
				}
			}

		}
	}
});

/*>>retina*/
 _checkInstance(); }));

/*!

 *         ,/

 *       ,'/

 *     ,' /

 *   ,'  /_____,

 * .'____    ,'

 *      /  ,'

 *     / ,'

 *    /,'

 *   /'

 *

 * Selectric ϟ v1.9.6 (Mar 24 2016) - http://lcdsantos.github.io/jQuery-Selectric/

 *

 * Copyright (c) 2016 Leonardo Santos; MIT License

 *

 */



(function(factory) {

    /* istanbul ignore next */

    if (typeof define === 'function' && define.amd) {

        define(['jquery'], factory);

    } else if (typeof module === 'object' && module.exports) {

        // Node/CommonJS

        module.exports = function( root, jQuery ) {

            if ( jQuery === undefined ) {

                if ( typeof window !== 'undefined' ) {

                    jQuery = require('jquery');

                }

                else {

                    jQuery = require('jquery')(root);

                }

            }

            factory(jQuery);

            return jQuery;

        };

    } else {

        // Browser globals

        factory(jQuery);

    }

}(function($) {



    'use strict';



    var pluginName = 'selectric',

        classList = 'Input Items Open Disabled TempShow HideSelect Wrapper Hover Responsive Above Scroll Group GroupLabel',

        bindSufix = '.sl',

        defaults = {

            onChange: function(elm) { $(elm).change(); },

            maxHeight: 300,

            keySearchTimeout: 500,

            arrowButtonMarkup: '<b class="button">&#x25be;</b>',

            disableOnMobile: true,

            openOnHover: false,

            hoverIntentTimeout: 500,

            expandToItemText: false,

            responsive: false,

            preventWindowScroll: true,

            inheritOriginalWidth: false,

            allowWrap: true,

            customClass: {

                prefix: pluginName,

                camelCase: false

            },

            optionsItemBuilder: '{text}', // function(itemData, element, index)

            labelBuilder: '{text}' // function(currItem)

        },

        hooks = {

            add: function(callbackName, hookName, fn) {

                if ( !this[callbackName] )

                    this[callbackName] = {};



                this[callbackName][hookName] = fn;

            },

            remove: function(callbackName, hookName) {

                delete this[callbackName][hookName];

            }

        },

        _utils = {

            // Replace diacritics

            replaceDiacritics: function(s) {

                // /[\340-\346]/g, // a

                // /[\350-\353]/g, // e

                // /[\354-\357]/g, // i

                // /[\362-\370]/g, // o

                // /[\371-\374]/g, // u

                // /[\361]/g,      // n

                // /[\347]/g,      // c

                // /[\377]/g       // y

                var d = '40-46 50-53 54-57 62-70 71-74 61 47 77'.replace(/\d+/g, '\\3$&').split(' '),

                    k = d.length;



                while (k--)

                    s = s.toLowerCase().replace(RegExp('[' + d[k] + ']', 'g'), 'aeiouncy'.charAt(k));



                return s;

            },

            // https://gist.github.com/atesgoral/984375

            format: function(f) {var a=arguments;return(""+f).replace(/{(\d+|(\w+))}/g,function(s,i,p) {return p&&a[1]?a[1][p]:a[i]})},

            nextEnabledItem: function(selectItems, selected) {

                while ( selectItems[ selected = (selected + 1) % selectItems.length ].disabled ) {}

                return selected;

            },

            previousEnabledItem: function(selectItems, selected) {

                while ( selectItems[ selected = (selected > 0 ? selected : selectItems.length) - 1 ].disabled ) {}

                return selected;

            },

            toDash: function(str) {

                return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();

            },

            triggerCallback: function(fn, scope) {

                var elm = scope.element,

                    func = scope.options['on' + fn];



                if ( $.isFunction(func) )

                    func.call(elm, elm, scope);



                if ( hooks[fn] ) {

                    $.each(hooks[fn], function() {

                        this.call(elm, elm, scope);

                    });

                }



                $(elm).trigger(pluginName + '-' + _utils.toDash(fn), scope);

            }

        },

        $doc = $(document),

        $win = $(window),

        Selectric = function(element, opts) {

            var _this = this,

                $original = $(element),

                $input, $items, $itemsScroll, $wrapper, $label, $outerWrapper, $li,

                isOpen = false,

                isEnabled = false,

                selected,

                currValue,

                itemsHeight,

                itemsInnerHeight,

                finalWidth,

                optionsLength,

                eventTriggers,

                isMobile = /android|ip(hone|od|ad)/i.test(navigator.userAgent),

                tabindex = $original.prop('tabindex'),

                labelBuilder;



            function _init(opts) {

                _this.options = $.extend(true, {}, defaults, _this.options, opts);

                _this.classes = {};

                _this.element = element;



                _utils.triggerCallback('BeforeInit', _this);



                // Disable on mobile browsers

                if ( _this.options.disableOnMobile && isMobile ) {

                    _this.disableOnMobile = true;

                    return;

                }



                // Preserve data

                _destroy(true);



                // Generate classNames for elements

                var customClass   = _this.options.customClass,

                    postfixes     = classList.split(' '),

                    originalWidth = $original.width();



                $.each(postfixes, function(i, currClass) {

                    var c = customClass.prefix + currClass;

                    _this.classes[currClass.toLowerCase()] = customClass.camelCase ? c : _utils.toDash(c);

                });



                $input        = $('<input/>', { 'class': _this.classes.input, 'readonly': isMobile });

                $items        = $('<div/>',   { 'class': _this.classes.items, 'tabindex': -1 });

                $itemsScroll  = $('<div/>',   { 'class': _this.classes.scroll });

                $wrapper      = $('<div/>',   { 'class': customClass.prefix, 'html': _this.options.arrowButtonMarkup });

                $label        = $('<p class="label"/>');

                $outerWrapper = $original.wrap('<div>').parent().append($wrapper.prepend($label), $items, $input);



                eventTriggers = {

                    open    : _open,

                    close   : _close,

                    destroy : _destroy,

                    refresh : _refresh,

                    init    : _init

                };



                $original.on(eventTriggers).wrap('<div class="' + _this.classes.hideselect + '">');

                $.extend(_this, eventTriggers);



                labelBuilder = _this.options.labelBuilder;



                if ( _this.options.inheritOriginalWidth && originalWidth > 0 )

                    $outerWrapper.width(originalWidth);



                _populate();

            }



            // Generate options markup and event binds

            function _populate() {

                _this.items = [];



                var $options = $original.children(),

                    _$li = '<ul>',

                    $justOptions = $original.find('option'),

                    selectedIndex = $justOptions.index($justOptions.filter(':selected')),

                    currIndex = 0;



                currValue = (selected = ~selectedIndex ? selectedIndex : 0);



                if ( optionsLength = $options.length ) {

                    // Build options markup

                    $options.each(function() {

                        var $elm = $(this);



                        if ( $elm.is('optgroup') ) {

                            var groupDisabled = $elm.prop('disabled'),

                                $children = $elm.children();



                            _$li += _utils.format('<ul class="{1}"><li class="{2}">{3}</li>',

                                $.trim([_this.classes.group, groupDisabled ? 'disabled' : '', $elm.prop('class')].join(' ')),

                                _this.classes.grouplabel,

                                $elm.prop('label')

                            );



                            if ( groupDisabled ) {

                                $children.prop('disabled', true);

                            }



                            $children.each(buildOption);



                            _$li += '</ul>';

                        } else {

                            buildOption.call($elm);

                        }



                        function buildOption() {

                            var $elm = $(this),

                                optionText = $elm.html(),

                                selectDisabled = $elm.prop('disabled'),

                                itemBuilder = _this.options.optionsItemBuilder;



                            _this.items[currIndex] = {

                                element  : $elm,

                                value    : $elm.val(),

                                text     : optionText,

                                slug     : _utils.replaceDiacritics(optionText),

                                disabled : selectDisabled

                            };



                            _$li += _utils.format('<li data-index="{1}" class="{2}">{3}</li>',

                                currIndex,

                                $.trim([currIndex == currValue ? 'selected' : '', currIndex == optionsLength - 1 ? 'last' : '', selectDisabled ? 'disabled' : ''].join(' ')),

                                $.isFunction(itemBuilder) ? itemBuilder(_this.items[currIndex], $elm, currIndex) : _utils.format(itemBuilder, _this.items[currIndex])

                            );



                            currIndex++;

                        }

                    });



                    $items.append( $itemsScroll.html(_$li + '</ul>') );



                    $label.html(

                        $.isFunction(labelBuilder) ? labelBuilder(_this.items[currValue]) : _utils.format(labelBuilder, _this.items[currValue])

                    )

                }



                $wrapper.add($original).add($outerWrapper).add($input).off(bindSufix);



                $outerWrapper.prop('class', [

                    _this.classes.wrapper,

                    $original.prop('class').replace(/\S+/g, _this.options.customClass.prefix + '-$&'),

                    _this.options.responsive ? _this.classes.responsive : ''

                ].join(' '));



                if ( !$original.prop('disabled') ) {

                    isEnabled = true;



                    // Not disabled, so... Removing disabled class and bind hover

                    $outerWrapper.removeClass(_this.classes.disabled).on('mouseenter' + bindSufix + ' mouseleave' + bindSufix, function(e) {

                        $(this).toggleClass(_this.classes.hover);



                        // Delay close effect when openOnHover is true

                        if ( _this.options.openOnHover ) {

                            clearTimeout(_this.closeTimer);

                            e.type == 'mouseleave' ? _this.closeTimer = setTimeout(_close, _this.options.hoverIntentTimeout) : _open();

                        }

                    });



                    // Toggle open/close

                    $wrapper.on('click' + bindSufix, function(e) {

                        isOpen ? _close() : _open(e);

                    });



                    $input

                        .prop({

                            tabindex: tabindex,

                            disabled: false

                        })

                        .on('keypress' + bindSufix, _handleSystemKeys)

                        .on('keydown' + bindSufix, function(e) {

                            _handleSystemKeys(e);



                            // Clear search

                            clearTimeout(_this.resetStr);

                            _this.resetStr = setTimeout(function() {

                                $input.val('');

                            }, _this.options.keySearchTimeout);



                            var key = e.keyCode || e.which;



                            // If it's a directional key

                            // 37 => Left

                            // 38 => Up

                            // 39 => Right

                            // 40 => Down

                            if ( key > 36 && key < 41 ) {

                                if ( !_this.options.allowWrap ) {

                                    if ( (key < 39 && selected == 0) || (key > 38 && (selected + 1) == _this.items.length) ) {

                                        return;

                                    }

                                }



                                _select(_utils[(key < 39 ? 'previous' : 'next') + 'EnabledItem'](_this.items, selected));

                            }

                        })

                        .on('focusin' + bindSufix, function(e) {

                            isOpen || _open(e);

                        })

                        .on('oninput' in $input[0] ? 'input' : 'keyup', function() {

                            if ( $input.val().length ) {

                                // Search in select options

                                $.each(_this.items, function(i, elm) {

                                    if ( RegExp('^' + $input.val(), 'i').test(elm.slug) && !elm.disabled ) {

                                        _select(i);

                                        return false;

                                    }

                                });

                            }

                        });



                    $original.prop('tabindex', false);



                    // Remove styles from items box

                    // Fix incorrect height when refreshed is triggered with fewer options

                    $li = $('li', $items.removeAttr('style')).on({

                        // Prevent <input> blur on Chrome

                        mousedown: function(e) {

                            e.preventDefault();

                            e.stopPropagation();

                        },

                        click: function() {

                            // The second parameter is to close the box after click

                            _select($(this).data('index'), true);



                            // Chrome doesn't close options box if select is wrapped with a label

                            // We need to 'return false' to avoid that

                            return false;

                        }

                    }).filter('[data-index]');

                } else {

                    $outerWrapper.addClass(_this.classes.disabled);

                    $input.prop('disabled', true);

                }



                _utils.triggerCallback('Init', _this);

            }



            function _refresh() {

                _utils.triggerCallback('Refresh', _this);

                _populate();

            }



            // Behavior when system keys is pressed

            function _handleSystemKeys(e) {

                var key = e.keyCode || e.which;



                if ( key == 13 ) {

                    e.preventDefault();

                }



                // Tab / Enter / ESC

                if ( /^(9|13|27)$/.test(key) ) {

                    e.stopPropagation();

                    _select(selected, true);

                }

            }



            // Set options box width/height

            function _calculateOptionsDimensions() {

                // Calculate options box height

                // Set a temporary class on the hidden parent of the element

                var hiddenChildren = $items.closest(':visible').children(':hidden').addClass(_this.classes.tempshow),

                    maxHeight = _this.options.maxHeight,

                    itemsWidth = $items.outerWidth(),

                    wrapperWidth = $wrapper.outerWidth() - (itemsWidth - $items.width());



                // Set the dimensions, minimum is wrapper width, expand for long items if option is true

                if ( !_this.options.expandToItemText || wrapperWidth > itemsWidth )

                    finalWidth = wrapperWidth;

                else {

                    // Make sure the scrollbar width is included

                    $items.css('overflow', 'scroll');



                    // Set a really long width for $outerWrapper

                    $outerWrapper.width(9e4);

                    finalWidth = $items.width();

                    // Set scroll bar to auto

                    $items.css('overflow', '');

                    $outerWrapper.width('');

                }



                $items.width(finalWidth).height() > maxHeight && $items.height(maxHeight);



                // Remove the temporary class

                hiddenChildren.removeClass(_this.classes.tempshow);

            }



            // Open the select options box

            function _open(e) {

                _utils.triggerCallback('BeforeOpen', _this);



                if ( e ) {

                    e.preventDefault();

                    e.stopPropagation();

                }



                if ( isEnabled ) {

                    _calculateOptionsDimensions();



                    // Find any other opened instances of select and close it

                    $('.' + _this.classes.hideselect, '.' + _this.classes.open).children()[pluginName]('close');



                    isOpen = true;

                    itemsHeight = $items.outerHeight();

                    itemsInnerHeight = $items.height();



                    // Toggle options box visibility

                    $outerWrapper.addClass(_this.classes.open);



                    // Give dummy input focus

                    $input.val('');

                    e && e.type !== 'focusin' && $input.focus();



                    $doc.on('click' + bindSufix, _close).on('scroll' + bindSufix, _isInViewport);

                    _isInViewport();



                    // Prevent window scroll when using mouse wheel inside items box

                    if ( _this.options.preventWindowScroll ) {

                        $doc.on('mousewheel' + bindSufix + ' DOMMouseScroll' + bindSufix, '.' + _this.classes.scroll, function(e) {

                            var orgEvent = e.originalEvent,

                                scrollTop = $(this).scrollTop(),

                                deltaY = 0;



                            if ( 'detail'      in orgEvent ) { deltaY = orgEvent.detail * -1; }

                            if ( 'wheelDelta'  in orgEvent ) { deltaY = orgEvent.wheelDelta;  }

                            if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }

                            if ( 'deltaY'      in orgEvent ) { deltaY = orgEvent.deltaY * -1; }



                            if ( scrollTop == (this.scrollHeight - itemsInnerHeight) && deltaY < 0 || scrollTop == 0 && deltaY > 0 ) {

                                e.preventDefault();

                            }

                        });

                    }



                    _detectItemVisibility(selected);



                    _utils.triggerCallback('Open', _this);

                }

            }



            // Detect is the options box is inside the window

            function _isInViewport() {

                var scrollTop = $win.scrollTop();

                var winHeight = $win.height();

                var uiPosX = $outerWrapper.offset().top;

                var uiHeight = $outerWrapper.outerHeight();



                var fitsDown = (uiPosX + uiHeight + itemsHeight) <= (scrollTop + winHeight);

                var fitsAbove = (uiPosX - itemsHeight) > scrollTop;



                // If it does not fit below, only render it

                // above it fit's there.

                // It's acceptable that the user needs to

                // scroll the viewport to see the cut off UI

                var renderAbove = !fitsDown && fitsAbove;



                $outerWrapper.toggleClass(_this.classes.above, renderAbove);

            }



            // Close the select options box

            function _close() {

                _utils.triggerCallback('BeforeClose', _this);



                if ( currValue != selected ) {

                    _utils.triggerCallback('BeforeChange', _this);



                    var text = _this.items[selected].text;



                    // Apply changed value to original select

                    $original

                        .prop('selectedIndex', currValue = selected)

                        .data('value', text);



                    // Change label text

                    $label.html(

                        $.isFunction(labelBuilder) ? labelBuilder(_this.items[selected]) : _utils.format(labelBuilder, _this.items[selected])

                    )



                    _utils.triggerCallback('Change', _this);

                }



                // Remove custom events on document

                $doc.off(bindSufix);



                // Remove visible class to hide options box

                $outerWrapper.removeClass(_this.classes.open);



                isOpen = false;



                _utils.triggerCallback('Close', _this);

            }



            // Select option

            function _select(index, close) {

                // Parameter index is required

                if ( index == undefined ) {

                    return;

                }



                // If element is disabled, can't select it

                if ( !_this.items[index].disabled ) {

                    // If 'close' is false (default), the options box won't close after

                    // each selected item, this is necessary for keyboard navigation

                    $li

                        .removeClass('selected')

                        .eq(selected = index)

                        .addClass('selected');



                    _detectItemVisibility(index);

                    close && _close();

                }

            }



            // Detect if currently selected option is visible and scroll the options box to show it

            function _detectItemVisibility(index) {

                var liHeight = $li.eq(index).outerHeight(),

                    liTop = $li[index].offsetTop,

                    itemsScrollTop = $itemsScroll.scrollTop(),

                    scrollT = liTop + liHeight * 2;



                $itemsScroll.scrollTop(

                    scrollT > itemsScrollTop + itemsHeight ? scrollT - itemsHeight :

                        liTop - liHeight < itemsScrollTop ? liTop - liHeight :

                            itemsScrollTop

                );

            }



            // Unbind and remove

            function _destroy(preserveData) {

                if ( isEnabled ) {

                    $items.add($wrapper).add($input).remove();

                    !preserveData && $original.removeData(pluginName).removeData('value');

                    $original.prop('tabindex', tabindex).off(bindSufix).off(eventTriggers).unwrap().unwrap();

                    isEnabled = false;

                }

            }



            _init(opts);

        };



    // A really lightweight plugin wrapper around the constructor,

    // preventing against multiple instantiations

    $.fn[pluginName] = function(args) {

        return this.each(function() {

            var data = $.data(this, pluginName);



            if ( data && !data.disableOnMobile )

                (''+args === args && data[args]) ? data[args]() : data.init(args);

            else

                $.data(this, pluginName, new Selectric(this, args));

        });

    };



    $.fn[pluginName].hooks = hooks;



}));